summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: f9237e1)
raw | patch | inline | side by side (parent: f9237e1)
author | stefan <stefan@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Mon, 23 Feb 2009 15:31:29 +0000 (15:31 +0000) | ||
committer | stefan <stefan@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Mon, 23 Feb 2009 15:31:29 +0000 (15:31 +0000) |
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/roundup/trunk@4161 57a73879-2fb5-44c3-a270-3262357dd7e2
134 files changed:
index b911541c3c48b20d0af5817f88195549ccd290c6..66b1e3500d8f169919f3436d09804fbcce8d405f 100644 (file)
--- a/demo.py
+++ b/demo.py
backend = sys.argv[-2]
else:
backend = 'anydbm'
- install_demo(home, backend, os.path.join('templates', 'classic'))
+ install_demo(home, backend, os.path.join('share', 'roundup', 'templates', 'classic'))
run_demo(home)
if __name__ == '__main__':
diff --git a/setup.py b/setup.py
index 27d533de624900485dc3d4ae739048c4f2d44965..3a0209762d63fa4e66390c17e5056259b382919d 100644 (file)
--- a/setup.py
+++ b/setup.py
# add the templates to the data files lists
from roundup.init import listTemplates
- templates = [t['path'] for t in listTemplates('templates').values()]
+ templates = [t['path'] for t in listTemplates(os.path.join('share','roundup','templates')).values()]
for tdir in templates:
# scan for data files
for idir in '. detectors extensions html'.split():
diff --git a/share/roundup/templates/classic/.cvsignore b/share/roundup/templates/classic/.cvsignore
--- /dev/null
@@ -0,0 +1,4 @@
+*.pyc
+*.pyo
+htmlbase.py
+*.cover
diff --git a/share/roundup/templates/classic/TEMPLATE-INFO.txt b/share/roundup/templates/classic/TEMPLATE-INFO.txt
--- /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/share/roundup/templates/classic/detectors/.cvsignore b/share/roundup/templates/classic/detectors/.cvsignore
--- /dev/null
@@ -0,0 +1,3 @@
+*.pyc
+*.pyo
+*.cover
diff --git a/share/roundup/templates/classic/detectors/messagesummary.py b/share/roundup/templates/classic/detectors/messagesummary.py
--- /dev/null
@@ -0,0 +1,19 @@
+#$Id: messagesummary.py,v 1.2 2007-04-03 06:47:21 a1s 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'], config=db.config)
+ 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/share/roundup/templates/classic/detectors/nosyreaction.py b/share/roundup/templates/classic/detectors/nosyreaction.py
--- /dev/null
@@ -0,0 +1,143 @@
+#
+# 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.4 2005-04-04 08:47:14 richard Exp $
+
+import sets
+
+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_nosy = sets.Set()
+ 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:
+ current_nosy.add(value)
+
+ # 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
+ current_nosy.add(value)
+
+ new_nosy = sets.Set(current_nosy)
+
+ # 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:
+ new_nosy.add(assignedto_id)
+
+ # 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
+ oldmessages = cl.get(nodeid, 'messages')
+ 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')
+ new_nosy.add(authid)
+
+ # add on the recipients of the message
+ if add_recips in ok:
+ for recipient in msg.get(msgid, 'recipients'):
+ new_nosy.add(recipient)
+
+ if current_nosy != new_nosy:
+ # that's it, save off the new nosy list
+ newvalues['nosy'] = list(new_nosy)
+
+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/share/roundup/templates/classic/detectors/statusauditor.py b/share/roundup/templates/classic/detectors/statusauditor.py
--- /dev/null
@@ -0,0 +1,85 @@
+# 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.5 2004-03-27 00:01:48 richard Exp $
+
+def chatty(db, cl, nodeid, newvalues):
+ ''' If the issue is currently 'unread', 'resolved', 'done-cbb' or None,
+ 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'):
+ 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'):
+ # 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 + [None]:
+ # 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
+
+ # get the unread state ID
+ try:
+ unread_id = db.status.lookup('unread')
+ except KeyError:
+ # no unread state, ignore all this stuff
+ return
+
+ # ok, do it
+ newvalues['status'] = unread_id
+
+
+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/share/roundup/templates/classic/detectors/userauditor.py b/share/roundup/templates/classic/detectors/userauditor.py
--- /dev/null
@@ -0,0 +1,94 @@
+# Copyright (c) 2003 Richard Jones (richard@mechanicalcat.net)
+#
+# 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: userauditor.py,v 1.9 2007-09-12 21:11:13 jpend Exp $
+
+import re
+
+# regular expression thanks to: http://www.regular-expressions.info/email.html
+# this is the "99.99% solution for syntax only".
+email_regexp = (r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*", r"(localhost|(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9]))")
+email_rfc = re.compile('^' + email_regexp[0] + '@' + email_regexp[1] + '$', re.IGNORECASE)
+email_local = re.compile('^' + email_regexp[0] + '$', re.IGNORECASE)
+
+def valid_address(address):
+ ''' If we see an @-symbol in the address then check against the full
+ RFC syntax. Otherwise it is a local-only address so only check
+ the local part of the RFC syntax.
+ '''
+ if '@' in address:
+ return email_rfc.match(address)
+ else:
+ return email_local.match(address)
+
+def get_addresses(user):
+ ''' iterate over all known addresses in a newvalues dict
+ this takes of the address/alterate_addresses handling
+ '''
+ if user.has_key('address'):
+ yield user['address']
+ if user.get('alternate_addresses', None):
+ for address in user['alternate_addresses'].split('\n'):
+ yield address
+
+def audit_user_fields(db, cl, nodeid, newvalues):
+ ''' Make sure user properties are valid.
+
+ - email address is syntactically valid
+ - email address is unique
+ - roles specified exist
+ - timezone is valid
+ '''
+
+ for address in get_addresses(newvalues):
+ if not valid_address(address):
+ raise ValueError, 'Email address syntax is invalid'
+
+ check_main = db.user.stringFind(address=address)
+ # make sure none of the alts are owned by anyone other than us (x!=nodeid)
+ check_alts = [x for x in db.user.filter(None, {'alternate_addresses' : address}) if x != nodeid]
+ if check_main or check_alts:
+ raise ValueError, 'Email address %s already in use' % address
+
+ for rolename in [r.lower().strip() for r in newvalues.get('roles', '').split(',')]:
+ if rolename and not db.security.role.has_key(rolename):
+ raise ValueError, 'Role "%s" does not exist'%rolename
+
+ tz = newvalues.get('timezone', None)
+ if tz:
+ # if they set a new timezone validate the timezone by attempting to
+ # use it before we store it to the db.
+ import roundup.date
+ import datetime
+ try:
+ TZ = roundup.date.get_timezone(tz)
+ dt = datetime.datetime.now()
+ local = TZ.localize(dt).utctimetuple()
+ except IOError:
+ raise ValueError, 'Timezone "%s" does not exist' % tz
+ except ValueError:
+ raise ValueError, 'Timezone "%s" exceeds valid range [-23...23]' % tz
+
+def init(db):
+ # fire before changes are made
+ db.user.audit('set', audit_user_fields)
+ db.user.audit('create', audit_user_fields)
+
+# vim: sts=4 sw=4 et si
diff --git a/share/roundup/templates/classic/extensions/README.txt b/share/roundup/templates/classic/extensions/README.txt
--- /dev/null
@@ -0,0 +1,6 @@
+This directory is for tracker extensions:
+
+- CGI Actions
+- Templating functions
+
+See the customisation doc for more information.
diff --git a/share/roundup/templates/classic/html/_generic.404.html b/share/roundup/templates/classic/html/_generic.404.html
--- /dev/null
@@ -0,0 +1,9 @@
+<html>
+<head>
+<title>Item Not Found</title>
+</head>
+
+<body>
+There is no <span tal:content="context/_classname" /> with id <span tal:content="context/id"/>
+</body>
+</html>
diff --git a/share/roundup/templates/classic/html/_generic.calendar.html b/share/roundup/templates/classic/html/_generic.calendar.html
--- /dev/null
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="@@file/style.css" />
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8;" />
+ <title tal:content="string:Roundup Calendar"></title>
+ <script language="Javascript"
+ type="text/javascript"
+ tal:content="structure string:
+ // this is the name of the field in the original form that we're working on
+ form = window.opener.document.${request/form/form/value};
+ field = '${request/form/property/value}';" >
+ </script>
+ </head>
+ <body class="body"
+ tal:content="structure python:utils.html_calendar(request)">
+ </body>
+</html>
diff --git a/share/roundup/templates/classic/html/_generic.collision.html b/share/roundup/templates/classic/html/_generic.collision.html
--- /dev/null
@@ -0,0 +1,16 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title" i18n:translate=""
+ ><span tal:replace="python:context._classname.capitalize()"
+ i18n:name="class" /> Edit Collision - <span i18n:name="tracker"
+ tal:replace="config/TRACKER_NAME" /></title>
+<tal:block metal:fill-slot="body_title" i18n:translate=""
+ ><span tal:replace="python:context._classname.capitalize()"
+ i18n:name="class" /> Edit Collision</tal:block>
+
+<td class="content" metal:fill-slot="content" i18n:translate="
+ There has been a collision. Another user updated this node
+ while you were editing. Please <a href='${context}'>reload</a>
+ the node and review your edits.
+"><span tal:replace="context/designator" i18n:name="context" />
+</td>
+</tal:block>
diff --git a/share/roundup/templates/classic/html/_generic.help-empty.html b/share/roundup/templates/classic/html/_generic.help-empty.html
--- /dev/null
@@ -0,0 +1,8 @@
+<html>
+ <head>
+ <title>Empty page (no search performed yet)</title>
+ </head>
+ <body>
+ <p i18n:translate="">Please specify your search parameters!</p>
+ </body>
+</html>
diff --git a/share/roundup/templates/classic/html/_generic.help-list.html b/share/roundup/templates/classic/html/_generic.help-list.html
--- /dev/null
@@ -0,0 +1,83 @@
+<!-- $Id: _generic.help-list.html,v 1.2 2008-03-01 08:18:07 richard Exp $ vim: sw=2 ts=8 et
+--><html tal:define="vok context/is_view_ok">
+ <head>
+ <title>Search result for user helper</title>
+ <link rel="stylesheet" type="text/css" href="@@file/style.css" />
+ <script language="Javascript" type="text/javascript"
+ tal:content="structure string:<!--
+ // this is the name of the field in the original form that we're working on
+ form = parent.opener.document.${request/form/form/value};
+ field = '${request/form/property/value}';
+ //-->"></script>
+ <script src="@@file/help_controls.js" type="text/javascript"></script>
+<script type="text/javascript"><!--
+var text_field = parent.submit.document.frm_help.text_preview;
+//--></script>
+ </head>
+ <body>
+ <pre tal:content="request/env/QUERY_STRING" tal:condition=false />
+
+ <p tal:condition="not:vok" i18n:translate="">You are not
+ allowed to view this page.</p>
+
+ <tal:if condition="context/is_view_ok">
+ <tal:def define="batch request/batch;">
+ <form name=dummyform>
+ <table width="100%"
+ tal:define="template string:help-list"
+ metal:use-macro="templates/help/macros/batch_navi"
+ >
+ <tr class="navigation">
+ <th>
+ <a href="#"><< previous</a>
+ </th>
+ <th i18n:translate="">1..25 out of 50
+ </th>
+ <th>
+ <a href="#">next >></a>
+ </th>
+ </tr>
+ </table>
+
+ <form name=dummyform>
+ <table class="classhelp"
+ tal:define="
+ props python:request.form['properties'].value.split(',');
+ legend templates/help/macros/legend;
+ "><thead>
+ <tr metal:use-macro="legend">
+ <th> <b>x</b></th>
+ <th tal:repeat="prop props" tal:content="prop" i18n:translate=""></th>
+ </tr>
+ </thead>
+ <tfoot tal:condition=true>
+ <tr metal:use-macro="legend" />
+ </tfoot>
+ <tbody>
+ <tr tal:repeat="item batch">
+ <tal:block tal:define="attr python:item[props[0]]" >
+ <td>
+ <input name="check"
+ onclick="switch_val(text_field, this);" type="checkbox"
+ tal:attributes="value attr; id string:id_$attr" />
+ </td>
+ <td tal:repeat="prop props">
+ <label class="classhelp-label"
+ tal:attributes="for string:id_$attr"
+ tal:content="python:item[prop]"></label>
+ </td>
+ </tal:block>
+ </tr>
+ </tbody>
+ </table>
+ </form>
+ </tal:def>
+ </tal:if>
+
+ <pre tal:content=request tal:condition=false />
+ <script type="text/javascript"><!--
+ parent.submit.document.frm_help.cb_listpresent.checked=true;
+ reviseList_framed(document.dummyform, text_field)
+ //--></script>
+ </body>
+</html>
diff --git a/share/roundup/templates/classic/html/_generic.help-search.html b/share/roundup/templates/classic/html/_generic.help-search.html
--- /dev/null
@@ -0,0 +1,13 @@
+<html>
+ <head>
+ <title>Frame for search input fields</title>
+ </head>
+ <body>
+ <p i18n:translate="">Generic template
+ <span tal:replace="request/template" i18n:name="template">help-search</span>
+ or version for class
+ <span tal:replace="request/classname" i18n:name="classname">user</span>
+ is not yet implemented</p>
+ </body>
+</html>
+
diff --git a/share/roundup/templates/classic/html/_generic.help-submit.html b/share/roundup/templates/classic/html/_generic.help-submit.html
--- /dev/null
@@ -0,0 +1,73 @@
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="@@file/style.css" />
+ <meta http-equiv="Content-Type"
+ tal:attributes="content string:text/html;; charset=${request/client/charset}" />
+ <tal:block tal:condition="python:request.form.has_key('property')">
+ <title>Generic submit page for framed helper windows</title>
+ <script language="Javascript" type="text/javascript"
+ tal:content="structure string:<!--
+// this is the name of the field in the original form that we're working on
+form = parent.opener.document.${request/form/form/value};
+callingform=form
+field = '${request/form/property/value}';
+var listform = null
+function listPresent() {
+ return document.frm_help.cb_listpresent.checked
+}
+function getListForm() {
+ if (listPresent()) {
+ return parent.list.document.forms.dummyform
+ } else {
+ return null
+ }
+}
+
+
+function checkListForm() {
+ // global listform
+ if (listform != null)
+ if (parent.list.document.dummyform) {
+ listform = parent.list.document.dummyform
+ alert(listform)
+ }
+
+ var bol= listform != null
+ alert('checkListForm: bol='+bol)
+ return bol
+}
+//-->">
+ </script>
+ <script src="@@file/help_controls.js" type="text/javascript"></script>
+ </tal:block>
+ </head>
+ <body class="body" onload="parent.focus();" id="submit">
+ <pre tal:content="request/env/QUERY_STRING" tal:condition=false />
+ <form name="frm_help"
+ tal:define="batch request/batch;
+ props python:request.form['properties'].value.split(',')"
+ class="help-submit"
+ id="classhelp-controls">
+ <div style="width:100%;text-align:left;margin-bottom:0.2em">
+ <input type="text" name="text_preview" size="24" class="preview"
+ onchange="f=getListForm();if(f){ reviseList_framed(f, this)};"
+ />
+ </div>
+ <input type=checkbox name="cb_listpresent" readonly="readonly" style="display:none">
+ <input type="button" id="btn_cancel"
+ value=" Cancel " onclick="parent.close();return false;"
+ i18n:attributes="value" />
+ <input type="reset" id="btn_reset"
+ onclick="text_field.value=original_field;f=getListForm();if (f) {reviseList_framed(f, this)};return false"
+ />
+ <input type="submit" id="btn_apply" class="apply"
+ value=" Apply " onclick="callingform[field].value=text_field.value; parent.close();"
+ i18n:attributes="value" />
+ </form>
+ <script type="text/javascript"><!--
+var text_field = document.frm_help.text_preview;
+original_field=form[field].value;
+text_field.value=original_field;
+//--></script>
+ </body>
+</html>
diff --git a/share/roundup/templates/classic/html/_generic.help.html b/share/roundup/templates/classic/html/_generic.help.html
--- /dev/null
@@ -0,0 +1,98 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html tal:define="property request/form/property/value" >
+ <head>
+ <link rel="stylesheet" type="text/css" href="@@file/style.css" />
+ <meta http-equiv="Content-Type"
+ tal:attributes="content string:text/html;; charset=${request/client/charset}" />
+ <tal:block tal:condition="python:request.form.has_key('property')">
+ <title i18n:translate=""><tal:x i18n:name="property"
+ tal:content="property" i18n:translate="" /> help - <span i18n:name="tracker"
+ tal:replace="config/TRACKER_NAME" /></title>
+ <script language="Javascript" type="text/javascript"
+ tal:content="structure string:
+ // this is the name of the field in the original form that we're working on
+ form = window.opener.document.${request/form/form/value};
+ field = '${request/form/property/value}';">
+ </script>
+ <script src="@@file/help_controls.js" type="text/javascript"><!--
+ //--></script>
+ </tal:block>
+ </head>
+ <body class="body" onload="resetList();">
+ <form name="frm_help" tal:attributes="action request/base"
+ tal:define="batch request/batch;
+ props python:request.form['properties'].value.split(',')">
+
+ <div id="classhelp-controls">
+ <!--input type="button" name="btn_clear"
+ value="Clear" onClick="clearList()"/ -->
+ <input type="text" name="text_preview" size="24" class="preview"
+ onchange="reviseList(this.value);"/>
+ <input type="button" name="btn_reset"
+ value=" Cancel " onclick="resetList(); window.close();"
+ i18n:attributes="value" />
+ <input type="button" name="btn_apply" class="apply"
+ value=" Apply " onclick="updateList(); window.close();"
+ i18n:attributes="value" />
+ </div>
+ <table width="100%">
+ <tr class="navigation">
+ <th>
+ <a tal:define="prev batch/previous" tal:condition="prev"
+ tal:attributes="href python:request.indexargs_url(request.classname,
+ {'@template':'help', 'property': request.form['property'].value,
+ 'properties': request.form['properties'].value,
+ 'form': request.form['form'].value,
+ 'type': request.form['type'].value,
+ '@startwith':prev.first, '@pagesize':prev.size})"
+ i18n:translate="" ><< previous</a>
+
+ </th>
+ <th i18n:translate=""><span tal:replace="batch/start" i18n:name="start"
+ />..<span tal:replace="python: batch.start + batch.length -1" i18n:name="end"
+ /> out of <span tal:replace="batch/sequence_length" i18n:name="total"
+ />
+ </th>
+ <th>
+ <a tal:define="next batch/next" tal:condition="next"
+ tal:attributes="href python:request.indexargs_url(request.classname,
+ {'@template':'help', 'property': request.form['property'].value,
+ 'properties': request.form['properties'].value,
+ 'form': request.form['form'].value,
+ 'type': request.form['type'].value,
+ '@startwith':next.first, '@pagesize':next.size})"
+ i18n:translate="" >next >></a>
+
+ </th>
+ </tr>
+ </table>
+
+ <table class="classhelp">
+ <tr>
+ <th> <b>x</b></th>
+ <th tal:repeat="prop props" tal:content="prop" i18n:translate=""></th>
+ </tr>
+ <tr tal:repeat="item batch">
+ <tal:block tal:define="attr python:item[props[0]]" >
+ <td>
+ <input name="check"
+ onclick="updatePreview();"
+ tal:attributes="type python:request.form['type'].value;
+ value attr; id string:id_$attr" />
+ </td>
+ <td tal:repeat="prop props">
+ <label class="classhelp-label"
+ tal:attributes="for string:id_$attr"
+ tal:content="python:item[prop]"></label>
+ </td>
+ </tal:block>
+ </tr>
+ <tr>
+ <th> <b>x</b></th>
+ <th tal:repeat="prop props" tal:content="prop" i18n:translate=""></th>
+ </tr>
+ </table>
+
+ </form>
+ </body>
+</html>
diff --git a/share/roundup/templates/classic/html/_generic.index.html b/share/roundup/templates/classic/html/_generic.index.html
--- /dev/null
@@ -0,0 +1,70 @@
+<!-- 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" i18n:translate=""
+ ><span tal:replace="python:context._classname.capitalize()"
+ i18n:name="class" /> editing - <span i18n:name="tracker"
+ tal:replace="config/TRACKER_NAME" /></title>
+<tal:block metal:fill-slot="body_title" i18n:translate=""
+ ><span tal:replace="python:context._classname.capitalize()"
+ i18n:name="class" /> editing</tal:block>
+
+<td class="content" metal:fill-slot="content">
+
+<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok()
+ or request.user.hasRole('Anonymous'))"
+ tal:omit-tag="python:1" i18n:translate=""
+>You are not allowed to view this page.</span>
+
+<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())
+ and request.user.hasRole('Anonymous')"
+ tal:omit-tag="python:1" i18n:translate=""
+>Please login with your username and password.</span>
+
+<tal:block tal:condition="context/is_edit_ok">
+<tal:block i18n:translate="">
+<p class="form-help">
+ You may edit the contents of the
+ <span tal:replace="request/classname" i18n:name="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>
+</tal:block>
+<form onSubmit="return submit_once()" method="POST"
+ tal:attributes="action context/designator">
+<textarea rows="15" style="width:90%" name="rows" tal:content="context/csv"></textarea>
+<br>
+<input type="hidden" name="@action" value="editCSV">
+<input type="submit" value="Edit Items" i18n:attributes="value">
+</form>
+</tal:block>
+
+<table tal:condition="context/is_only_view_ok" width="100%" class="list">
+ <tr>
+ <th tal:repeat="property context/propnames" tal:content="property"> </th>
+ </tr>
+ <tal:block repeat="item context/list">
+ <tr tal:condition="item/is_view_ok"
+ tal:attributes="class python:['normal', 'alt'][repeat['item'].index%6/3]">
+ <td tal:repeat="property context/propnames"
+ tal:content="python: item[property] or default"
+ > </td>
+ </tr>
+ </tal:block>
+</table>
+
+</td>
+
+</tal:block>
diff --git a/share/roundup/templates/classic/html/_generic.item.html b/share/roundup/templates/classic/html/_generic.item.html
--- /dev/null
@@ -0,0 +1,53 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title" i18n:translate=""
+ ><span tal:replace="python:context._classname.capitalize()"
+ i18n:name="class" /> editing - <span i18n:name="tracker"
+ tal:replace="config/TRACKER_NAME" /></title>
+<tal:block metal:fill-slot="body_title" i18n:translate=""
+ ><span tal:replace="python:context._classname.capitalize()"
+ i18n:name="class" /> editing</tal:block>
+
+<td class="content" metal:fill-slot="content">
+
+<p tal:condition="python:not (context.is_view_ok()
+ or request.user.hasRole('Anonymous'))" i18n:translate="">
+ You are not allowed to view this page.</p>
+
+<p tal:condition="python:not context.is_view_ok()
+ and request.user.hasRole('Anonymous')" i18n:translate="">
+ Please login with your username and password.</p>
+
+<div tal:condition="context/is_view_ok">
+
+<form method="POST" onSubmit="return submit_once()"
+ enctype="multipart/form-data" tal:condition="context/is_view_ok"
+ tal:attributes="action context/designator">
+
+<input type="hidden" name="@template" value="item">
+
+<table class="form">
+
+<tr tal:repeat="prop python:db[context._classname].properties()">
+ <tal:block tal:condition="python:prop._name not in ('id',
+ 'creator', 'creation', 'actor', 'activity')">
+ <th tal:content="prop/_name"></th>
+ <td tal:content="structure python:context[prop._name].field()"></td>
+ </tal:block>
+</tr>
+<tr>
+ <td> </td>
+ <td colspan=3 tal:content="structure context/submit">
+ submit button will go here
+ </td>
+</tr>
+</table>
+
+</form>
+
+<tal:block tal:condition="context/id" tal:replace="structure context/history" />
+
+</div>
+
+</td>
+
+</tal:block>
diff --git a/share/roundup/templates/classic/html/file.index.html b/share/roundup/templates/classic/html/file.index.html
--- /dev/null
@@ -0,0 +1,31 @@
+<!-- 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" i18n:translate=""
+ >List of files - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">List of files</span>
+<td class="content" metal:fill-slot="content">
+
+<table class="otherinfo" tal:define="batch request/batch">
+ <tr><th style="padding-right: 10" i18n:translate="">Download</th>
+ <th style="padding-right: 10" i18n:translate="">Content Type</th>
+ <th style="padding-right: 10" i18n:translate="">Uploaded By</th>
+ <th style="padding-right: 10" i18n:translate="">Date</th>
+ </tr>
+ <tr tal:repeat="file batch" tal:attributes="class python:['normal', 'alt'][repeat['file'].index%6/3]">
+ <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>
+
+ <metal:block use-macro="templates/issue.index/macros/batch-footer" />
+
+</table>
+
+</td>
+
+</tal:block>
diff --git a/share/roundup/templates/classic/html/file.item.html b/share/roundup/templates/classic/html/file.item.html
--- /dev/null
@@ -0,0 +1,53 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title" i18n:translate="">File display - <span
+ i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">File display</span>
+
+<td class="content" metal:fill-slot="content">
+
+<p tal:condition="python:not (context.is_view_ok()
+ or request.user.hasRole('Anonymous'))" i18n:translate="">
+ You are not allowed to view this page.</p>
+
+<p tal:condition="python:not context.is_view_ok()
+ and request.user.hasRole('Anonymous')" i18n:translate="">
+ Please login with your username and password.</p>
+
+<form method="POST" onSubmit="return submit_once()"
+ enctype="multipart/form-data" tal:condition="context/is_view_ok"
+ tal:attributes="action context/designator">
+
+<table class="form">
+ <tr>
+ <th i18n:translate="">Name</th>
+ <td tal:content="structure context/name/field"></td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Content Type</th>
+ <td tal:content="structure context/type/field"></td>
+ </tr>
+
+ <tr>
+ <td>
+
+ <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">
+ </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}"
+ i18n:translate="">download</a>
+
+<tal:block tal:condition="context/id" tal:replace="structure context/history" />
+
+</td>
+
+</tal:block>
diff --git a/share/roundup/templates/classic/html/help.html b/share/roundup/templates/classic/html/help.html
--- /dev/null
@@ -0,0 +1,38 @@
+<!--
+Macros for framed help windows
+-->
+
+<!-- legend for helper search results -->
+<thead>
+<tr metal:define-macro="legend">
+ <th><b>x</b></th>
+ <th tal:repeat="prop props" tal:content="prop" i18n:translate=""></th>
+</tr>
+</thead>
+
+<table width="100%"
+ metal:define-macro="batch_navi"
+ tal:define="prev batch/previous;
+ next batch/next;
+ "
+ tal:condition="python:prev or next">
+ <tr class="navigation">
+ <th width="30%">
+ <a tal:condition="prev"
+ tal:attributes="href python:request.indexargs_url(request.classname, {'@template':'help-list', 'property': request.form['property'].value, 'properties': request.form['properties'].value, 'form': request.form['form'].value, '@startwith':prev.first, '@pagesize':prev.size})"
+ i18n:translate="" ><< previous</a>
+
+ </th>
+ <th i18n:translate="" width="40%"><span tal:replace="batch/start" i18n:name="start"
+ />..<span tal:replace="python: batch.start + batch.length -1" i18n:name="end"
+ /> out of <span tal:replace="batch/sequence_length" i18n:name="total"
+ />
+ </th>
+ <th width="30%">
+ <a tal:condition="next"
+ tal:attributes="href python:request.indexargs_url(request.classname, {'@template':'help-list', 'property': request.form['property'].value, 'properties': request.form['properties'].value, 'form': request.form['form'].value, '@startwith':next.first, '@pagesize':next.size})"
+ i18n:translate="" >next >></a>
+
+ </th>
+ </tr>
+ </table>
diff --git a/share/roundup/templates/classic/html/help_controls.js b/share/roundup/templates/classic/html/help_controls.js
--- /dev/null
@@ -0,0 +1,324 @@
+// initial values for either Nosy, Superseder, Keyword and Waiting On,
+// depending on which has called
+original_field = form[field].value;
+
+// Some browsers (ok, IE) don't define the "undefined" variable.
+undefined = document.geez_IE_is_really_friggin_annoying;
+
+function trim(value) {
+ var temp = value;
+ var obj = /^(\s*)([\W\w]*)(\b\s*$)/;
+ if (obj.test(temp)) { temp = temp.replace(obj, '$2'); }
+ var obj = / /g;
+ while (temp.match(obj)) { temp = temp.replace(obj, " "); }
+ return temp;
+}
+
+function determineList() {
+ // generate a comma-separated list of the checked items
+ var list = new String('');
+
+ // either a checkbox object or an array of checkboxes
+ var check = document.frm_help.check;
+
+ if ((check.length == undefined) && (check.checked != undefined)) {
+ // only one checkbox on page
+ if (check.checked) {
+ list = check.value;
+ }
+ } else {
+ // array of checkboxes
+ for (box=0; box < check.length; box++) {
+ if (check[box].checked) {
+ if (list.length == 0) {
+ separator = '';
+ }
+ else {
+ separator = ',';
+ }
+ // we used to use an Array and push / join, but IE5.0 sux
+ list = list + separator + check[box].value;
+ }
+ }
+ }
+ return list;
+}
+
+/**
+ * update the field in the opening window;
+ * the text_field variable must be set in the calling page
+ */
+function updateOpener() {
+ // write back to opener window
+ if (document.frm_help.check==undefined) { return; }
+ form[field].value = text_field.value;
+}
+
+function updateList() {
+ // write back to opener window
+ if (document.frm_help.check==undefined) { return; }
+ form[field].value = determineList();
+}
+
+function updatePreview() {
+ // update the preview box
+ if (document.frm_help.check==undefined) { return; }
+ writePreview(determineList());
+}
+
+function clearList() {
+ // uncheck all checkboxes
+ if (document.frm_help.check==undefined) { return; }
+ for (box=0; box < document.frm_help.check.length; box++) {
+ document.frm_help.check[box].checked = false;
+ }
+}
+
+function reviseList_framed(form, textfield) {
+ // update the checkboxes based on the preview field
+ // alert('reviseList_framed')
+ // alert(form)
+ if (form.check==undefined)
+ return;
+ // alert(textfield)
+ var to_check;
+ var list = textfield.value.split(",");
+ if (form.check.length==undefined) {
+ check = form.check;
+ to_check = false;
+ for (val in list) {
+ if (check.value==trim(list[val])) {
+ to_check = true;
+ break;
+ }
+ }
+ check.checked = to_check;
+ } else {
+ for (box=0; box < form.check.length; box++) {
+ check = form.check[box];
+ to_check = false;
+ for (val in list) {
+ if (check.value==trim(list[val])) {
+ to_check = true;
+ break;
+ }
+ }
+ check.checked = to_check;
+ }
+ }
+}
+
+function reviseList(vals) {
+ // update the checkboxes based on the preview field
+ if (document.frm_help.check==undefined) { return; }
+ var to_check;
+ var list = vals.split(",");
+ if (document.frm_help.check.length==undefined) {
+ check = document.frm_help.check;
+ to_check = false;
+ for (val in list) {
+ if (check.value==trim(list[val])) {
+ to_check = true;
+ break;
+ }
+ }
+ check.checked = to_check;
+ } else {
+ for (box=0; box < document.frm_help.check.length; box++) {
+ check = document.frm_help.check[box];
+ to_check = false;
+ for (val in list) {
+ if (check.value==trim(list[val])) {
+ to_check = true;
+ break;
+ }
+ }
+ check.checked = to_check;
+ }
+ }
+}
+
+function resetList() {
+ // reset preview and check boxes to initial values
+ if (document.frm_help.check==undefined) { return; }
+ writePreview(original_field);
+ reviseList(original_field);
+}
+
+function writePreview(val) {
+ // writes a value to the text_preview
+ document.frm_help.text_preview.value = val;
+}
+
+function focusField(name) {
+ for(i=0; i < document.forms.length; ++i) {
+ var obj = document.forms[i].elements[name];
+ if (obj && obj.focus) {obj.focus();}
+ }
+}
+
+function selectField(name) {
+ for(i=0; i < document.forms.length; ++i) {
+ var obj = document.forms[i].elements[name];
+ if (obj && obj.focus){obj.focus();}
+ if (obj && obj.select){obj.select();}
+ }
+}
+
+function checkRequiredFields(fields)
+{
+ var bonk='';
+ var res='';
+ var argv = checkRequiredFields.arguments;
+ var argc = argv.length;
+ var input = '';
+ var val='';
+
+ for (var i=0; i < argc; i++) {
+ fi = argv[i];
+ input = document.getElementById(fi);
+ if (input) {
+ val = input.value
+ if (val == '' || val == '-1' || val == -1) {
+ if (res == '') {
+ res = fi;
+ bonk = input;
+ } else {
+ res += ', '+fi;
+ }
+ }
+ } else {
+ alert('Field with id='+fi+' not found!')
+ }
+ }
+ if (res == '') {
+ return submit_once();
+ } else {
+ alert('Missing value here ('+res+')!');
+ if (window.event && window.event.returnvalue) {
+ event.returnValue = 0; // work-around for IE
+ }
+ bonk.focus();
+ return false;
+ }
+}
+
+/**
+ * seeks the given value (2nd argument)
+ * in the value of the given input element (1st argument),
+ * which is considered a list of values, separated by commas
+ */
+function has_value(input, val)
+{
+ var actval = input.value
+ var arr = feld.value.split(',');
+ var max = arr.length;
+ for (i=0;i<max;i++) {
+ if (trim(arr[i]) == val) {
+ return true
+ }
+ }
+ return false
+}
+
+/**
+ * Switch Value:
+ * change the value of the given input field (might be of type text or hidden),
+ * adding or removing the value of the given checkbox field (might be a radio
+ * button as well)
+ *
+ * This function doesn't care whether or not the checkboxes of all values of
+ * interest are present; but of course it doesn't have total control of the
+ * text field.
+ */
+function switch_val(text, check)
+{
+ var switched_val = check.value
+ var arr = text.value.split(',')
+ var max = arr.length
+ if (check.checked) {
+ for (i=0; i<max; i++) {
+ if (trim(arr[i]) == switched_val) {
+ return
+ }
+ }
+ if (text.value)
+ text.value = text.value+','+switched_val
+ else
+ text.value = switched_val
+ } else {
+ var neu = ''
+ var changed = false
+ for (i=0; i<max; i++) {
+ if (trim(arr[i]) == switched_val) {
+ changed=true
+ } else {
+ neu = neu+','+trim(arr[i])
+ }
+ }
+ if (changed) {
+ text.value = neu.substr(1)
+ }
+ }
+}
+
+/**
+ * append the given value (2nd argument) to an input field
+ * (1st argument) which contains comma-separated values;
+ * see --> remove_val()
+ *
+ * This will work nicely even for batched lists
+ */
+function append_val(name, val)
+{
+ var feld = document.itemSynopsis[name];
+ var actval = feld.value;
+ if (actval == '') {
+ feld.value = val
+ } else {
+ var arr = feld.value.split(',');
+ var max = arr.length;
+ for (i=0;i<max;i++) {
+ if (trim(arr[i]) == val) {
+ return
+ }
+ }
+ feld.value = actval+','+val
+ }
+}
+
+/**
+ * remove the given value (2nd argument) from the comma-separated values
+ * of the given input element (1st argument); see --> append_val()
+ */
+function remove_val(name, val)
+{
+ var feld = document.itemSynopsis[name];
+ var actval = feld.value;
+ var changed=false;
+ if (actval == '') {
+ return
+ } else {
+ var arr = feld.value.split(',');
+ var max = arr.length;
+ var neu = ''
+ for (i=0;i<max;i++) {
+ if (trim(arr[i]) == val) {
+ changed=true
+ } else {
+ neu = neu+','+trim(arr[i])
+ }
+ }
+ if (changed) {
+ feld.value = neu.substr(1)
+ }
+ }
+}
+
+/**
+ * give the focus to the element given by id
+ */
+function focus2id(name)
+{
+ document.getElementById(name).focus();
+}
diff --git a/share/roundup/templates/classic/html/home.classlist.html b/share/roundup/templates/classic/html/home.classlist.html
--- /dev/null
@@ -0,0 +1,25 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title" i18n:translate="">List of classes - <span
+ i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">List of classes</span>
+<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/share/roundup/templates/classic/html/home.html b/share/roundup/templates/classic/html/home.html
--- /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/share/roundup/templates/classic/html/issue.index.html b/share/roundup/templates/classic/html/issue.index.html
--- /dev/null
@@ -0,0 +1,166 @@
+<!-- $Id: issue.index.html,v 1.29 2007-09-18 17:44:26 jpend Exp $ -->
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title" >
+ <span tal:omit-tag="true" i18n:translate="" >List of issues</span>
+ <span tal:condition="request/dispname"
+ tal:replace="python:' - %s '%request.dispname"
+ /> - <span tal:replace="config/TRACKER_NAME" />
+</title>
+<span metal:fill-slot="body_title" tal:omit-tag="true">
+ <span tal:omit-tag="true" i18n:translate="" >List of issues</span>
+ <span tal:condition="request/dispname"
+ tal:replace="python:' - %s' % request.dispname" />
+</span>
+<td class="content" metal:fill-slot="content">
+
+<p tal:condition="python:not (context.is_view_ok()
+ or request.user.hasRole('Anonymous'))" i18n:translate="">
+ You are not allowed to view this page.</p>
+
+<p tal:condition="python:not context.is_view_ok()
+ and request.user.hasRole('Anonymous')" i18n:translate="">
+ Please login with your username and password.</p>
+
+<tal:block tal:define="batch request/batch" tal:condition="context/is_view_ok">
+ <table class="list">
+ <tr>
+ <th tal:condition="request/show/priority" i18n:translate="">Priority</th>
+ <th tal:condition="request/show/id" i18n:translate="">ID</th>
+ <th tal:condition="request/show/creation" i18n:translate="">Creation</th>
+ <th tal:condition="request/show/activity" i18n:translate="">Activity</th>
+ <th tal:condition="request/show/actor" i18n:translate="">Actor</th>
+ <th tal:condition="request/show/keyword" i18n:translate="">Keyword</th>
+ <th tal:condition="request/show/title" i18n:translate="">Title</th>
+ <th tal:condition="request/show/status" i18n:translate="">Status</th>
+ <th tal:condition="request/show/creator" i18n:translate="">Creator</th>
+ <th tal:condition="request/show/assignedto" i18n:translate="">Assigned To</th>
+ </tr>
+ <tal:block tal:repeat="i batch" condition=true>
+ <tr tal:define="group python:[r[1] for r in request.group]"
+ tal:condition="python:group and batch.propchanged(*group)">
+ <th tal:attributes="colspan python:len(request.columns)" class="group">
+ <tal:block tal:repeat="g group">
+ <tal:block i18n:translate="" tal:content="python:str(i[g]) or '(no %s set)'%g"/>
+ </tal:block>
+ </th>
+ </tr>
+
+ <tr>
+ <td tal:condition="request/show/priority"
+ tal:content="python:i.priority.plain() or default"> </td>
+ <td tal:condition="request/show/id" tal:content="i/id"> </td>
+ <td class="date" tal:condition="request/show/creation"
+ tal:content="i/creation/reldate"> </td>
+ <td class="date" tal:condition="request/show/activity"
+ tal:content="i/activity/reldate"> </td>
+ <td class="date" tal:condition="request/show/actor"
+ tal:content="python:i.actor.plain() or default"> </td>
+ <td tal:condition="request/show/keyword"
+ tal:content="python:i.keyword.plain() or default"> </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"
+ i18n:translate=""
+ tal:content="python:i.status.plain() or default"> </td>
+ <td tal:condition="request/show/creator"
+ tal:content="python:i.creator.plain() or default"> </td>
+ <td tal:condition="request/show/assignedto"
+ tal:content="python:i.assignedto.plain() or default"> </td>
+ </tr>
+
+ </tal:block>
+
+ <metal:index define-macro="batch-footer">
+ <tr tal:condition="batch">
+ <th tal:attributes="colspan python:len(request.columns)">
+ <table width="100%">
+ <tr class="navigation">
+ <th>
+ <a tal:define="prev batch/previous" tal:condition="prev"
+ tal:attributes="href python:request.indexargs_url(request.classname,
+ {'@startwith':prev.first, '@pagesize':prev.size})"
+ i18n:translate=""><< previous</a>
+
+ </th>
+ <th i18n:translate=""><span tal:replace="batch/start" i18n:name="start"
+ />..<span tal:replace="python: batch.start + batch.length -1" i18n:name="end"
+ /> out of <span tal:replace="batch/sequence_length" i18n:name="total"
+ /></th>
+ <th>
+ <a tal:define="next batch/next" tal:condition="next"
+ tal:attributes="href python:request.indexargs_url(request.classname,
+ {'@startwith':next.first, '@pagesize':next.size})"
+ i18n:translate="">next >></a>
+
+ </th>
+ </tr>
+ </table>
+ </th>
+ </tr>
+ </metal:index>
+</table>
+
+<a tal:attributes="href python:request.indexargs_url('issue',
+ {'@action':'export_csv'})" i18n:translate="">Download as CSV</a>
+
+<form method="GET" class="index-controls"
+ tal:attributes="action request/classname">
+
+ <table class="form" tal:define="n_sort python:2">
+ <tal:block tal:repeat="n python:range(n_sort)" tal:condition="batch">
+ <tr tal:define="key python:len(request.sort)>n and request.sort[n]">
+ <th>
+ <tal:block tal:condition="not:n" i18n:translate="">Sort on:</tal:block>
+ </th>
+ <td>
+ <select tal:attributes="name python:'@sort%d'%n">
+ <option value="" i18n:translate="">- nothing -</option>
+ <option tal:repeat="col context/properties"
+ tal:attributes="value col/_name;
+ selected python:key and col._name == key[1]"
+ tal:content="col/_name"
+ i18n:translate="">column</option>
+ </select>
+ </td>
+ <th i18n:translate="">Descending:</th>
+ <td><input type="checkbox" tal:attributes="name python:'@sortdir%d'%n;
+ checked python:key and key[0] == '-'">
+ </td>
+ </tr>
+ </tal:block>
+ <tal:block tal:repeat="n python:range(n_sort)" tal:condition="batch">
+ <tr tal:define="key python:len(request.group)>n and request.group[n]">
+ <th>
+ <tal:block tal:condition="not:n" i18n:translate="">Group on:</tal:block>
+ </th>
+ <td>
+ <select tal:attributes="name python:'@group%d'%n">
+ <option value="" i18n:translate="">- nothing -</option>
+ <option tal:repeat="col context/properties"
+ tal:attributes="value col/_name;
+ selected python:key and col._name == key[1]"
+ tal:content="col/_name"
+ i18n:translate="">column</option>
+ </select>
+ </td>
+ <th i18n:translate="">Descending:</th>
+ <td><input type="checkbox" tal:attributes="name python:'@groupdir%d'%n;
+ checked python:key and key[0] == '-'">
+ </td>
+ </tr>
+ </tal:block>
+ <tr><td colspan="4">
+ <input type="submit" value="Redisplay" i18n:attributes="value">
+ <tal:block tal:replace="structure
+ python:request.indexargs_form(sort=0, group=0)" />
+ </td></tr>
+ </table>
+</form>
+
+</tal:block>
+
+</td>
+</tal:block><tal:comment condition=false> vim: sw=1 ts=8 et si
+</tal:comment>
diff --git a/share/roundup/templates/classic/html/issue.item.html b/share/roundup/templates/classic/html/issue.item.html
--- /dev/null
@@ -0,0 +1,197 @@
+<!-- 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">
+<tal:block condition="context/id" i18n:translate=""
+ >Issue <tal:x tal:content="context/id" i18n:name="id"
+ />: <tal:x content="context/title" i18n:name="title"
+ /> - <tal:x content="config/TRACKER_NAME" i18n:name="tracker"
+/></tal:block>
+<tal:block condition="not:context/id" i18n:translate=""
+ >New Issue - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker"
+/></tal:block>
+</title>
+<tal:block metal:fill-slot="body_title">
+ <span tal:condition="python: not (context.id or context.is_edit_ok())"
+ tal:omit-tag="python:1" i18n:translate="">New Issue</span>
+ <span tal:condition="python: not context.id and context.is_edit_ok()"
+ tal:omit-tag="python:1" i18n:translate="">New Issue Editing</span>
+ <span tal:condition="python: context.id and not context.is_edit_ok()"
+ tal:omit-tag="python:1" i18n:translate="">Issue<tal:x
+ replace="context/id" i18n:name="id" /></span>
+ <span tal:condition="python: context.id and context.is_edit_ok()"
+ tal:omit-tag="python:1" i18n:translate="">Issue<tal:x
+ replace="context/id" i18n:name="id" /> Editing</span>
+</tal:block>
+
+<td class="content" metal:fill-slot="content">
+
+<p tal:condition="python:not (context.is_view_ok()
+ or request.user.hasRole('Anonymous'))" i18n:translate="">
+ You are not allowed to view this page.</p>
+
+<p tal:condition="python:not context.is_view_ok()
+ and request.user.hasRole('Anonymous')" i18n:translate="">
+ Please login with your username and password.</p>
+
+<div tal:condition="context/is_view_ok">
+
+<form method="POST" name="itemSynopsis"
+ onSubmit="return submit_once()" enctype="multipart/form-data"
+ tal:attributes="action context/designator">
+
+<table class="form">
+<tr>
+ <th class="required" i18n:translate="">Title</th>
+ <td colspan=3 tal:content="structure python:context.title.field(size=60)">title</td>
+</tr>
+
+<tr>
+ <th class="required" i18n:translate="">Priority</th>
+ <td tal:content="structure context/priority/menu">priority</td>
+ <th i18n:translate="">Status</th>
+ <td tal:content="structure context/status/menu">status</td>
+</tr>
+
+<tr>
+ <th i18n:translate="">Superseder</th>
+ <td>
+ <span tal:replace="structure python:context.superseder.field(showid=1, size=20)" />
+ <span tal:condition="context/is_edit_ok" tal:replace="structure python:db.issue.classhelp('id,title', property='superseder')" />
+ <span tal:condition="context/superseder">
+ <br><span i18n:translate="">View:</span>
+ <a tal:repeat="sup context/superseder"
+ tal:content="python:sup['id'] + ', '*(not repeat['sup'].end)"
+ tal:attributes="href string:issue${sup/id}"></a>
+ </span>
+ </td>
+ <th i18n:translate="">Nosy List</th>
+ <td>
+ <span tal:replace="structure context/nosy/field" />
+ <span tal:condition="context/is_edit_ok" tal:replace="structure
+python:db.user.classhelp('username,realname,address', property='nosy', width='600')" /><br>
+ </td>
+</tr>
+
+<tr>
+ <th i18n:translate="">Assigned To</th>
+ <td tal:content="structure context/assignedto/menu">assignedto menu</td>
+ <th i18n:translate="">Keywords</th>
+ <td>
+ <span tal:replace="structure context/keyword/field" />
+ <span tal:condition="context/is_edit_ok" tal:replace="structure python:db.keyword.classhelp(property='keyword')" />
+ </td>
+</tr>
+
+<tr tal:condition="context/is_edit_ok">
+ <th i18n:translate="">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 tal:condition="context/is_edit_ok">
+ <th i18n:translate="">File</th>
+ <td colspan=3><input type="file" name="@file" size="40"></td>
+</tr>
+
+<tr tal:condition="context/is_edit_ok">
+ <td>
+
+ <input type="hidden" name="@template" value="item">
+ <input type="hidden" name="@required" value="title,priority">
+ </td>
+ <td colspan=3>
+ <span tal:replace="structure context/submit">submit button</span>
+ <a tal:condition="context/id" tal:attributes="href context/copy_url"
+ i18n:translate="">Make a copy</a>
+ </td>
+</tr>
+
+</table>
+</form>
+
+<tal:block tal:condition="not:context/id" i18n:translate="">
+<table class="form">
+<tr>
+ <td>Note: </td>
+ <th class="required">highlighted</th>
+ <td> fields are required.</td>
+</tr>
+</table>
+</tal:block>
+
+<p tal:condition="context/id" i18n:translate="">
+ Created on <b tal:content="context/creation" i18n:name="creation" />
+ by <b tal:content="context/creator" i18n:name="creator" />,
+ last changed <b content="context/activity" i18n:name="activity" />
+ by <b tal:content="context/actor" i18n:name="actor" />.
+</p>
+
+<table class="files" tal:condition="context/files">
+ <tr><th colspan="5" class="header" i18n:translate="">Files</th></tr>
+ <tr>
+ <th i18n:translate="">File name</th>
+ <th i18n:translate="">Uploaded</th>
+ <th i18n:translate="">Type</th>
+ <th i18n:translate="">Edit</th>
+ <th i18n:translate="">Remove</th>
+ </tr>
+ <tr tal:repeat="file context/files">
+ <td>
+ <a tal:attributes="href file/download_url"
+ 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>
+ <td tal:content="file/type" />
+ <td><a tal:condition="file/is_edit_ok"
+ tal:attributes="href string:file${file/id}">edit</a>
+ </td>
+ <td>
+ <form style="padding:0" tal:condition="context/is_edit_ok"
+ tal:attributes="action string:issue${context/id}">
+ <input type="hidden" name="@remove@files" tal:attributes="value file/id">
+ <input type="hidden" name="@action" value="edit">
+ <input type="submit" value="remove" i18n:attributes="value">
+ </form>
+ </td>
+ </tr>
+</table>
+
+<table class="messages" tal:condition="context/messages">
+ <tr><th colspan="4" class="header" i18n:translate="">Messages</th></tr>
+ <tal:block tal:repeat="msg context/messages/reverse">
+ <tr>
+ <th><a tal:attributes="href string:msg${msg/id}"
+ i18n:translate="">msg<tal:x replace="msg/id" i18n:name="id" /> (view)</a></th>
+ <th i18n:translate="">Author: <tal:x replace="msg/author"
+ i18n:name="author" /></th>
+ <th i18n:translate="">Date: <tal:x replace="msg/date"
+ i18n:name="date" /></th>
+ <th>
+ <form style="padding:0" tal:condition="context/is_edit_ok"
+ tal:attributes="action string:issue${context/id}">
+ <input type="hidden" name="@remove@messages" tal:attributes="value msg/id">
+ <input type="hidden" name="@action" value="edit">
+ <input type="submit" value="remove" i18n:attributes="value">
+ </form>
+ </th>
+ </tr>
+ <tr>
+ <td colspan="4" class="content">
+ <pre tal:content="structure msg/content/hyperlinked">content</pre>
+ </td>
+ </tr>
+ </tal:block>
+</table>
+
+<tal:block tal:condition="context/id" tal:replace="structure context/history" />
+
+</div>
+
+</td>
+
+</tal:block>
diff --git a/share/roundup/templates/classic/html/issue.search.html b/share/roundup/templates/classic/html/issue.search.html
--- /dev/null
@@ -0,0 +1,234 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title" i18n:translate="">Issue searching - <span
+ i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">Issue searching</span>
+<td class="content" metal:fill-slot="content">
+
+<form method="GET" name="itemSynopsis"
+ tal:attributes="action request/classname">
+
+<table class="form" tal:define="
+ cols python:request.columns or 'id activity title status assignedto'.split();
+ sort_on python:request.sort and request.sort[0] or nothing;
+ sort_desc python:sort_on and sort_on[0] == '-';
+ sort_on python:(sort_on and sort_on[1]) or 'activity';
+ group_on python:request.group and request.group[0] or nothing;
+ group_desc python:group_on and group_on[0] == '-';
+ group_on python:(group_on and group_on[1]) or 'priority';
+
+ search_input templates/page/macros/search_input;
+ search_date templates/page/macros/search_date;
+ column_input templates/page/macros/column_input;
+ sort_input templates/page/macros/sort_input;
+ group_input templates/page/macros/group_input;
+ search_select templates/page/macros/search_select;
+ search_select_translated templates/page/macros/search_select_translated;
+ search_multiselect templates/page/macros/search_multiselect;">
+
+<tr>
+ <th class="header"> </th>
+ <th class="header" i18n:translate="">Filter on</th>
+ <th class="header" i18n:translate="">Display</th>
+ <th class="header" i18n:translate="">Sort on</th>
+ <th class="header" i18n:translate="">Group on</th>
+</tr>
+
+<tr tal:define="name string:@search_text">
+ <th i18n:translate="">All text*:</th>
+ <td metal:use-macro="search_input"></td>
+ <td> </td>
+ <td> </td>
+ <td> </td>
+</tr>
+
+<tr tal:define="name string:title">
+ <th i18n:translate="">Title:</th>
+ <td metal:use-macro="search_input"></td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td> </td>
+</tr>
+
+<tr tal:define="name string:keyword;
+ db_klass string:keyword;
+ db_content string:name;">
+ <th i18n:translate="">Keyword:</th>
+ <td metal:use-macro="search_select">
+ <option metal:fill-slot="extra_options" value="-1" i18n:translate=""
+ tal:attributes="selected python:value == '-1'">not selected</option>
+ </td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td metal:use-macro="group_input"></td>
+</tr>
+
+<tr tal:define="name string:id">
+ <th i18n:translate="">ID:</th>
+ <td metal:use-macro="search_input"></td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td> </td>
+</tr>
+
+<tr tal:define="name string:creation">
+ <th i18n:translate="">Creation Date:</th>
+ <td metal:use-macro="search_date"></td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td metal:use-macro="group_input"></td>
+</tr>
+
+<tr tal:define="name string:creator;
+ db_klass string:user;
+ db_content string:username;"
+ tal:condition="db/user/is_view_ok">
+ <th i18n:translate="">Creator:</th>
+ <td metal:use-macro="search_select">
+ <option metal:fill-slot="extra_options" i18n:translate=""
+ tal:attributes="value request/user/id">created by me</option>
+ </td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td metal:use-macro="group_input"></td>
+</tr>
+
+<tr tal:define="name string:activity">
+ <th i18n:translate="">Activity:</th>
+ <td metal:use-macro="search_date"></td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td> </td>
+</tr>
+
+<tr tal:define="name string:actor;
+ db_klass string:user;
+ db_content string:username;"
+ tal:condition="db/user/is_view_ok">
+ <th i18n:translate="">Actor:</th>
+ <td metal:use-macro="search_select">
+ <option metal:fill-slot="extra_options" i18n:translate=""
+ tal:attributes="value request/user/id">done by me</option>
+ </td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td> </td>
+</tr>
+
+<tr tal:define="name string:priority;
+ db_klass string:priority;
+ db_content string:name;">
+ <th i18n:translate="">Priority:</th>
+ <td metal:use-macro="search_select_translated">
+ <option metal:fill-slot="extra_options" value="-1" i18n:translate=""
+ tal:attributes="selected python:value == '-1'">not selected</option>
+ </td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td metal:use-macro="group_input"></td>
+</tr>
+
+<tr tal:define="name string:status;
+ db_klass string:status;
+ db_content string:name;">
+ <th i18n:translate="">Status:</th>
+ <td metal:use-macro="search_select_translated">
+ <tal:block metal:fill-slot="extra_options">
+ <option value="-1,1,2,3,4,5,6,7" i18n:translate=""
+ tal:attributes="selected python:value == '-1,1,2,3,4,5,6,7'">not resolved</option>
+ <option value="-1" i18n:translate=""
+ tal:attributes="selected python:value == '-1'">not selected</option>
+ </tal:block>
+ </td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td metal:use-macro="group_input"></td>
+</tr>
+
+<tr tal:define="name string:assignedto;
+ db_klass string:user;
+ db_content string:username;"
+ tal:condition="db/user/is_view_ok">
+ <th i18n:translate="">Assigned to:</th>
+ <td metal:use-macro="search_select">
+ <tal:block metal:fill-slot="extra_options">
+ <option tal:attributes="value request/user/id"
+ i18n:translate="">assigned to me</option>
+ <option value="-1" tal:attributes="selected python:value == '-1'"
+ i18n:translate="">unassigned</option>
+ </tal:block>
+ </td>
+ <td metal:use-macro="column_input"></td>
+ <td metal:use-macro="sort_input"></td>
+ <td metal:use-macro="group_input"></td>
+</tr>
+
+<tr>
+ <th i18n:translate="">No Sort or group:</th>
+ <td> </td>
+ <td> </td>
+ <td><input type="radio" name="@sort" value=""></td>
+ <td><input type="radio" name="@group" value=""></td>
+</tr>
+
+<tr>
+<th i18n:translate="">Pagesize:</th>
+<td><input name="@pagesize" size="3" value="50"
+ tal:attributes="value request/form/@pagesize/value | default"></td>
+</tr>
+
+<tr>
+<th i18n:translate="">Start With:</th>
+<td><input name="@startwith" size="3" value="0"
+ tal:attributes="value request/form/@startwith/value | default"></td>
+</tr>
+
+<tr>
+<th i18n:translate="">Sort Descending:</th>
+<td><input type="checkbox" name="@sortdir"
+ tal:attributes="checked sort_desc">
+</td>
+</tr>
+
+<tr>
+<th i18n:translate="">Group Descending:</th>
+<td><input type="checkbox" name="@groupdir"
+ tal:attributes="checked group_desc">
+</td>
+</tr>
+
+<tr tal:condition="python:request.user.hasPermission('Edit', 'query')">
+ <th i18n:translate="">Query name**:</th>
+ <td tal:define="value request/form/@queryname/value | nothing">
+ <input name="@queryname" tal:attributes="value value">
+ <input type="hidden" name="@old-queryname" tal:attributes="value value">
+ </td>
+</tr>
+
+<tr>
+ <td>
+
+ <input type="hidden" name="@action" value="search">
+ </td>
+ <td><input type="submit" value="Search" i18n:attributes="value"></td>
+</tr>
+
+<tr><td> </td>
+ <td colspan="4" class="help">
+ <span i18n:translate="" tal:omit-tag="true">
+ *: The "all text" field will look in message bodies and issue titles
+ </span><br>
+ <span tal:condition="python:request.user.hasPermission('Edit', 'query')"
+ i18n:translate="" tal:omit-tag="true"
+ >
+ **: If you supply a name, the query will be saved off and available as a
+ link in the sidebar
+ </span>
+ </td>
+</tr>
+</table>
+
+</form>
+</td>
+
+</tal:block>
diff --git a/share/roundup/templates/classic/html/keyword.item.html b/share/roundup/templates/classic/html/keyword.item.html
--- /dev/null
@@ -0,0 +1,55 @@
+<!-- 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" i18n:translate="">Keyword editing - <span
+ i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">Keyword editing</span>
+<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" i18n:translate="">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" i18n:translate="">
+ 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" i18n:translate="">
+ 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"
+ tal:attributes="action context/designator">
+
+ <table class="form">
+ <tr>
+ <th i18n:translate="">Keyword</th>
+ <td tal:content="structure context/name/field">name</td>
+ </tr>
+
+ <tr>
+ <td>
+
+ <input type="hidden" name="@required" value="name">
+ <input type="hidden" name="@template" value="item">
+ </td>
+ <td colspan=3 tal:content="structure context/submit">
+ submit button will go here
+ </td>
+ </tr>
+ </table>
+</form>
+</td>
+
+</tal:block>
diff --git a/share/roundup/templates/classic/html/msg.index.html b/share/roundup/templates/classic/html/msg.index.html
--- /dev/null
@@ -0,0 +1,25 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title" i18n:translate=""
+ >List of messages - <span tal:replace="config/TRACKER_NAME"
+ i18n:name="tracker"/></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">Message listing</span>
+<td class="content" metal:fill-slot="content">
+<table tal:define="batch request/batch" class="messages">
+ <tr><th colspan=2 class="header" i18n:translate="">Messages</th></tr>
+ <tal:block tal:repeat="msg batch">
+ <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>
+
+ <metal:block use-macro="templates/issue.index/macros/batch-footer" />
+
+</table>
+</td>
+
+</tal:block>
diff --git a/share/roundup/templates/classic/html/msg.item.html b/share/roundup/templates/classic/html/msg.item.html
--- /dev/null
@@ -0,0 +1,83 @@
+<!-- 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">
+<tal:block condition="context/id" i18n:translate=""
+ >Message <span tal:replace="context/id" i18n:name="id"
+ /> - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker"
+/></tal:block>
+<tal:block condition="not:context/id" i18n:translate=""
+ >New Message - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker"
+/></tal:block>
+</title>
+<tal:block metal:fill-slot="body_title">
+ <span tal:condition="python: not (context.id or context.is_edit_ok())"
+ tal:omit-tag="python:1" i18n:translate="">New Message</span>
+ <span tal:condition="python: not context.id and context.is_edit_ok()"
+ tal:omit-tag="python:1" i18n:translate="">New Message Editing</span>
+ <span tal:condition="python: context.id and not context.is_edit_ok()"
+ tal:omit-tag="python:1" i18n:translate="">Message<tal:x
+ replace="context/id" i18n:name="id" /></span>
+ <span tal:condition="python: context.id and context.is_edit_ok()"
+ tal:omit-tag="python:1" i18n:translate="">Message<tal:x
+ replace="context/id" i18n:name="id" /> Editing</span>
+</tal:block>
+<td class="content" metal:fill-slot="content">
+
+<p tal:condition="python:not (context.is_view_ok()
+ or request.user.hasRole('Anonymous'))" i18n:translate="">
+ You are not allowed to view this page.</p>
+
+<p tal:condition="python:not context.is_view_ok()
+ and request.user.hasRole('Anonymous')" i18n:translate="">
+ Please login with your username and password.</p>
+
+<div tal:condition="context/is_view_ok">
+<table class="form">
+
+<tr>
+ <th i18n:translate="">Author</th>
+ <td tal:content="context/author"></td>
+</tr>
+
+<tr>
+ <th i18n:translate="">Recipients</th>
+ <td tal:content="context/recipients"></td>
+</tr>
+
+<tr>
+ <th i18n:translate="">Date</th>
+ <td tal:content="context/date"></td>
+</tr>
+</table>
+
+<table class="messages">
+ <tr><th colspan=2 class="header" i18n:translate="">Content</th></tr>
+ <tr>
+ <td class="content" colspan=2><pre tal:content="structure context/content/hyperlinked"></pre></td>
+ </tr>
+</table>
+
+<table class="files" tal:condition="context/files">
+ <tr><th colspan="2" class="header" i18n:translate="">Files</th></tr>
+ <tr>
+ <th i18n:translate="">File name</th>
+ <th i18n:translate="">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" />
+
+</div>
+</td>
+
+</tal:block>
diff --git a/share/roundup/templates/classic/html/page.html b/share/roundup/templates/classic/html/page.html
--- /dev/null
@@ -0,0 +1,347 @@
+<!-- vim:sw=2 sts=2
+--><tal:block metal:define-macro="icing"
+><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title metal:define-slot="head_title">title goes here</title>
+<link rel="stylesheet" type="text/css" href="@@file/style.css">
+<meta http-equiv="Content-Type"
+ tal:attributes="content string:text/html;; charset=${request/client/charset}" />
+<script tal:replace="structure request/base_javascript">
+</script>
+<metal:x define-slot="more-javascript" />
+
+</head>
+<body class="body">
+
+<table class="body"
+ tal:define="
+kw_edit python:request.user.hasPermission('Edit', 'keyword');
+kw_create python:request.user.hasPermission('Create', 'keyword');
+kw_edit_link python:kw_edit and db.keyword.list();
+columns string:id,activity,title,creator,status;
+columns_showall string:id,activity,title,creator,assignedto,status;
+status_notresolved string:-1,1,2,3,4,5,6,7;
+"
+>
+
+<tr>
+ <td class="page-header-left"> </td>
+ <td class="page-header-top">
+ <div id="body-title">
+ <h2><span metal:define-slot="body_title">body title</span></h2>
+ </div>
+ <div id="searchbox">
+ <form method="GET" action="issue">
+ <input type="hidden" name="@columns"
+ tal:attributes="value columns_showall"
+ value="id,activity,title,creator,assignedto,status"/>
+ <input type="hidden" name="@sort" value="activity"/>
+ <input type="hidden" name="@group" value="priority"/>
+ <input id="search-text" name="@search_text" size="10"
+ tal:attributes="value request/search_text | default" />
+ <input type="submit" id="submit" name="submit" value="Search"
+ i18n:attributes="value" />
+ </form>
+ </div>
+ </td>
+</tr>
+
+<tr>
+ <td rowspan="2" valign="top" class="sidebar">
+ <p class="classblock"
+ tal:condition="python:request.user.hasPermission('View', 'query')">
+ <span i18n:translate=""
+ ><b>Your Queries</b> (<a href="query?@template=edit">edit</a>)</span><br>
+ <tal:block tal:repeat="qs request/user/queries">
+ <a href="#" tal:attributes="href string:${qs/klass}?${qs/url}&@dispname=${qs/name}"
+ tal:content="qs/name">link</a><br>
+ </tal:block>
+ </p>
+
+ <form method="POST" tal:attributes="action request/base">
+ <p class="classblock"
+ tal:condition="python:request.user.hasPermission('View', 'issue')">
+ <b i18n:translate="">Issues</b><br>
+ <span tal:condition="python:request.user.hasPermission('Create', 'issue')">
+ <a href="issue?@template=item" i18n:translate="">Create New</a><br>
+ </span>
+ <a href="#"
+ tal:attributes="href python:request.indexargs_url('issue', {
+ '@sort': '-activity',
+ '@group': 'priority',
+ '@filter': 'status,assignedto',
+ '@columns': columns,
+ '@search_text': '',
+ 'status': status_notresolved,
+ 'assignedto': '-1',
+ '@dispname': i18n.gettext('Show Unassigned'),
+ })"
+ i18n:translate="">Show Unassigned</a><br>
+ <a href="#"
+ tal:attributes="href python:request.indexargs_url('issue', {
+ '@sort': '-activity',
+ '@group': 'priority',
+ '@filter': 'status',
+ '@columns': columns_showall,
+ '@search_text': '',
+ 'status': status_notresolved,
+ '@dispname': i18n.gettext('Show All'),
+ })"
+ i18n:translate="">Show All</a><br>
+ <a href="issue?@template=search" i18n:translate="">Search</a><br>
+ <input type="submit" class="form-small" value="Show issue:"
+ i18n:attributes="value"><input class="form-small" 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:kw_edit or kw_create">
+ <b i18n:translate="">Keywords</b><br>
+ <span tal:condition="python:request.user.hasPermission('Create', 'keyword')">
+ <a href="keyword?@template=item" i18n:translate="">Create New</a><br>
+ </span>
+ <span tal:condition="kw_edit_link">
+ <a href="keyword?@template=item" i18n:translate="">Edit Existing</a><br>
+ </span>
+ </p>
+
+ <p class="classblock"
+ tal:condition="python:request.user.hasPermission('View', 'user')">
+ <b i18n:translate="">Administration</b><br>
+ <span tal:condition="python:request.user.hasPermission('Edit', None)">
+ <a href="home?@template=classlist" i18n:translate="">Class List</a><br>
+ </span>
+ <span tal:condition="python:request.user.hasPermission('View', 'user')
+ or request.user.hasPermission('Edit', 'user')">
+ <a href="user" i18n:translate="">User List</a><br>
+ </span>
+ <a tal:condition="python:request.user.hasPermission('Create', 'user')"
+ href="user?@template=item" i18n:translate="">Add User</a>
+ </p>
+
+ <form method="POST" tal:condition="python:request.user.username=='anonymous'"
+ tal:attributes="action request/base">
+ <p class="userblock">
+ <b i18n:translate="">Login</b><br>
+ <input size="10" name="__login_name"><br>
+ <input size="10" type="password" name="__login_password"><br>
+ <input type="hidden" name="@action" value="Login">
+ <input type="checkbox" name="remember" id="remember">
+ <label for="remember" i18n:translate="">Remember me?</label><br>
+ <input type="submit" value="Login" i18n:attributes="value"><br>
+ <input type="hidden" name="__came_from" tal:attributes="value string:${request/base}${request/env/PATH_INFO}">
+ <span tal:replace="structure request/indexargs_form" />
+ <a href="user?@template=register"
+ tal:condition="python:request.user.hasPermission('Create', 'user')"
+ i18n:translate="">Register</a><br>
+ <a href="user?@template=forgotten" i18n:translate="">Lost your login?</a><br>
+ </p>
+ </form>
+
+ <p class="userblock" tal:condition="python:request.user.username != 'anonymous'">
+ <b i18n:translate="">Hello, <span i18n:name="user"
+ tal:replace="python:request.user.username.plain(escape=1)">username</span></b><br>
+ <a href="#"
+ tal:attributes="href python:request.indexargs_url('issue', {
+ '@sort': '-activity',
+ '@group': 'priority',
+ '@filter': 'status,assignedto',
+ '@columns': 'id,activity,title,creator,status',
+ '@search_text': '',
+ 'status': status_notresolved,
+ 'assignedto': request.user.id,
+ '@dispname': i18n.gettext('Your Issues'),
+ })"
+ i18n:translate="">Your Issues</a><br>
+ <a href="#" tal:attributes="href string:user${request/user/id}"
+ i18n:translate="">Your Details</a><br>
+ <a href="#" tal:attributes="href python:request.indexargs_url('',
+ {'@action':'logout'})" i18n:translate="">Logout</a>
+ </p>
+ <p class="userblock">
+ <b i18n:translate="">Help</b><br>
+ <a href="http://roundup.sourceforge.net/doc-1.0/"
+ i18n:translate="">Roundup docs</a>
+ </p>
+ </td>
+ <td>
+ <p tal:condition="options/error_message | nothing" class="error-message"
+ tal:repeat="m options/error_message" tal:content="structure m" />
+ <p tal:condition="options/ok_message | nothing" class="ok-message">
+ <span tal:repeat="m options/ok_message"
+ tal:content="structure string:$m <br/ > " />
+ <a class="form-small" tal:attributes="href request/current_url"
+ i18n:translate="">clear this message</a>
+ </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>
+</tal:block>
+
+<!--
+The following macros are intended to be used in search pages.
+
+The invoking context must define a "name" variable which names the
+property being searched.
+
+See issue.search.html in the classic template for examples.
+-->
+
+<!-- creates a th and a label: -->
+<th metal:define-macro="th_label"
+ tal:define="required required | python:[]"
+ tal:attributes="class python:(name in required) and 'required' or nothing">
+ <label tal:attributes="for name" tal:content="label" i18n:translate="">text</label>
+ <metal:x define-slot="behind_the_label" />
+</th>
+
+<td metal:define-macro="search_input">
+ <input tal:attributes="value python:request.form.getvalue(name) or nothing;
+ name name;
+ id name">
+</td>
+
+<td metal:define-macro="search_date">
+ <input tal:attributes="value python:request.form.getvalue(name) or nothing;
+ name name;
+ id name">
+ <a class="classhelp"
+ tal:attributes="href python:'''javascript:help_window('issue?@template=calendar&property=%s&form=itemSynopsis', 300, 200)'''%name">(cal)</a>
+</td>
+
+<td metal:define-macro="search_popup">
+ <!--
+ context needs to specify the popup "columns" as a comma-separated
+ string (eg. "id,title" or "id,name,description") as well as name
+ -->
+ <input tal:attributes="value python:request.form.getvalue(name) or nothing;
+ name name;
+ id name">
+ <span tal:replace="structure python:db.issue.classhelp(columns,
+ property=name)" />
+</td>
+
+<td metal:define-macro="search_select">
+ <select tal:attributes="name name; id name"
+ tal:define="value python:request.form.getvalue(name)">
+ <option value="" i18n:translate="">don't care</option>
+ <metal:slot define-slot="extra_options" />
+ <option value="" i18n:translate="" disabled="disabled">------------</option>
+ <option tal:repeat="s python:db[db_klass].list()"
+ tal:attributes="value s/id; selected python:value == s.id"
+ tal:content="python:s[db_content]"></option>
+ </select>
+</td>
+
+<!-- like search_select, but translates the further values.
+Could extend it (METAL 1.1 attribute "extend-macro")
+-->
+<td metal:define-macro="search_select_translated">
+ <select tal:attributes="name name; id name"
+ tal:define="value python:request.form.getvalue(name)">
+ <option value="" i18n:translate="">don't care</option>
+ <metal:slot define-slot="extra_options" />
+ <option value="" i18n:translate="" disabled="disabled">------------</option>
+ <option tal:repeat="s python:db[db_klass].list()"
+ tal:attributes="value s/id; selected python:value == s.id"
+ tal:content="python:s[db_content]"
+ i18n:translate=""></option>
+ </select>
+</td>
+
+<!-- currently, there is no convenient API to get a list of all roles -->
+<td metal:define-macro="search_select_roles"
+ tal:define="onchange onchange | nothing">
+ <select name=roles id=roles tal:attributes="onchange onchange">
+ <option value="" i18n:translate="">don't care</option>
+ <option value="" i18n:translate="" disabled="disabled">------------</option>
+ <option value="User">User</option>
+ <option value="Admin">Admin</option>
+ <option value="Anonymous">Anonymous</option>
+ </select>
+</td>
+
+<td metal:define-macro="search_multiselect">
+ <input tal:attributes="value python:request.form.getvalue(name) or nothing;
+ name name;
+ id name">
+ <span tal:replace="structure python:db[db_klass].classhelp(db_content,
+ property=name, width='600')" />
+</td>
+
+<td metal:define-macro="search_checkboxes">
+ <ul class="search-checkboxes"
+ tal:define="value python:request.form.getvalue(name);
+ values python:value and value.split(',') or []">
+ <li tal:repeat="s python:db[db_klass].list()">
+ <input type="checkbox" tal:attributes="name name; id string:$name-${s/id};
+ value s/id; checked python:s.id in values" />
+ <label tal:attributes="for string:$name-${s/id}"
+ tal:content="python:s[db_content]" />
+ </li>
+ <li metal:define-slot="no_value_item">
+ <input type="checkbox" value="-1" tal:attributes="name name;
+ id string:$name--1; checked python:value == '-1'" />
+ <label tal:attributes="for string:$name--1" i18n:translate="">no value</label>
+ </li>
+ </ul>
+</td>
+
+<td metal:define-macro="column_input">
+ <input type="checkbox" name="@columns"
+ tal:attributes="value name;
+ checked python:name in cols">
+</td>
+
+<td metal:define-macro="sort_input">
+ <input type="radio" name="@sort"
+ tal:attributes="value name;
+ checked python:name == sort_on">
+</td>
+
+<td metal:define-macro="group_input">
+ <input type="radio" name="@group"
+ tal:attributes="value name;
+ checked python:name == group_on">
+</td>
+
+<!--
+The following macros are intended for user editing.
+
+The invoking context must define a "name" variable which names the
+property being searched; the "edit_ok" variable tells whether the
+current user is allowed to edit.
+
+See user.item.html in the classic template for examples.
+-->
+<script metal:define-macro="user_utils" type="text/javascript" src="@@file/user_utils.js"></script>
+
+<!-- src: value will be re-used for other input fields -->
+<input metal:define-macro="user_src_input"
+ type="text" tal:attributes="onblur python:edit_ok and 'split_name(this)';
+ id name; name name; value value; readonly not:edit_ok"
+ value="heinz.kunz">
+<!-- normal: no re-using -->
+<input metal:define-macro="user_normal_input" type="text"
+ tal:attributes="id name; name name; value value; readonly not:edit_ok"
+ value="heinz">
+<!-- password: type; no initial value -->
+ <input metal:define-macro="user_pw_input" type="password"
+ tal:attributes="id name; name name; readonly not:edit_ok" value="">
+ <input metal:define-macro="user_confirm_input" type="password"
+ tal:attributes="id name; name string:@confirm@$name; readonly not:edit_ok" value="">
+
diff --git a/share/roundup/templates/classic/html/query.edit.html b/share/roundup/templates/classic/html/query.edit.html
--- /dev/null
@@ -0,0 +1,111 @@
+<!-- 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" i18n:translate=""
+ >"Your Queries" Editing - <span tal:replace="config/TRACKER_NAME"
+ i18n:name="tracker" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">"Your Queries" Editing</span>
+
+<td class="content" metal:fill-slot="content">
+
+<span tal:condition="not:context/is_edit_ok"
+ i18n:translate="">You are not allowed to edit queries.</span>
+
+<script language="javascript">
+// This exists solely because I can't figure how to get the & into an
+// attributes TALES expression, and so it keeps getting quoted.
+function retire(qid) {
+ window.location = 'query'+qid+'?@action=retire&@template=edit';
+}
+</script>
+
+<form method="POST" onSubmit="return submit_once()" action="query"
+ enctype="multipart/form-data" tal:condition="context/is_edit_ok">
+
+<table class="list" width="100%"
+ tal:define="uid request/user/id; mine request/user/queries">
+
+<tr><th i18n:translate="">Query</th>
+ <th i18n:translate="">Include in "Your Queries"</th>
+ <th i18n:translate="">Edit</th>
+ <th i18n:translate="">Private to you?</th>
+ <th> </th>
+</tr>
+
+<tr tal:repeat="query mine">
+ <tal:block condition="query/is_retired">
+
+ <td><a tal:attributes="href string:${query/klass}?${query/url}"
+ tal:content="query/name">query</a></td>
+
+ <td metal:define-macro="include">
+ <select tal:condition="python:query.id not in mine"
+ tal:attributes="name string:user${uid}@add@queries">
+ <option value="" i18n:translate="">leave out</option>
+ <option tal:attributes="value query/id" i18n:translate="">include</option>
+ </select>
+ <select tal:condition="python:query.id in mine"
+ tal:attributes="name string:user${uid}@remove@queries">
+ <option value="" i18n:translate="">leave in</option>
+ <option tal:attributes="value query/id" i18n:translate="">remove</option>
+ </select>
+ </td>
+
+ <td colspan="3" i18n:translate="">[query is retired]</td>
+
+ <!-- <td> maybe offer "restore" some day </td> -->
+ </tal:block>
+</tr>
+
+<tr tal:repeat="query mine">
+ <tal:block condition="not:query/is_retired">
+ <td><a tal:attributes="href string:${query/klass}?${query/url}"
+ tal:content="query/name">query</a></td>
+
+ <td metal:use-macro="template/macros/include" />
+
+ <td><a tal:attributes="href string:query${query/id}" i18n:translate="">edit</a></td>
+
+ <td>
+ <select tal:attributes="name string:query${query/id}@private_for">
+ <option tal:attributes="selected python:query.private_for == uid;
+ value uid" i18n:translate="">yes</option>
+ <option tal:attributes="selected python:query.private_for == None"
+ value="-1" i18n:translate="">no</option>
+ </select>
+ </td>
+
+ <td>
+ <input type="button" value="Delete" i18n:attributes="value"
+ tal:attributes="onClick python:'''retire('%s')'''%query.id">
+ </td>
+ </tal:block>
+</tr>
+
+<tr tal:define="queries python:db.query.filter(filterspec={'private_for':None})"
+ tal:repeat="query queries">
+ <tal:block condition="python: query.creator != uid">
+ <td><a tal:attributes="href string:${query/klass}?${query/url}"
+ tal:content="query/name">query</a></td>
+
+ <td metal:use-macro="template/macros/include" />
+
+ <td colspan="3" tal:condition="query/is_edit_ok">
+ <a tal:attributes="href string:query${query/id}" i18n:translate="">edit</a>
+ </td>
+ <td tal:condition="not:query/is_edit_ok" colspan="3"
+ i18n:translate="">[not yours to edit]</td>
+ </tal:block>
+</tr>
+
+<tr><td colspan="5">
+ <input type="hidden" name="@action" value="edit">
+ <input type="hidden" name="@template" value="edit">
+ <input type="submit" value="Save Selection" i18n:attributes="value">
+</td></tr>
+
+</table>
+
+</form>
+</td>
+</tal:block>
diff --git a/share/roundup/templates/classic/html/query.item.html b/share/roundup/templates/classic/html/query.item.html
--- /dev/null
@@ -0,0 +1,3 @@
+<!-- query.item -->
+<span tal:replace="structure context/renderQueryForm" />
+
diff --git a/share/roundup/templates/classic/html/style.css b/share/roundup/templates/classic/html/style.css
--- /dev/null
@@ -0,0 +1,433 @@
+/* main page styles */
+body.body {
+ font-family: sans-serif, Arial, Helvetica;
+ background-color: white;
+ color: #333;
+ margin: 0;
+}
+a[href]:hover {
+ color:blue;
+ text-decoration: underline;
+}
+a[href], a[href]:link {
+ color:blue;
+ text-decoration: none;
+}
+
+table.body {
+ border: 0;
+ padding: 0;
+ border-spacing: 0;
+ border-collapse: separate;
+}
+
+td.page-header-left {
+ padding: 5px;
+ border-bottom: 1px solid #444;
+}
+td.sidebar {
+ padding: 1px 0 0 1px;
+ white-space: nowrap;
+}
+
+/* don't display the sidebar when printing */
+@media print {
+ td.page-header-left {
+ display: none;
+ }
+ td.sidebar {
+ display: none;
+ }
+ .index-controls {
+ display: none;
+ }
+ #searchbox {
+ display: none;
+ }
+}
+
+td.page-header-top {
+ padding: 5px;
+ border-bottom: 1px solid #444;
+}
+#searchbox {
+ float: right;
+}
+
+div#body-title {
+ float: left;
+}
+
+
+div#searchbox {
+ float: right;
+ padding-top: 1em;
+}
+
+div#searchbox input#search-text {
+ width: 10em;
+}
+
+form {
+ margin: 0;
+}
+
+textarea {
+ font-family: monospace;
+}
+
+td.sidebar p.classblock {
+ padding: 2px 5px 2px 5px;
+ margin: 1px;
+ border: 1px solid #444;
+ background-color: #eee;
+}
+
+td.sidebar p.userblock {
+ padding: 2px 5px 2px 5px;
+ margin: 1px 1px 1px 1px;
+ border: 1px solid #444;
+ background-color: #eef;
+}
+
+.form-small {
+ padding: 0;
+ font-size: 75%;
+}
+
+
+td.content {
+ padding: 1px 5px 1px 5px;
+ vertical-align: top;
+ width: 100%;
+}
+
+td.date, th.date {
+ white-space: nowrap;
+}
+
+p.ok-message {
+ background-color: #22bb22;
+ padding: 5px;
+ color: white;
+ font-weight: bold;
+}
+p.error-message {
+ background-color: #bb2222;
+ padding: 5px;
+ color: white;
+ font-weight: bold;
+}
+p.error-message a[href] {
+ color: white;
+ text-decoration: underline;
+}
+
+
+/* style for search forms */
+ul.search-checkboxes {
+ display: inline;
+ padding: 0;
+ list-style: none;
+}
+ul.search-checkboxes > li {
+ display: inline;
+ padding-right: .5em;
+}
+
+
+/* style for forms */
+table.form {
+ padding: 2px;
+ border-spacing: 0;
+ border-collapse: separate;
+}
+
+table.form th {
+ color: #338;
+ text-align: right;
+ vertical-align: top;
+ font-weight: normal;
+ white-space: nowrap;
+}
+
+table.form th.header {
+ font-weight: bold;
+ background-color: #eef;
+ text-align: left;
+}
+
+table.form th.required {
+ font-weight: bold;
+}
+
+table.form td {
+ color: #333;
+ empty-cells: show;
+ vertical-align: top;
+}
+
+table.form td.optional {
+ font-weight: bold;
+ font-style: italic;
+}
+
+table.form td.html {
+ color: #777;
+}
+
+/* style for lists */
+table.list {
+ border-spacing: 0;
+ border-collapse: separate;
+ width: 100%;
+}
+
+table.list th {
+ padding: 0 4px 0 4px;
+ color: #404070;
+ background-color: #eef;
+ 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 4px 0 4px;
+ border: 1px solid white;
+ color: #404070;
+ background-color: #efefef;
+ vertical-align: top;
+ empty-cells: show;
+}
+
+table.list tr.navigation th {
+ width: 33%;
+ border-style: hidden;
+ text-align: center;
+}
+table.list tr.navigation td {
+ border: none
+}
+table.list tr.navigation th:first-child {
+ text-align: left;
+}
+table.list tr.navigation th:last-child {
+ text-align: right;
+}
+
+
+/* style for message displays */
+table.messages {
+ border-spacing: 0;
+ 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: 2px 5px 2px 5px;
+}
+
+table.messages td:first-child {
+ border-left: 1px solid #afafaf;
+ border-right: 1px solid #afafaf;
+}
+
+/* style for file displays */
+table.files {
+ border-spacing: 0;
+ 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: 0;
+ 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: 0;
+ 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 { /* the table-layout: fixed; */
+ table-layout: fixed; /* compromises quality for speed */
+ overflow: hidden;
+ font-size: .9em;
+ padding-bottom: 3em;
+}
+
+table.classhelp th {
+ font-weight: normal;
+ text-align: left;
+ color: #444;
+ background-color: #efefef;
+ border-bottom: 1px solid #afafaf;
+ border-top: 1px solid #afafaf;
+ text-transform: uppercase;
+ vertical-align: middle;
+ line-height:1.5em;
+}
+
+table.classhelp td {
+ vertical-align: middle;
+ padding-right: .2em;
+ border-bottom: 1px solid #efefef;
+ text-align: left;
+ empty-cells: show;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+
+table.classhelp tr:hover {
+ background-color: #eee;
+}
+
+label.classhelp-label {
+ cursor: pointer;
+}
+
+#classhelp-controls {
+ position: fixed;
+ display: block;
+ top: auto;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ padding: .5em;
+ border-top: 2px solid #444;
+ background-color: #eee;
+}
+
+#classhelp-controls input.apply {
+ width: 7em;
+ font-weight: bold;
+ margin-right: 2em;
+ margin-left: 2em;
+}
+
+#classhelp-controls input.preview {
+ margin-right: 3em;
+ margin-left: 1em;
+}
+
+/* style for "other" displays */
+table.otherinfo {
+ border-spacing: 0;
+ 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;
+}
+input[type="text"]:focus,
+input[type="checkbox"]:focus,
+input[type="radio"]:focus,
+input[type="password"]:focus,
+textarea:focus, select:focus {
+ background-color: #ffffc0;
+}
+
+/* vim: sts=2 sw=2 et
+*/
diff --git a/share/roundup/templates/classic/html/user.forgotten.html b/share/roundup/templates/classic/html/user.forgotten.html
--- /dev/null
@@ -0,0 +1,43 @@
+<!-- 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" i18n:translate="">Password reset request - <span
+ i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">Password reset request</span>
+<td class="content" metal:fill-slot="content">
+
+<p i18n:translate="">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()"
+ tal:attributes="action context/designator">
+ <table class="form">
+ <tr>
+ <th i18n:translate="">Email Address:</th>
+ <td><input name="address"></td>
+ </tr>
+ <tr>
+ <td> </td>
+ <td>
+ <input type="hidden" name="@action" value="passrst">
+ <input type="hidden" name="@template" value="forgotten">
+ <input type="submit" value="Request password reset"
+ i18n:attributes="value">
+ </td>
+ </tr>
+</table>
+
+<p i18n:translate="">Or, if you know your username, then enter it below.</p>
+
+<table class="form">
+ <tr><th i18n:translate="">Username:</th> <td><input name="username"></td> </tr>
+ <tr><td></td><td><input type="submit" value="Request password reset"
+ i18n:attributes="value"></td></tr>
+</table>
+</form>
+
+<p i18n:translate="">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/share/roundup/templates/classic/html/user.help-search.html b/share/roundup/templates/classic/html/user.help-search.html
--- /dev/null
@@ -0,0 +1,85 @@
+<html
+ tal:define="form request/form/form/value;
+ field request/form/property/value"
+ >
+ <head>
+ <title>Search input for user helper</title>
+ <script language="Javascript" type="text/javascript"
+ tal:content="structure string:<!--
+ // this is the name of the field in the original form that we're working on
+ form = parent.opener.document.${form};
+ field = '${field}';
+ //-->">
+ </script>
+ <script type="text/javascript" src="@@file/help_controls.js"></script>
+ <link rel="stylesheet" type="text/css" href="@@file/style.css" />
+ </head>
+ <body onload="parent.submit.url='...'"
+ tal:define="
+qs request/env/QUERY_STRING;
+qs python:'&'.join([a for a in qs.split('&') if not a.startswith('@template=')])"
+>
+ <pre tal:content="request/env/QUERY_STRING" tal:condition=false />
+ <form method="GET" name="itemSynopsis"
+ target="list"
+ tal:attributes="action request/classname"
+ tal:define="
+ property request/form/property/value;
+ cols python:request.columns or 'id username address realname roles'.split();
+ sort_on request/sort | nothing;
+ sort_desc python:sort_on and request.sort[0][0] == '-';
+ sort_on python:sort_on and request.sort[0][1] or 'lastname';
+
+ search_input templates/page/macros/search_input;
+ search_select templates/page/macros/search_select;
+ search_select_roles templates/page/macros/search_select_roles;
+ required python:[];
+ th_label templates/page/macros/th_label;
+ ">
+ <input type="hidden" name="@template" value="help-list">
+ <input type="hidden" name="property" value="" tal:attributes="value property">
+ <input type="hidden" name="form" value="" tal:attributes="value request/form/form/value">
+ <table>
+<tr tal:define="name string:username; label string:Username:">
+ <th metal:use-macro="th_label">Name</th>
+ <td metal:use-macro="search_input"><input type=text></td>
+</tr>
+
+<tr tal:define="name string:phone; label string:Phone number">
+ <th metal:use-macro="th_label">Phone</th>
+ <td metal:use-macro="search_input"><input type=text></td>
+</tr>
+
+<tr tal:define="name string:roles;
+ onchange string:this.form.submit();
+ label string:Roles:"
+ >
+ <th metal:use-macro="th_label">role</th>
+ <td metal:use-macro="search_select_roles">
+ <select>
+ <option value="">jokester</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td> </td>
+ <td>
+ <input type="hidden" name="@action" value="search">
+ <input type="submit" value="Search" i18n:attributes="value">
+ <input type="reset">
+ <input type="hidden" value="username,realname,phone,organisation,roles" name="properties">
+ <input type="text" name="@pagesize" id="sp-pagesize" value="25" size="2">
+ <label for="sp-pagesize" i18n:translate="">Pagesize</label>
+ </td>
+</tr>
+
+ </table>
+
+</form>
+<pre tal:content="request" tal:condition=false />
+<script type="text/javascript"><!--
+ focus2id('username');
+//--></script>
+ </body>
+</html>
diff --git a/share/roundup/templates/classic/html/user.help.html b/share/roundup/templates/classic/html/user.help.html
--- /dev/null
@@ -0,0 +1,49 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html tal:define="property request/form/property/value;
+qs request/env/QUERY_STRING;
+qs python:'&'.join([a for a in qs.split('&') if not a.startswith('@template=')]);
+form request/form/form/value;
+field request/form/property/value">
+ <head>
+ <link rel="stylesheet" type="text/css" href="@@file/style.css" />
+ <meta http-equiv="Content-Type"
+ tal:attributes="content string:text/html;; charset=${request/client/charset}" />
+ <tal:block tal:condition="python:request.form.has_key('property')">
+ <title><tal:x i18n:translate=""><tal:x i18n:name="property"
+ tal:content="property" i18n:translate="" /> help - <span i18n:name="tracker"
+ tal:replace="config/TRACKER_NAME" /></tal:x></title>
+ <script language="Javascript" type="text/javascript"
+ tal:condition=false
+ tal:content="structure string:<!--
+ // this is the name of the field in the original form that we're working on
+ form = window.opener.document.${form};
+ field = '${field}';
+ //-->">
+ </script>
+ <script src="@@file/help_controls.js"
+ tal:condition=false type="text/javascript"><!--
+ //--></script>
+ </tal:block>
+ </head>
+<frameset rows="123,*,62">
+ <frame src="#" tal:attributes="src string:?@template=help-search&${qs}" name="search">
+ <!-- for search results: help-list -->
+ <frame
+ tal:attributes="src string:?@template=help-empty&${qs}"
+ name="list">
+ <frame
+ tal:attributes="src string:?@template=help-submit&${qs}"
+ name="submit">
+ <!-- -->
+</frameset>
+<noframes>
+ <body>
+<p i18n:translate="">
+Your browser is not capable of using frames; you should be redirected immediately,
+or visit <a href="#" tal:attributes="href string:?${qs}&template=help-noframes"
+i18n:name="link">this link</a>.
+</p>
+</body>
+</noframes>
+
+</html>
diff --git a/share/roundup/templates/classic/html/user.index.html b/share/roundup/templates/classic/html/user.index.html
--- /dev/null
@@ -0,0 +1,45 @@
+<!-- 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" i18n:translate="">User listing - <span
+ i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">User listing</span>
+<td class="content" metal:fill-slot="content">
+
+<span tal:condition="python:not (context.is_view_ok()
+ or request.user.hasRole('Anonymous'))"
+ i18n:translate="">You are not allowed to view this page.</span>
+
+<span tal:condition="python:not context.is_view_ok()
+ and request.user.hasRole('Anonymous')"
+ i18n:translate="">Please login with your username and password.</span>
+
+<table width="100%" tal:condition="context/is_view_ok" class="list">
+<tr>
+ <th i18n:translate="">Username</th>
+ <th i18n:translate="">Real name</th>
+ <th i18n:translate="">Organisation</th>
+ <th i18n:translate="">Email address</th>
+ <th i18n:translate="">Phone number</th>
+ <th tal:condition="context/is_edit_ok" i18n:translate="">Retire</th>
+</tr>
+<tal:block repeat="user context/list">
+<tr 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.realname.plain() or default"> </td>
+ <td tal:content="python:user.organisation.plain() or default"> </td>
+ <td tal:content="python:user.address.email() or default"> </td>
+ <td tal:content="python:user.phone.plain() or default"> </td>
+ <td tal:condition="context/is_edit_ok">
+ <a tal:attributes="href string:user${user/id}?@action=retire&@template=index"
+ i18n:translate="">retire</a>
+ </td>
+</tr>
+</tal:block>
+</table>
+</td>
+
+</tal:block>
diff --git a/share/roundup/templates/classic/html/user.item.html b/share/roundup/templates/classic/html/user.item.html
--- /dev/null
@@ -0,0 +1,169 @@
+<!-- dollarId: user.item,v 1.7 2002/08/16 04:29:04 richard Exp dollar-->
+<tal:doc metal:use-macro="templates/page/macros/icing"
+define="edit_ok context/is_edit_ok"
+>
+<title metal:fill-slot="head_title">
+<tal:if condition="context/id" i18n:translate=""
+ >User <tal:x content="context/id" i18n:name="id"
+ />: <tal:x content="context/username" i18n:name="title"
+ /> - <tal:x content="config/TRACKER_NAME" i18n:name="tracker"
+/></tal:if>
+<tal:if condition="not:context/id" i18n:translate=""
+ >New User - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker"
+/></tal:if>
+</title>
+<metal:slot fill-slot="more-javascript">
+<script metal:use-macro="templates/page/macros/user_utils"></script>
+<script type="text/javascript" src="@@file/help_controls.js"></script>
+</metal:slot>
+<tal:block metal:fill-slot="body_title"
+ define="edit_ok context/is_edit_ok">
+ <span tal:condition="python: not (context.id or edit_ok)"
+ tal:omit-tag="python:1" i18n:translate="">New User</span>
+ <span tal:condition="python: not context.id and edit_ok"
+ tal:omit-tag="python:1" i18n:translate="">New User Editing</span>
+ <span tal:condition="python: context.id and not edit_ok"
+ tal:omit-tag="python:1" i18n:translate="">User<tal:x
+ replace="context/id" i18n:name="id" /></span>
+ <span tal:condition="python: context.id and edit_ok"
+ tal:omit-tag="python:1" i18n:translate="">User<tal:x
+ replace="context/id" i18n:name="id" /> Editing</span>
+</tal:block>
+
+<td class="content" metal:fill-slot="content">
+
+<p tal:condition="python:not (context.is_view_ok()
+ or request.user.hasRole('Anonymous'))" i18n:translate="">
+ You are not allowed to view this page.</p>
+
+<p tal:condition="python:not context.is_view_ok()
+ and request.user.hasRole('Anonymous')" i18n:translate="">
+ Please login with your username and password.</p>
+
+<div tal:condition="context/is_view_ok">
+
+<form method="POST"
+ name="itemSynopsis"
+ tal:define="required python:'username address'.split()"
+ enctype="multipart/form-data"
+ tal:attributes="action context/designator;
+ onSubmit python:'return checkRequiredFields(\'%s\')'%'\', \''.join(required);
+ ">
+<table class="form" tal:define="
+ th_label templates/page/macros/th_label;
+ src_input templates/page/macros/user_src_input;
+ normal_input templates/page/macros/user_normal_input;
+ pw_input templates/page/macros/user_pw_input;
+ confirm_input templates/page/macros/user_confirm_input;
+ edit_ok context/is_edit_ok;
+ ">
+ <tr tal:define="name string:realname; label string:Name; value context/realname; edit_ok edit_ok">
+ <th metal:use-macro="th_label">Name</th>
+ <td><input name="realname" metal:use-macro="src_input"></td>
+ </tr>
+ <tr tal:define="name string:username; label string:Login Name; value context/username">
+ <th metal:use-macro="th_label">Login Name</th>
+ <td><input metal:use-macro="src_input"></td>
+ </tr>
+ <tal:if condition="edit_ok">
+ <tr tal:define="name string:password; label string:Login Password">
+ <th metal:use-macro="th_label">Login Password</th>
+ <td><input metal:use-macro="pw_input" type="password"></td>
+ </tr>
+ <tr tal:define="name string:password; label string:Confirm Password">
+ <th metal:use-macro="th_label">Confirm Password</th>
+ <td><input metal:use-macro="confirm_input" type="password"></td>
+ </tr>
+ </tal:if>
+ <tal:if condition="python:request.user.hasPermission('Web Roles')">
+ <tr tal:define="name string:roles; label string:Roles;">
+ <th><label for="roles" i18n:translate="">Roles</label></th>
+ <td tal:define="gips context/id">
+ <tal:subif condition=gips define="value context/roles">
+ <input metal:use-macro="normal_input">
+ </tal:subif>
+ <tal:subif condition="not:gips" define="value db/config/NEW_WEB_USER_ROLES">
+ <input metal:use-macro="normal_input">
+ </tal:subif>
+ <tal:block i18n:translate="">(to give the user more than one role,
+ enter a comma,separated,list)</tal:block>
+ </td>
+ </tr>
+ </tal:if>
+
+ <tr tal:define="name string:phone; label string:Phone; value context/phone">
+ <th metal:use-macro="th_label">Phone</th>
+ <td><input name="phone" metal:use-macro="normal_input"></td>
+ </tr>
+
+ <tr tal:define="name string:organisation; label string:Organisation; value context/organisation">
+ <th metal:use-macro="th_label">Organisation</th>
+ <td><input name="organisation" metal:use-macro="normal_input"></td>
+ </tr>
+
+ <tr tal:condition="python:edit_ok or context.timezone"
+ tal:define="name string:timezone; label string:Timezone; value context/timezone">
+ <th metal:use-macro="th_label">Timezone</th>
+ <td><input name="timezone" metal:use-macro="normal_input">
+ <tal:block tal:condition="edit_ok" i18n:translate="">(this is a numeric hour offset, the default is
+ <span tal:replace="db/config/DEFAULT_TIMEZONE" i18n:name="zone"
+ />)</tal:block>
+ </td>
+ </tr>
+
+ <tr tal:define="name string:address; label string:E-mail address; value context/address">
+ <th metal:use-macro="th_label">E-mail address</th>
+ <td tal:define="mailto python:context.address.field(id='address');
+ mklink python:mailto and not edit_ok">
+ <a href="mailto:calvin@the-z.org"
+ tal:attributes="href string:mailto:$value"
+ tal:content="value"
+ tal:condition="python:mklink">calvin@the-z.org</a>
+ <tal:if condition=edit_ok>
+ <input metal:use-macro="src_input" value="calvin@the-z.org">
+ </tal:if>
+
+ </td>
+ </tr>
+
+ <tr>
+ <th><label for="alternate_addresses" i18n:translate="">Alternate E-mail addresses<br>One address per line</label></th>
+ <td>
+ <textarea rows=5 cols=40 tal:replace="structure context/alternate_addresses/multiline">nobody@nowhere.org
+anybody@everywhere.net
+(alternate_addresses)
+ </textarea>
+ </td>
+ </tr>
+
+ <tr tal:condition="edit_ok">
+ <td>
+
+ <input type="hidden" name="@template" value="item">
+ <input type="hidden" name="@required" value="username,address"
+ tal:attributes="value python:','.join(required)">
+ </td>
+ <td><input type="submit" value="save" tal:replace="structure context/submit"><!--submit button here-->
+ <input type=reset>
+ </td>
+ </tr>
+</table>
+</form>
+
+<tal:block tal:condition="not:context/id" i18n:translate="">
+<table class="form">
+<tr>
+ <td>Note: </td>
+ <th class="required">highlighted</th>
+ <td> fields are required.</td>
+</tr>
+</table>
+</tal:block>
+
+<tal:block tal:condition="context/id" tal:replace="structure context/history" />
+
+</div>
+
+</td>
+
+</tal:doc>
diff --git a/share/roundup/templates/classic/html/user.register.html b/share/roundup/templates/classic/html/user.register.html
--- /dev/null
@@ -0,0 +1,81 @@
+<!-- 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"
+ i18n:translate="">Registering with <span i18n:name="tracker"
+ tal:replace="db/config/TRACKER_NAME" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">Registering with <span i18n:name="tracker"
+ tal:replace="db/config/TRACKER_NAME" /></span>
+<td class="content" metal:fill-slot="content">
+
+<form method="POST" onSubmit="return submit_once()"
+ enctype="multipart/form-data"
+ tal:attributes="action context/designator">
+
+<table class="form">
+ <tr>
+ <th i18n:translate="">Name</th>
+ <td tal:content="structure context/realname/field">realname</td>
+ </tr>
+ <tr>
+ <th class="required" i18n:translate="">Login Name</th>
+ <td tal:content="structure context/username/field">username</td>
+ </tr>
+ <tr>
+ <th class="required" i18n:translate="">Login Password</th>
+ <td tal:content="structure context/password/field">password</td>
+ </tr>
+ <tr>
+ <th class="required" i18n:translate="">Confirm Password</th>
+ <td tal:content="structure context/password/confirm">password</td>
+ </tr>
+ <tr tal:condition="python:request.user.hasPermission('Web Roles')">
+ <th i18n:translate="">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 i18n:translate="">Phone</th>
+ <td tal:content="structure context/phone/field">phone</td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Organisation</th>
+ <td tal:content="structure context/organisation/field">organisation</td>
+ </tr>
+ <tr>
+ <th class="required" i18n:translate="">E-mail address</th>
+ <td tal:content="structure context/address/field">address</td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Alternate E-mail addresses<br>One address per line</th>
+ <td tal:content="structure context/alternate_addresses/multiline">alternate_addresses</td>
+ </tr>
+
+ <tr>
+ <td> </td>
+ <td>
+ <input type="hidden" name="@template" value="register">
+ <input type="hidden" name="@required" value="username,password,address">
+ <input type="hidden" name="@action" value="register">
+ <input type="submit" name="submit" value="Register" i18n:attributes="value">
+ </td>
+ </tr>
+</table>
+</form>
+
+<tal:block tal:condition="not:context/id" i18n:translate="">
+<table class="form">
+<tr>
+ <td>Note: </td>
+ <th class="required">highlighted</th>
+ <td> fields are required.</td>
+</tr>
+</table>
+</tal:block>
+
+</td>
+
+</tal:block>
diff --git a/share/roundup/templates/classic/html/user.rego_progress.html b/share/roundup/templates/classic/html/user.rego_progress.html
--- /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"
+ i18n:translate="">Registration in progress - <span i18n:name="tracker"
+ tal:replace="config/TRACKER_NAME" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">Registration in progress...</span>
+<td class="content" metal:fill-slot="content">
+
+<p i18n:translate="">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/share/roundup/templates/classic/html/user_utils.js b/share/roundup/templates/classic/html/user_utils.js
--- /dev/null
@@ -0,0 +1,114 @@
+// User Editing Utilities
+
+/**
+ * for new users:
+ * Depending on the input field which calls it, takes the value
+ * and dispatches it to certain other input fields:
+ *
+ * address
+ * +-> username
+ * | `-> realname
+ * `-> organisation
+ */
+function split_name(that) {
+ var raw = that.value
+ var val = trim(raw)
+ if (val == '') {
+ return
+ }
+ var username=''
+ var realname=''
+ var address=''
+ switch (that.name) {
+ case 'address':
+ address=val
+ break
+ case 'username':
+ username=val
+ break
+ case 'realname':
+ realname=val
+ break
+ case 'firstname':
+ case 'lastname':
+ return
+ default:
+ alert('Ooops - unknown name field '+that.name+'!')
+ return
+ }
+ var the_form = that.form;
+
+ function field_empty(name) {
+ return the_form[name].value == ''
+ }
+
+ // no break statements - on purpose!
+ switch (that.name) {
+ case 'address':
+ var split1 = address.split('@')
+ if (field_empty('username')) {
+ username = split1[0]
+ the_form.username.value = username
+ }
+ if (field_empty('organisation')) {
+ the_form.organisation.value = default_organisation(split1[1])
+ }
+ case 'username':
+ if (field_empty('realname')) {
+ realname = Cap(username.split('.').join(' '))
+ the_form.realname.value = realname
+ }
+ case 'realname':
+ if (field_empty('username')) {
+ username = Cap(realname.replace(' ', '.'))
+ the_form.username.value = username
+ }
+ if (the_form.firstname && the_form.lastname) {
+ var split2 = realname.split(' ')
+ var firstname='', lastname=''
+ firstname = split2[0]
+ lastname = split2.slice(1).join(' ')
+ if (field_empty('firstname')) {
+ the_form.firstname.value = firstname
+ }
+ if (field_empty('lastname')) {
+ the_form.lastname.value = lastname
+ }
+ }
+ }
+}
+
+function SubCap(str) {
+ switch (str) {
+ case 'de': case 'do': case 'da':
+ case 'du': case 'von':
+ return str;
+ }
+ if (str.toLowerCase().slice(0,2) == 'mc') {
+ return 'Mc'+str.slice(2,3).toUpperCase()+str.slice(3).toLowerCase()
+ }
+ return str.slice(0,1).toUpperCase()+str.slice(1).toLowerCase()
+}
+
+function Cap(str) {
+ var liz = str.split(' ')
+ for (var i=0; i<liz.length; i++) {
+ liz[i] = SubCap(liz[i])
+ }
+ return liz.join(' ')
+}
+
+/**
+ * Takes a domain name (behind the @ part of an email address)
+ * Customise this to handle the mail domains you're interested in
+ */
+function default_organisation(orga) {
+ switch (orga.toLowerCase()) {
+ case 'gmx':
+ case 'yahoo':
+ return ''
+ default:
+ return orga
+ }
+}
+
diff --git a/share/roundup/templates/classic/initial_data.py b/share/roundup/templates/classic/initial_data.py
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# TRACKER 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=admin_email, roles='Admin')
+user.create(username="anonymous", roles='Anonymous')
+
+# add any additional database creation steps here - but only if you
+# haven't initialised the database with the admin "initialise" command
+
+
+# vim: set filetype=python sts=4 sw=4 et si
+#SHA: b1da2e72a7fe9f26086f243eb744135b085101d9
diff --git a/share/roundup/templates/classic/schema.py b/share/roundup/templates/classic/schema.py
--- /dev/null
@@ -0,0 +1,169 @@
+
+#
+# TRACKER SCHEMA
+#
+
+# Class automatically gets these properties:
+# creation = Date()
+# activity = Date()
+# creator = Link('user')
+# actor = Link('user')
+
+# Priorities
+pri = Class(db, "priority",
+ name=String(),
+ order=Number())
+pri.setkey("name")
+
+# Statuses
+stat = Class(db, "status",
+ name=String(),
+ order=Number())
+stat.setkey("name")
+
+# Keywords
+keyword = Class(db, "keyword",
+ name=String())
+keyword.setkey("name")
+
+# User-defined saved searches
+query = Class(db, "query",
+ klass=String(),
+ name=String(),
+ url=String(),
+ private_for=Link('user'))
+
+# add any additional database schema configuration here
+
+user = Class(db, "user",
+ username=String(),
+ password=Password(),
+ address=String(),
+ realname=String(),
+ phone=String(),
+ organisation=String(),
+ alternate_addresses=String(),
+ queries=Multilink('query'),
+ roles=String(), # comma-separated string of Role names
+ timezone=String())
+user.setkey("username")
+
+# FileClass automatically gets this property in addition to the Class ones:
+# content = String() [saved to disk in <tracker home>/db/files/]
+# type = String() [MIME type of the content, default 'text/plain']
+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())
+
+# IssueClass automatically gets these properties in addition to the Class ones:
+# title = String()
+# messages = Multilink("msg")
+# files = Multilink("file")
+# nosy = Multilink("user")
+# superseder = Multilink("issue")
+issue = IssueClass(db, "issue",
+ assignedto=Link("user"),
+ keyword=Multilink("keyword"),
+ priority=Link("priority"),
+ status=Link("status"))
+
+#
+# TRACKER SECURITY SETTINGS
+#
+# See the configuration and customisation document for information
+# about security setup.
+
+#
+# REGULAR USERS
+#
+# Give the regular users access to the web and email interface
+db.security.addPermissionToRole('User', 'Web Access')
+db.security.addPermissionToRole('User', 'Email Access')
+
+# Assign the access and edit Permissions for issue, file and message
+# to regular users now
+for cl in 'issue', 'file', 'msg', 'keyword':
+ db.security.addPermissionToRole('User', 'View', cl)
+ db.security.addPermissionToRole('User', 'Edit', cl)
+ db.security.addPermissionToRole('User', 'Create', cl)
+for cl in 'priority', 'status':
+ db.security.addPermissionToRole('User', 'View', cl)
+
+# May users view other user information? Comment these lines out
+# if you don't want them to
+db.security.addPermissionToRole('User', 'View', 'user')
+
+# Users should be able to edit their own details -- this permission is
+# limited to only the situation where the Viewed or Edited item is their own.
+def own_record(db, userid, itemid):
+ '''Determine whether the userid matches the item being accessed.'''
+ return userid == itemid
+p = db.security.addPermission(name='View', klass='user', check=own_record,
+ description="User is allowed to view their own user details")
+db.security.addPermissionToRole('User', p)
+p = db.security.addPermission(name='Edit', klass='user', check=own_record,
+ description="User is allowed to edit their own user details")
+db.security.addPermissionToRole('User', p)
+
+# Users should be able to edit and view their own queries. They should also
+# be able to view any marked as not private. They should not be able to
+# edit others' queries, even if they're not private
+def view_query(db, userid, itemid):
+ private_for = db.query.get(itemid, 'private_for')
+ if not private_for: return True
+ return userid == private_for
+def edit_query(db, userid, itemid):
+ return userid == db.query.get(itemid, 'creator')
+p = db.security.addPermission(name='View', klass='query', check=view_query,
+ description="User is allowed to view their own and public queries")
+db.security.addPermissionToRole('User', p)
+p = db.security.addPermission(name='Edit', klass='query', check=edit_query,
+ description="User is allowed to edit their queries")
+db.security.addPermissionToRole('User', p)
+p = db.security.addPermission(name='Create', klass='query',
+ description="User is allowed to create queries")
+db.security.addPermissionToRole('User', p)
+
+
+#
+# ANONYMOUS USER PERMISSIONS
+#
+# Let anonymous users access the web interface. Note that almost all
+# trackers will need this Permission. The only situation where it's not
+# required is in a tracker that uses an HTTP Basic Authenticated front-end.
+db.security.addPermissionToRole('Anonymous', 'Web Access')
+
+# Let anonymous users access the email interface (note that this implies
+# that they will be registered automatically, hence they will need the
+# "Create" user Permission below)
+# This is disabled by default to stop spam from auto-registering users on
+# public trackers.
+#db.security.addPermissionToRole('Anonymous', 'Email Access')
+
+# Assign the appropriate permissions to the anonymous user's Anonymous
+# Role. Choices here are:
+# - Allow anonymous users to register
+db.security.addPermissionToRole('Anonymous', 'Create', 'user')
+
+# Allow anonymous users access to view issues (and the related, linked
+# information)
+for cl in 'issue', 'file', 'msg', 'keyword', 'priority', 'status':
+ db.security.addPermissionToRole('Anonymous', 'View', cl)
+
+# [OPTIONAL]
+# Allow anonymous users access to create or edit "issue" items (and the
+# related file and message items)
+#for cl in 'issue', 'file', 'msg':
+# db.security.addPermissionToRole('Anonymous', 'Create', cl)
+# db.security.addPermissionToRole('Anonymous', 'Edit', cl)
+
+
+# vim: set filetype=python sts=4 sw=4 et si :
diff --git a/share/roundup/templates/minimal/.cvsignore b/share/roundup/templates/minimal/.cvsignore
--- /dev/null
@@ -0,0 +1,4 @@
+*.pyc
+*.pyo
+htmlbase.py
+*.cover
diff --git a/share/roundup/templates/minimal/TEMPLATE-INFO.txt b/share/roundup/templates/minimal/TEMPLATE-INFO.txt
--- /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/share/roundup/templates/minimal/detectors/.cvsignore b/share/roundup/templates/minimal/detectors/.cvsignore
--- /dev/null
@@ -0,0 +1,3 @@
+*.pyc
+*.pyo
+*.cover
diff --git a/share/roundup/templates/minimal/detectors/userauditor.py b/share/roundup/templates/minimal/detectors/userauditor.py
--- /dev/null
@@ -0,0 +1,94 @@
+# Copyright (c) 2003 Richard Jones (richard@mechanicalcat.net)
+#
+# 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: userauditor.py,v 1.8 2007-09-12 21:11:14 jpend Exp $
+
+import re
+
+# regular expression thanks to: http://www.regular-expressions.info/email.html
+# this is the "99.99% solution for syntax only".
+email_regexp = (r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*", r"(localhost|(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9]))")
+email_rfc = re.compile('^' + email_regexp[0] + '@' + email_regexp[1] + '$', re.IGNORECASE)
+email_local = re.compile('^' + email_regexp[0] + '$', re.IGNORECASE)
+
+def valid_address(address):
+ ''' If we see an @-symbol in the address then check against the full
+ RFC syntax. Otherwise it is a local-only address so only check
+ the local part of the RFC syntax.
+ '''
+ if '@' in address:
+ return email_rfc.match(address)
+ else:
+ return email_local.match(address)
+
+def get_addresses(user):
+ ''' iterate over all known addresses in a newvalues dict
+ this takes of the address/alterate_addresses handling
+ '''
+ if user.has_key('address'):
+ yield user['address']
+ if user.get('alternate_addresses', None):
+ for address in user['alternate_addresses'].split('\n'):
+ yield address
+
+def audit_user_fields(db, cl, nodeid, newvalues):
+ ''' Make sure user properties are valid.
+
+ - email address is syntactically valid
+ - email address is unique
+ - roles specified exist
+ - timezone is valid
+ '''
+
+ for address in get_addresses(newvalues):
+ if not valid_address(address):
+ raise ValueError, 'Email address syntax is invalid'
+
+ check_main = db.user.stringFind(address=address)
+ # make sure none of the alts are owned by anyone other than us (x!=nodeid)
+ check_alts = [x for x in db.user.filter(None, {'alternate_addresses' : address}) if x != nodeid]
+ if check_main or check_alts:
+ raise ValueError, 'Email address %s already in use' % address
+
+ for rolename in [r.lower().strip() for r in newvalues.get('roles', '').split(',')]:
+ if rolename and not db.security.role.has_key(rolename):
+ raise ValueError, 'Role "%s" does not exist'%rolename
+
+ tz = newvalues.get('timezone', None)
+ if tz:
+ # if they set a new timezone validate the timezone by attempting to
+ # use it before we store it to the db.
+ import roundup.date
+ import datetime
+ try:
+ TZ = roundup.date.get_timezone(tz)
+ dt = datetime.datetime.now()
+ local = TZ.localize(dt).utctimetuple()
+ except IOError:
+ raise ValueError, 'Timezone "%s" does not exist' % tz
+ except ValueError:
+ raise ValueError, 'Timezone "%s" exceeds valid range [-23...23]' % tz
+
+def init(db):
+ # fire before changes are made
+ db.user.audit('set', audit_user_fields)
+ db.user.audit('create', audit_user_fields)
+
+# vim: sts=4 sw=4 et si
diff --git a/share/roundup/templates/minimal/extensions/README.txt b/share/roundup/templates/minimal/extensions/README.txt
--- /dev/null
@@ -0,0 +1,6 @@
+This directory is for tracker extensions:
+
+- CGI Actions
+- Templating functions
+
+See the customisation doc for more information.
diff --git a/share/roundup/templates/minimal/html/_generic.404.html b/share/roundup/templates/minimal/html/_generic.404.html
--- /dev/null
@@ -0,0 +1,9 @@
+<html>
+<head>
+<title>Item Not Found</title>
+</head>
+
+<body>
+There is no <span tal:content="context/_classname" /> with id <span tal:content="context/id"/>
+</body>
+</html>
diff --git a/share/roundup/templates/minimal/html/_generic.calendar.html b/share/roundup/templates/minimal/html/_generic.calendar.html
--- /dev/null
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="@@file/style.css" />
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8;" />
+ <title tal:content="string:Roundup Calendar"></title>
+ <script language="Javascript"
+ type="text/javascript"
+ tal:content="structure string:
+ // this is the name of the field in the original form that we're working on
+ form = window.opener.document.${request/form/form/value};
+ field = '${request/form/property/value}';" >
+ </script>
+ </head>
+ <body class="body"
+ tal:content="structure python:utils.html_calendar (request)">
+ </body>
+</html>
diff --git a/share/roundup/templates/minimal/html/_generic.collision.html b/share/roundup/templates/minimal/html/_generic.collision.html
--- /dev/null
@@ -0,0 +1,16 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title" i18n:translate=""
+ ><span tal:replace="python:context._classname.capitalize()"
+ i18n:name="class" /> Edit Collision - <span i18n:name="tracker"
+ tal:replace="config/TRACKER_NAME" /></title>
+<tal:block metal:fill-slot="body_title" i18n:translate=""
+ ><span tal:replace="python:context._classname.capitalize()"
+ i18n:name="class" /> Edit Collision</tal:block>
+
+<td class="content" metal:fill-slot="content" i18n:translate="
+ There has been a collision. Another user updated this node
+ while you were editing. Please <a href='${context}'>reload</a>
+ the node and review your edits.
+"><span tal:replace="context/designator" i18n:name="context" />
+</td>
+</tal:block>
diff --git a/share/roundup/templates/minimal/html/_generic.help.html b/share/roundup/templates/minimal/html/_generic.help.html
--- /dev/null
@@ -0,0 +1,98 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html tal:define="property request/form/property/value" >
+ <head>
+ <link rel="stylesheet" type="text/css" href="@@file/style.css" />
+ <meta http-equiv="Content-Type"
+ tal:attributes="content string:text/html;; charset=${request/client/charset}" />
+ <tal:block tal:condition="python:request.form.has_key('property')">
+ <title i18n:translate=""><tal:x i18n:name="property"
+ tal:content="property" i18n:translate="" /> help - <span i18n:name="tracker"
+ tal:replace="config/TRACKER_NAME" /></title>
+ <script language="Javascript" type="text/javascript"
+ tal:content="structure string:
+ // this is the name of the field in the original form that we're working on
+ form = window.opener.document.${request/form/form/value};
+ field = '${request/form/property/value}';">
+ </script>
+ <script src="@@file/help_controls.js" type="text/javascript"><!--
+ //--></script>
+ </tal:block>
+ </head>
+ <body class="body" onload="resetList();">
+ <form name="frm_help" tal:attributes="action request/base"
+ tal:define="batch request/batch;
+ props python:request.form['properties'].value.split(',')">
+
+ <div id="classhelp-controls">
+ <!--input type="button" name="btn_clear"
+ value="Clear" onClick="clearList()"/ -->
+ <input type="text" name="text_preview" size="24" class="preview"
+ onchange="reviseList(this.value);"/>
+ <input type="button" name="btn_reset"
+ value=" Cancel " onclick="resetList(); window.close();"
+ i18n:attributes="value" />
+ <input type="button" name="btn_apply" class="apply"
+ value=" Apply " onclick="updateList(); window.close();"
+ i18n:attributes="value" />
+ </div>
+ <table width="100%">
+ <tr class="navigation">
+ <th>
+ <a tal:define="prev batch/previous" tal:condition="prev"
+ tal:attributes="href python:request.indexargs_url(request.classname,
+ {'@template':'help', 'property': request.form['property'].value,
+ 'properties': request.form['properties'].value,
+ 'form': request.form['form'].value,
+ 'type': request.form['type'].value,
+ '@startwith':prev.first, '@pagesize':prev.size})"
+ i18n:translate="" ><< previous</a>
+
+ </th>
+ <th i18n:translate=""><span tal:replace="batch/start" i18n:name="start"
+ />..<span tal:replace="python: batch.start + batch.length -1" i18n:name="end"
+ /> out of <span tal:replace="batch/sequence_length" i18n:name="total"
+ />
+ </th>
+ <th>
+ <a tal:define="next batch/next" tal:condition="next"
+ tal:attributes="href python:request.indexargs_url(request.classname,
+ {'@template':'help', 'property': request.form['property'].value,
+ 'properties': request.form['properties'].value,
+ 'form': request.form['form'].value,
+ 'type': request.form['type'].value,
+ '@startwith':next.first, '@pagesize':next.size})"
+ i18n:translate="" >next >></a>
+
+ </th>
+ </tr>
+ </table>
+
+ <table class="classhelp">
+ <tr>
+ <th> <b>x</b></th>
+ <th tal:repeat="prop props" tal:content="prop" i18n:translate=""></th>
+ </tr>
+ <tr tal:repeat="item batch">
+ <tal:block tal:define="attr python:item[props[0]]" >
+ <td>
+ <input name="check"
+ onclick="updatePreview();"
+ tal:attributes="type python:request.form['type'].value;
+ value attr; id string:id_$attr" />
+ </td>
+ <td tal:repeat="prop props">
+ <label class="classhelp-label"
+ tal:attributes="for string:id_$attr"
+ tal:content="python:item[prop]"></label>
+ </td>
+ </tal:block>
+ </tr>
+ <tr>
+ <th> <b>x</b></th>
+ <th tal:repeat="prop props" tal:content="prop" i18n:translate=""></th>
+ </tr>
+ </table>
+
+ </form>
+ </body>
+</html>
diff --git a/share/roundup/templates/minimal/html/_generic.index.html b/share/roundup/templates/minimal/html/_generic.index.html
--- /dev/null
@@ -0,0 +1,70 @@
+<!-- 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" i18n:translate=""
+ ><span tal:replace="python:context._classname.capitalize()"
+ i18n:name="class" /> editing - <span i18n:name="tracker"
+ tal:replace="config/TRACKER_NAME" /></title>
+<tal:block metal:fill-slot="body_title" i18n:translate=""
+ ><span tal:replace="python:context._classname.capitalize()"
+ i18n:name="class" /> editing</tal:block>
+
+<td class="content" metal:fill-slot="content">
+
+<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok()
+ or request.user.hasRole('Anonymous'))"
+ tal:omit-tag="python:1" i18n:translate=""
+>You are not allowed to view this page.</span>
+
+<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())
+ and request.user.hasRole('Anonymous')"
+ tal:omit-tag="python:1" i18n:translate=""
+>Please login with your username and password.</span>
+
+<tal:block tal:condition="context/is_edit_ok">
+<tal:block i18n:translate="">
+<p class="form-help">
+ You may edit the contents of the
+ <span tal:replace="request/classname" i18n:name="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>
+</tal:block>
+<form onSubmit="return submit_once()" method="POST"
+ tal:attributes="action context/designator">
+<textarea rows="15" style="width:90%" name="rows" tal:content="context/csv"></textarea>
+<br>
+<input type="hidden" name="@action" value="editCSV">
+<input type="submit" value="Edit Items" i18n:attributes="value">
+</form>
+</tal:block>
+
+<table tal:condition="context/is_only_view_ok" width="100%" class="list">
+ <tr>
+ <th tal:repeat="property context/propnames" tal:content="property"> </th>
+ </tr>
+ <tal:block repeat="item context/list">
+ <tr tal:condition="item/is_view_ok"
+ tal:attributes="class python:['normal', 'alt'][repeat['item'].index%6/3]">
+ <td tal:repeat="property context/propnames"
+ tal:content="python: item[property] or default"
+ > </td>
+ </tr>
+ </tal:block>
+</table>
+
+</td>
+
+</tal:block>
diff --git a/share/roundup/templates/minimal/html/_generic.item.html b/share/roundup/templates/minimal/html/_generic.item.html
--- /dev/null
@@ -0,0 +1,65 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title" i18n:translate=""
+ ><span tal:replace="python:context._classname.capitalize()"
+ i18n:name="class" /> editing - <span i18n:name="tracker"
+ tal:replace="config/TRACKER_NAME" /></title>
+<tal:block metal:fill-slot="body_title" i18n:translate=""
+ ><span tal:replace="python:context._classname.capitalize()"
+ i18n:name="class" /> editing</tal:block>
+
+<td class="content" metal:fill-slot="content">
+
+<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok()
+ or request.user.hasRole('Anonymous'))"
+ tal:omit-tag="python:1" i18n:translate=""
+>You are not allowed to view this page.</span>
+
+<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())
+ and request.user.hasRole('Anonymous')"
+ tal:omit-tag="python:1" i18n:translate=""
+>Please login with your username and password.</span>
+
+<form method="POST" onSubmit="return submit_once()"
+ enctype="multipart/form-data" tal:condition="context/is_edit_ok"
+ tal:attributes="action context/designator">
+
+<input type="hidden" name="@template" value="item">
+
+<table class="form">
+
+<tr tal:repeat="prop python:db[context._classname].properties()">
+ <tal:block tal:condition="python:prop._name not in ('id',
+ 'creator', 'creation', 'actor', 'activity')">
+ <th tal:content="prop/_name"></th>
+ <td tal:content="structure python:context[prop._name].field()"></td>
+ </tal:block>
+</tr>
+<tr>
+ <td> </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/share/roundup/templates/minimal/html/help_controls.js b/share/roundup/templates/minimal/html/help_controls.js
--- /dev/null
@@ -0,0 +1,111 @@
+// initial values for either Nosy, Superseder, Keyword and Waiting On,
+// depending on which has called
+original_field = form[field].value;
+
+// Some browsers (ok, IE) don't define the "undefined" variable.
+undefined = document.geez_IE_is_really_friggin_annoying;
+
+function trim(value) {
+ var temp = value;
+ var obj = /^(\s*)([\W\w]*)(\b\s*$)/;
+ if (obj.test(temp)) { temp = temp.replace(obj, '$2'); }
+ var obj = / /g;
+ while (temp.match(obj)) { temp = temp.replace(obj, " "); }
+ return temp;
+}
+
+function determineList() {
+ // generate a comma-separated list of the checked items
+ var list = new String('');
+ for (box=0; box < document.frm_help.check.length; box++) {
+ if (document.frm_help.check[box].checked) {
+ if (list.length == 0) {
+ separator = '';
+ }
+ else {
+ separator = ',';
+ }
+ // we used to use an Array and push / join, but IE5.0 sux
+ list = list + separator + document.frm_help.check[box].value;
+ }
+ }
+ return list;
+}
+
+function updateList() {
+ // write back to opener window
+ if (document.frm_help.check==undefined) { return; }
+ form[field].value = determineList();
+}
+
+function updatePreview() {
+ // update the preview box
+ if (document.frm_help.check==undefined) { return; }
+ writePreview(determineList());
+}
+
+function clearList() {
+ // uncheck all checkboxes
+ if (document.frm_help.check==undefined) { return; }
+ for (box=0; box < document.frm_help.check.length; box++) {
+ document.frm_help.check[box].checked = false;
+ }
+}
+
+function reviseList(vals) {
+ // update the checkboxes based on the preview field
+ if (document.frm_help.check==undefined) { return; }
+ var to_check;
+ var list = vals.split(",");
+ if (document.frm_help.check.length==undefined) {
+ check = document.frm_help.check;
+ to_check = false;
+ for (val in list) {
+ if (check.value==trim(list[val])) {
+ to_check = true;
+ break;
+ }
+ }
+ check.checked = to_check;
+ } else {
+ for (box=0; box < document.frm_help.check.length; box++) {
+ check = document.frm_help.check[box];
+ to_check = false;
+ for (val in list) {
+ if (check.value==trim(list[val])) {
+ to_check = true;
+ break;
+ }
+ }
+ check.checked = to_check;
+ }
+ }
+}
+
+function resetList() {
+ // reset preview and check boxes to initial values
+ if (document.frm_help.check==undefined) { return; }
+ writePreview(original_field);
+ reviseList(original_field);
+}
+
+function writePreview(val) {
+ // writes a value to the text_preview
+ document.frm_help.text_preview.value = val;
+}
+
+function focusField(name) {
+ for(i=0; i < document.forms.length; ++i) {
+ var obj = document.forms[i].elements[name];
+ if (obj && obj.focus) {obj.focus();}
+ }
+}
+
+function selectField(name) {
+ for(i=0; i < document.forms.length; ++i) {
+ var obj = document.forms[i].elements[name];
+ if (obj && obj.focus){obj.focus();}
+ if (obj && obj.select){obj.select();}
+ }
+}
+
diff --git a/share/roundup/templates/minimal/html/home.classlist.html b/share/roundup/templates/minimal/html/home.classlist.html
--- /dev/null
@@ -0,0 +1,25 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title" i18n:translate="">List of classes - <span
+ i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">List of classes</span>
+<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/share/roundup/templates/minimal/html/home.html b/share/roundup/templates/minimal/html/home.html
--- /dev/null
@@ -0,0 +1,25 @@
+<tal:block metal:use-macro="templates/page/macros/icing">
+<title metal:fill-slot="head_title" i18n:translate="">Tracker home - <span
+ i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">Tracker home</span>
+<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" i18n:translate="">
+Please select from one of the menu options on the left.
+</p>
+<p tal:condition="anon" class="help" i18n:translate="">
+Please log in or register.
+</p>
+</tal:block>
+
+</td>
+</tal:block>
diff --git a/share/roundup/templates/minimal/html/page.html b/share/roundup/templates/minimal/html/page.html
--- /dev/null
@@ -0,0 +1,334 @@
+<!-- vim:sw=2 sts=2
+--><tal:block metal:define-macro="icing"
+><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title metal:define-slot="head_title">title goes here</title>
+<link rel="stylesheet" type="text/css" href="@@file/style.css">
+<meta http-equiv="Content-Type"
+ tal:attributes="content string:text/html;; charset=${request/client/charset}" />
+<script tal:replace="structure request/base_javascript">
+</script>
+<metal:x define-slot="more-javascript" />
+
+</head>
+<body class="body">
+
+<table class="body"
+ tal:define="
+kw_edit python:request.user.hasPermission('Edit', 'keyword');
+kw_create python:request.user.hasPermission('Create', 'keyword');
+kw_edit_link python:kw_edit and db.keyword.list();
+columns string:id,activity,title,creator,status;
+columns_showall string:id,activity,title,creator,assignedto,status;
+status_notresolved string:-1,1,2,3,4,5,6,7;
+"
+>
+
+<tr>
+ <td class="page-header-left"> </td>
+ <td class="page-header-top">
+ <div id="body-title">
+ <h2><span metal:define-slot="body_title">body title</span></h2>
+ </div>
+ <div id="searchbox">
+ <form method="GET" action="issue">
+ <input type="hidden" name="@columns"
+ tal:attributes="value columns_showall"
+ value="id,activity,title,creator,assignedto,status"/>
+ <input type="hidden" name="@sort" value="activity"/>
+ <input type="hidden" name="@group" value="priority"/>
+ <input id="search-text" name="@search_text" size="10"
+ tal:attributes="value request/search_text"/>
+ <input type="submit" id="submit" name="submit" value="Search" i18n:attributes="value" />
+ </form>
+ </div>
+ </td>
+</tr>
+
+<tr>
+ <td rowspan="2" valign="top" class="sidebar">
+ <p class="classblock"
+ tal:condition="python:request.user.hasPermission('View', 'query')">
+ <span i18n:translate=""
+ ><b>Your Queries</b> (<a href="query?@template=edit">edit</a>)</span><br>
+ <tal:block tal:repeat="qs request/user/queries">
+ <a href="#" tal:attributes="href string:${qs/klass}?${qs/url}&@dispname=${qs/name}"
+ tal:content="qs/name">link</a><br>
+ </tal:block>
+ </p>
+
+ <form method="POST" tal:attributes="action request/base">
+ <p class="classblock"
+ tal:condition="python:request.user.hasPermission('View', 'issue')">
+ <b i18n:translate="">Issues</b><br>
+ <span tal:condition="python:request.user.hasPermission('Create', 'issue')">
+ <a href="issue?@template=item" i18n:translate="">Create New</a><br>
+ </span>
+ <a href="#"
+ tal:attributes="href python:request.indexargs_url('issue', {
+ '@sort': '-activity',
+ '@group': 'priority',
+ '@filter': 'status,assignedto',
+ '@columns': columns,
+ '@search_text': '',
+ 'status': status_notresolved,
+ 'assignedto': '-1',
+ '@dispname': i18n.gettext('Show Unassigned'),
+ })"
+ i18n:translate="">Show Unassigned</a><br>
+ <a href="#"
+ tal:attributes="href python:request.indexargs_url('issue', {
+ '@sort': '-activity',
+ '@group': 'priority',
+ '@filter': 'status',
+ '@columns': columns_showall,
+ '@search_text': '',
+ 'status': status_notresolved,
+ '@dispname': i18n.gettext('Show All'),
+ })"
+ i18n:translate="">Show All</a><br>
+ <a href="issue?@template=search" i18n:translate="">Search</a><br>
+ <input type="submit" class="form-small" value="Show issue:"
+ i18n:attributes="value"><input class="form-small" 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:kw_edit or kw_create">
+ <b i18n:translate="">Keywords</b><br>
+ <span tal:condition="python:request.user.hasPermission('Create', 'keyword')">
+ <a href="keyword?@template=item" i18n:translate="">Create New</a><br>
+ </span>
+ <span tal:condition="kw_edit_link">
+ <a href="keyword?@template=item" i18n:translate="">Edit Existing</a><br>
+ </span>
+ </p>
+
+ <p class="classblock"
+ tal:condition="python:request.user.hasPermission('View', 'user')">
+ <b i18n:translate="">Administration</b><br>
+ <span tal:condition="python:request.user.hasPermission('Edit', None)">
+ <a href="home?@template=classlist" i18n:translate="">Class List</a><br>
+ </span>
+ <span tal:condition="python:request.user.hasPermission('View', 'user')
+ or request.user.hasPermission('Edit', 'user')">
+ <a href="user" i18n:translate="">User List</a><br>
+ </span>
+ <a tal:condition="python:request.user.hasPermission('Create', 'user')"
+ href="user?@template=item" i18n:translate="">Add User</a>
+ </p>
+
+ <form method="POST" tal:condition="python:request.user.username=='anonymous'"
+ tal:attributes="action request/base">
+ <p class="userblock">
+ <b i18n:translate="">Login</b><br>
+ <input size="10" name="__login_name"><br>
+ <input size="10" type="password" name="__login_password"><br>
+ <input type="hidden" name="@action" value="Login">
+ <input type="checkbox" name="remember" id="remember">
+ <label for="remember" i18n:translate="">Remember me?</label><br>
+ <input type="submit" value="Login" i18n:attributes="value"><br>
+ <input type="hidden" name="__came_from" tal:attributes="value string:${request/base}${request/env/PATH_INFO}">
+ <span tal:replace="structure request/indexargs_form" />
+ <a href="user?@template=register"
+ tal:condition="python:request.user.hasPermission('Create', 'user')"
+ i18n:translate="">Register</a><br>
+ <a href="user?@template=forgotten" i18n:translate="">Lost your login?</a><br>
+ </p>
+ </form>
+
+ <p class="userblock" tal:condition="python:request.user.username != 'anonymous'">
+ <b i18n:translate="">Hello, <span i18n:name="user"
+ tal:replace="python:request.user.username.plain(escape=1)">username</span></b><br>
+ <a href="#" tal:attributes="href string:user${request/user/id}"
+ i18n:translate="">Your Details</a><br>
+ <a href="#" tal:attributes="href python:request.indexargs_url('',
+ {'@action':'logout'})" i18n:translate="">Logout</a>
+ </p>
+ <p class="userblock">
+ <b i18n:translate="">Help</b><br>
+ <a href="http://roundup.sourceforge.net/doc-1.0/"
+ i18n:translate="">Roundup docs</a>
+ </p>
+ </td>
+ <td>
+ <p tal:condition="options/error_message | nothing" class="error-message"
+ tal:repeat="m options/error_message" tal:content="structure m" />
+ <p tal:condition="options/ok_message | nothing" class="ok-message">
+ <span tal:repeat="m options/ok_message"
+ tal:content="structure string:$m <br/ > " />
+ <a class="form-small" tal:attributes="href request/current_url"
+ i18n:translate="">clear this message</a>
+ </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>
+</tal:block>
+
+<!--
+The following macros are intended to be used in search pages.
+
+The invoking context must define a "name" variable which names the
+property being searched.
+
+See issue.search.html in the classic template for examples.
+-->
+
+<!-- creates a th and a label: -->
+<th metal:define-macro="th_label"
+ tal:define="required required | python:[]"
+ tal:attributes="class python:(name in required) and 'required' or nothing">
+ <label tal:attributes="for name" tal:content="label" i18n:translate="">text</label>
+ <metal:x define-slot="behind_the_label" />
+</th>
+
+<td metal:define-macro="search_input">
+ <input tal:attributes="value python:request.form.getvalue(name) or nothing;
+ name name;
+ id name">
+</td>
+
+<td metal:define-macro="search_date">
+ <input tal:attributes="value python:request.form.getvalue(name) or nothing;
+ name name;
+ id name">
+ <a class="classhelp"
+ tal:attributes="href python:'''javascript:help_window('issue?@template=calendar&property=%s&form=itemSynopsis', 300, 200)'''%name">(cal)</a>
+</td>
+
+<td metal:define-macro="search_popup">
+ <!--
+ context needs to specify the popup "columns" as a comma-separated
+ string (eg. "id,title" or "id,name,description") as well as name
+ -->
+ <input tal:attributes="value python:request.form.getvalue(name) or nothing;
+ name name;
+ id name">
+ <span tal:replace="structure python:db.issue.classhelp(columns,
+ property=name)" />
+</td>
+
+<td metal:define-macro="search_select">
+ <select tal:attributes="name name; id name"
+ tal:define="value python:request.form.getvalue(name)">
+ <option value="" i18n:translate="">don't care</option>
+ <metal:slot define-slot="extra_options" />
+ <option value="" i18n:translate="" disabled="disabled">------------</option>
+ <option tal:repeat="s python:db[db_klass].list()"
+ tal:attributes="value s/id; selected python:value == s.id"
+ tal:content="python:s[db_content]"></option>
+ </select>
+</td>
+
+<!-- like search_select, but translates the further values.
+Could extend it (METAL 1.1 attribute "extend-macro")
+-->
+<td metal:define-macro="search_select_translated">
+ <select tal:attributes="name name; id name"
+ tal:define="value python:request.form.getvalue(name)">
+ <option value="" i18n:translate="">don't care</option>
+ <metal:slot define-slot="extra_options" />
+ <option value="" i18n:translate="" disabled="disabled">------------</option>
+ <option tal:repeat="s python:db[db_klass].list()"
+ tal:attributes="value s/id; selected python:value == s.id"
+ tal:content="python:s[db_content]"
+ i18n:translate=""></option>
+ </select>
+</td>
+
+<!-- currently, there is no convenient API to get a list of all roles -->
+<td metal:define-macro="search_select_roles"
+ tal:define="onchange onchange | nothing">
+ <select name=roles id=roles tal:attributes="onchange onchange">
+ <option value="" i18n:translate="">don't care</option>
+ <option value="" i18n:translate="" disabled="disabled">------------</option>
+ <option value="User">User</option>
+ <option value="Admin">Admin</option>
+ <option value="Anonymous">Anonymous</option>
+ </select>
+</td>
+
+<td metal:define-macro="search_multiselect">
+ <input tal:attributes="value python:request.form.getvalue(name) or nothing;
+ name name;
+ id name">
+ <span tal:replace="structure python:db[db_klass].classhelp(db_content,
+ property=name, width='600')" />
+</td>
+
+<td metal:define-macro="search_checkboxes">
+ <ul class="search-checkboxes"
+ tal:define="value python:request.form.getvalue(name);
+ values python:value and value.split(',') or []">
+ <li tal:repeat="s python:db[db_klass].list()">
+ <input type="checkbox" tal:attributes="name name; id string:$name-${s/id};
+ value s/id; checked python:s.id in values" />
+ <label tal:attributes="for string:$name-${s/id}"
+ tal:content="python:s[db_content]" />
+ </li>
+ <li metal:define-slot="no_value_item">
+ <input type="checkbox" value="-1" tal:attributes="name name;
+ id string:$name--1; checked python:value == '-1'" />
+ <label tal:attributes="for string:$name--1" i18n:translate="">no value</label>
+ </li>
+ </ul>
+</td>
+
+<td metal:define-macro="column_input">
+ <input type="checkbox" name="@columns"
+ tal:attributes="value name;
+ checked python:name in cols">
+</td>
+
+<td metal:define-macro="sort_input">
+ <input type="radio" name="@sort"
+ tal:attributes="value name;
+ checked python:name == sort_on">
+</td>
+
+<td metal:define-macro="group_input">
+ <input type="radio" name="@group"
+ tal:attributes="value name;
+ checked python:name == group_on">
+</td>
+
+<!--
+The following macros are intended for user editing.
+
+The invoking context must define a "name" variable which names the
+property being searched; the "edit_ok" variable tells whether the
+current user is allowed to edit.
+
+See user.item.html in the classic template for examples.
+-->
+<script metal:define-macro="user_utils" type="text/javascript" src="@@file/user_utils.js"></script>
+
+<!-- src: value will be re-used for other input fields -->
+<input metal:define-macro="user_src_input"
+ type="text" tal:attributes="onblur python:edit_ok and 'split_name(this)';
+ id name; name name; value value; readonly not:edit_ok"
+ value="heinz.kunz">
+<!-- normal: no re-using -->
+<input metal:define-macro="user_normal_input" type="text"
+ tal:attributes="id name; name name; value value; readonly not:edit_ok"
+ value="heinz">
+<!-- password: type; no initial value -->
+ <input metal:define-macro="user_pw_input" type="password"
+ tal:attributes="id name; name name; readonly not:edit_ok" value="">
+ <input metal:define-macro="user_confirm_input" type="password"
+ tal:attributes="id name; name string:@confirm@$name; readonly not:edit_ok" value="">
+
diff --git a/share/roundup/templates/minimal/html/style.css b/share/roundup/templates/minimal/html/style.css
--- /dev/null
@@ -0,0 +1,423 @@
+/* main page styles */
+body.body {
+ font-family: sans-serif, Arial, Helvetica;
+ background-color: white;
+ color: #333;
+ margin: 0;
+}
+a[href]:hover {
+ color:blue;
+ text-decoration: underline;
+}
+a[href], a[href]:link {
+ color:blue;
+ text-decoration: none;
+}
+
+table.body {
+ border: 0;
+ padding: 0;
+ border-spacing: 0;
+ border-collapse: separate;
+}
+
+td.page-header-left {
+ padding: 5px;
+ border-bottom: 1px solid #444;
+}
+td.sidebar {
+ padding: 1px 0 0 1px;
+ white-space: nowrap;
+}
+
+/* don't display the sidebar when printing */
+@media print {
+ td.page-header-left {
+ display: none;
+ }
+ td.sidebar {
+ display: none;
+ }
+ .index-controls {
+ display: none;
+ }
+ #searchbox {
+ display: none;
+ }
+}
+
+td.page-header-top {
+ padding: 5px;
+ border-bottom: 1px solid #444;
+}
+#searchbox {
+ float: right;
+}
+
+div#body-title {
+ float: left;
+}
+
+
+div#searchbox {
+ float: right;
+ padding-top: 1em;
+}
+
+div#searchbox input#search-text {
+ width: 10em;
+}
+
+form {
+ margin: 0;
+}
+
+textarea {
+ font-family: monospace;
+}
+
+td.sidebar p.classblock {
+ padding: 2px 5px 2px 5px;
+ margin: 1px;
+ border: 1px solid #444;
+ background-color: #eee;
+}
+
+td.sidebar p.userblock {
+ padding: 2px 5px 2px 5px;
+ margin: 1px 1px 1px 1px;
+ border: 1px solid #444;
+ background-color: #eef;
+}
+
+.form-small {
+ padding: 0;
+ font-size: 75%;
+}
+
+
+td.content {
+ padding: 1px 5px 1px 5px;
+ vertical-align: top;
+ width: 100%;
+}
+
+td.date, th.date {
+ white-space: nowrap;
+}
+
+p.ok-message {
+ background-color: #22bb22;
+ padding: 5px;
+ color: white;
+ font-weight: bold;
+}
+p.error-message {
+ background-color: #bb2222;
+ padding: 5px;
+ color: white;
+ font-weight: bold;
+}
+p.error-message a[href] {
+ color: white;
+ text-decoration: underline;
+}
+
+
+/* style for search forms */
+ul.search-checkboxes {
+ display: inline;
+ padding: none;
+ list-style: none;
+}
+ul.search-checkboxes > li {
+ display: inline;
+ padding-right: .5em;
+}
+
+
+/* style for forms */
+table.form {
+ padding: 2px;
+ border-spacing: 0;
+ border-collapse: separate;
+}
+
+table.form th {
+ color: #338;
+ text-align: right;
+ vertical-align: top;
+ font-weight: normal;
+ white-space: nowrap;
+}
+
+table.form th.header {
+ font-weight: bold;
+ background-color: #eef;
+ text-align: left;
+}
+
+table.form th.required {
+ font-weight: bold;
+}
+
+table.form td {
+ color: #333;
+ empty-cells: show;
+ vertical-align: top;
+}
+
+table.form td.optional {
+ font-weight: bold;
+ font-style: italic;
+}
+
+table.form td.html {
+ color: #777;
+}
+
+/* style for lists */
+table.list {
+ border-spacing: 0;
+ border-collapse: separate;
+ width: 100%;
+}
+
+table.list th {
+ padding: 0 4px 0 4px;
+ color: #404070;
+ background-color: #eef;
+ 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 4px 0 4px;
+ border: 1px solid white;
+ color: #404070;
+ background-color: #efefef;
+ vertical-align: top;
+ empty-cells: show;
+}
+
+table.list tr.navigation th {
+ width: 33%;
+ border-style: hidden;
+ text-align: center;
+}
+table.list tr.navigation td {
+ border: none
+}
+table.list tr.navigation th:first-child {
+ text-align: left;
+}
+table.list tr.navigation th:last-child {
+ text-align: right;
+}
+
+
+/* style for message displays */
+table.messages {
+ border-spacing: 0;
+ 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: 2px 5px 2px 5px;
+}
+
+table.messages td:first-child {
+ border-left: 1px solid #afafaf;
+ border-right: 1px solid #afafaf;
+}
+
+/* style for file displays */
+table.files {
+ border-spacing: 0;
+ 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: 0;
+ 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: 0;
+ 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 { /* the table-layout: fixed; */
+ table-layout: fixed; /* compromises quality for speed */
+ overflow: hidden;
+ font-size: .9em;
+ padding-bottom: 3em;
+}
+
+table.classhelp th {
+ font-weight: normal;
+ text-align: left;
+ color: #444;
+ background-color: #efefef;
+ border-bottom: 1px solid #afafaf;
+ border-top: 1px solid #afafaf;
+ text-transform: uppercase;
+ vertical-align: middle;
+ line-height:1.5em;
+}
+
+table.classhelp td {
+ vertical-align: middle;
+ padding-right: .2em;
+ border-bottom: 1px solid #efefef;
+ text-align: left;
+ empty-cells: show;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+
+table.classhelp tr:hover {
+ background-color: #eee;
+}
+
+label.classhelp-label {
+ cursor: pointer;
+}
+
+#classhelp-controls {
+ position: fixed;
+ display: block;
+ top: auto;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ padding: .5em;
+ border-top: 2px solid #444;
+ background-color: #eee;
+}
+
+#classhelp-controls input.apply {
+ width: 7em;
+ font-weight: bold;
+ margin-right: 2em;
+ margin-left: 2em;
+}
+
+#classhelp-controls input.preview {
+ margin-right: 3em;
+ margin-left: 1em;
+}
+
+/* style for "other" displays */
+table.otherinfo {
+ border-spacing: 0;
+ 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/share/roundup/templates/minimal/html/user.index.html b/share/roundup/templates/minimal/html/user.index.html
--- /dev/null
@@ -0,0 +1,35 @@
+<!-- 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" i18n:translate="">User listing - <span
+ i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">User listing</span>
+<td class="content" metal:fill-slot="content">
+
+<span tal:condition="python:not (context.is_view_ok()
+ or request.user.hasRole('Anonymous'))"
+ i18n:translate="">You are not allowed to view this page.</span>
+
+<span tal:condition="python:not context.is_view_ok()
+ and request.user.hasRole('Anonymous')"
+ i18n:translate="">Please login with your username and password.</span>
+
+<table width="100%" tal:condition="context/is_view_ok" class="list">
+<tr>
+ <th i18n:translate="">Username</th>
+ <th i18n:translate="">Email address</th>
+</tr>
+<tal:block repeat="user context/list">
+ <tr tal:condition="user/is_view_ok"
+ 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>
+</tal:block>
+</table>
+</td>
+
+</tal:block>
diff --git a/share/roundup/templates/minimal/html/user.item.html b/share/roundup/templates/minimal/html/user.item.html
--- /dev/null
@@ -0,0 +1,169 @@
+<!-- dollarId: user.item,v 1.7 2002/08/16 04:29:04 richard Exp dollar-->
+<tal:doc metal:use-macro="templates/page/macros/icing"
+define="edit_ok context/is_edit_ok"
+>
+<title metal:fill-slot="head_title">
+<tal:if condition="context/id" i18n:translate=""
+ >User <tal:x content="context/id" i18n:name="id"
+ />: <tal:x content="context/username" i18n:name="title"
+ /> - <tal:x content="config/TRACKER_NAME" i18n:name="tracker"
+/></tal:if>
+<tal:if condition="not:context/id" i18n:translate=""
+ >New User - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker"
+/></tal:if>
+</title>
+<metal:slot fill-slot="more-javascript">
+<script metal:use-macro="templates/page/macros/user_utils"></script>
+<script type="text/javascript" src="@@file/help_controls.js"></script>
+</metal:slot>
+<tal:block metal:fill-slot="body_title"
+ define="edit_ok context/is_edit_ok">
+ <span tal:condition="python: not (context.id or edit_ok)"
+ tal:omit-tag="python:1" i18n:translate="">New User</span>
+ <span tal:condition="python: not context.id and edit_ok"
+ tal:omit-tag="python:1" i18n:translate="">New User Editing</span>
+ <span tal:condition="python: context.id and not edit_ok"
+ tal:omit-tag="python:1" i18n:translate="">User<tal:x
+ replace="context/id" i18n:name="id" /></span>
+ <span tal:condition="python: context.id and edit_ok"
+ tal:omit-tag="python:1" i18n:translate="">User<tal:x
+ replace="context/id" i18n:name="id" /> Editing</span>
+</tal:block>
+
+<td class="content" metal:fill-slot="content">
+
+<p tal:condition="python:not (context.is_view_ok()
+ or request.user.hasRole('Anonymous'))" i18n:translate="">
+ You are not allowed to view this page.</p>
+
+<p tal:condition="python:not context.is_view_ok()
+ and request.user.hasRole('Anonymous')" i18n:translate="">
+ Please login with your username and password.</p>
+
+<div tal:condition="context/is_view_ok">
+
+<form method="POST"
+ name="itemSynopsis"
+ tal:define="required python:'username address'.split()"
+ enctype="multipart/form-data"
+ tal:attributes="action context/designator;
+ onSubmit python:'return checkRequiredFields(\'%s\')'%'\', \''.join(required);
+ ">
+<table class="form" tal:define="
+ th_label templates/page/macros/th_label;
+ src_input templates/page/macros/user_src_input;
+ normal_input templates/page/macros/user_normal_input;
+ pw_input templates/page/macros/user_pw_input;
+ confirm_input templates/page/macros/user_confirm_input;
+ edit_ok context/is_edit_ok;
+ ">
+ <tr tal:define="name string:realname; label string:Name; value context/realname; edit_ok edit_ok">
+ <th metal:use-macro="th_label">Name</th>
+ <td><input name="realname" metal:use-macro="src_input"></td>
+ </tr>
+ <tr tal:define="name string:username; label string:Login Name; value context/username">
+ <th metal:use-macro="th_label">Login Name</th>
+ <td><input metal:use-macro="src_input"></td>
+ </tr>
+ <tal:if condition="edit_ok">
+ <tr tal:define="name string:password; label string:Login Password">
+ <th metal:use-macro="th_label">Login Password</th>
+ <td><input metal:use-macro="pw_input" type="password"></td>
+ </tr>
+ <tr tal:define="name string:password; label string:Confirm Password">
+ <th metal:use-macro="th_label">Confirm Password</th>
+ <td><input metal:use-macro="confirm_input" type="password"></td>
+ </tr>
+ </tal:if>
+ <tal:if condition="python:request.user.hasPermission('Web Roles')">
+ <tr tal:define="name string:roles; label string:Roles;">
+ <th><label for="roles" i18n:translate="">Roles</label></th>
+ <td tal:define="gips context/id">
+ <tal:subif condition=gips define="value context/roles">
+ <input metal:use-macro="normal_input">
+ </tal:subif>
+ <tal:subif condition="not:gips" define="value db/config/NEW_WEB_USER_ROLES">
+ <input metal:use-macro="normal_input">
+ </tal:subif>
+ <tal:block i18n:translate="">(to give the user more than one role,
+ enter a comma,separated,list)</tal:block>
+ </td>
+ </tr>
+ </tal:if>
+
+ <tr tal:define="name string:phone; label string:Phone; value context/phone">
+ <th metal:use-macro="th_label">Phone</th>
+ <td><input name="phone" metal:use-macro="normal_input"></td>
+ </tr>
+
+ <tr tal:define="name string:organisation; label string:Organisation; value context/organisation">
+ <th metal:use-macro="th_label">Organisation</th>
+ <td><input name="organisation" metal:use-macro="normal_input"></td>
+ </tr>
+
+ <tr tal:condition="python:edit_ok or context.timezone"
+ tal:define="name string:timezone; label string:Timezone; value context/timezone">
+ <th metal:use-macro="th_label">Timezone</th>
+ <td><input name="timezone" metal:use-macro="normal_input">
+ <tal:block tal:condition="edit_ok" i18n:translate="">(this is a numeric hour offset, the default is
+ <span tal:replace="db/config/DEFAULT_TIMEZONE" i18n:name="zone"
+ />)</tal:block>
+ </td>
+ </tr>
+
+ <tr tal:define="name string:address; label string:E-mail address; value context/address">
+ <th metal:use-macro="th_label">E-mail address</th>
+ <td tal:define="mailto python:context.address.field(id='address');
+ mklink python:mailto and not edit_ok">
+ <a href="mailto:calvin@the-z.org"
+ tal:attributes="href string:mailto:$value"
+ tal:content="value"
+ tal:condition="python:mklink">calvin@the-z.org</a>
+ <tal:if condition=edit_ok>
+ <input metal:use-macro="src_input" value="calvin@the-z.org">
+ </tal:if>
+
+ </td>
+ </tr>
+
+ <tr>
+ <th><label for="alternate_addresses" i18n:translate="">Alternate E-mail addresses<br>One address per line</label></th>
+ <td>
+ <textarea rows=5 cols=40 tal:replace="structure context/alternate_addresses/multiline">nobody@nowhere.org
+anybody@everywhere.net
+(alternate_addresses)
+ </textarea>
+ </td>
+ </tr>
+
+ <tr tal:condition="edit_ok">
+ <td>
+
+ <input type="hidden" name="@template" value="item">
+ <input type="hidden" name="@required" value="username,address"
+ tal:attributes="value python:','.join(required)">
+ </td>
+ <td><input type="submit" value="save" tal:replace="structure context/submit"><!--submit button here-->
+ <input type=reset>
+ </td>
+ </tr>
+</table>
+</form>
+
+<tal:block tal:condition="not:context/id" i18n:translate="">
+<table class="form">
+<tr>
+ <td>Note: </td>
+ <th class="required">highlighted</th>
+ <td> fields are required.</td>
+</tr>
+</table>
+</tal:block>
+
+<tal:block tal:condition="context/id" tal:replace="structure context/history" />
+
+</div>
+
+</td>
+
+</tal:doc>
diff --git a/share/roundup/templates/minimal/html/user.register.html b/share/roundup/templates/minimal/html/user.register.html
--- /dev/null
@@ -0,0 +1,73 @@
+<!-- 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"
+ i18n:translate="">Registering with <span i18n:name="tracker"
+ tal:replace="db/config/TRACKER_NAME" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">Registering with <span i18n:name="tracker"
+ tal:replace="db/config/TRACKER_NAME" /></span>
+<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 or request.user.hasRole('Anonymous'))"
+ i18n:translate="">You are not allowed to view this page.</span>
+
+<span tal:condition="python:not editok and request.user.hasRole('Anonymous')"
+ i18n:translate="">Please login with your username and password.</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 i18n:translate="">Login Name</th>
+ <td tal:content="structure context/username/field">username</td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Login Password</th>
+ <td tal:content="structure context/password/field">password</td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Confirm Password</th>
+ <td tal:content="structure context/password/confirm">password</td>
+ </tr>
+ <tr tal:condition="python:request.user.hasPermission('Web Roles')">
+ <th i18n:translate="">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 i18n:translate="">E-mail address</th>
+ <td tal:content="structure context/address/field">address</td>
+ </tr>
+ <tr>
+ <th i18n:translate="">Alternate E-mail addresses<br>One address per line</th>
+ <td tal:content="structure context/alternate_addresses/multiline">alternate_addresses</td>
+ </tr>
+
+ <tr>
+ <td> </td>
+ <td>
+ <input type="hidden" name=":action" value="register">
+ <input type="submit" name="submit" value="Register" i18n:attributes="value">
+ </td>
+ </tr>
+</table>
+</form>
+
+</tal:block>
+
+</tal:block>
+
+</td>
+
+</tal:block>
diff --git a/share/roundup/templates/minimal/html/user.rego_progress.html b/share/roundup/templates/minimal/html/user.rego_progress.html
--- /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"
+ i18n:translate="">Registration in progress - <span i18n:name="tracker"
+ tal:replace="config/TRACKER_NAME" /></title>
+<span metal:fill-slot="body_title" tal:omit-tag="python:1"
+ i18n:translate="">Registration in progress...</span>
+<td class="content" metal:fill-slot="content">
+
+<p i18n:translate="">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/share/roundup/templates/minimal/initial_data.py b/share/roundup/templates/minimal/initial_data.py
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# TRACKER DATABASE INITIALIZATION
+#
+
+# create the two default users
+user = db.getclass('user')
+user.create(username="admin", password=adminpw,
+ address=admin_email, roles='Admin')
+user.create(username="anonymous", roles='Anonymous')
+
+# add any additional database creation steps here - but only if you
+# haven't initialised the database with the admin "initialise" command
+
+# vim: set et sts=4 sw=4 :
diff --git a/share/roundup/templates/minimal/schema.py b/share/roundup/templates/minimal/schema.py
--- /dev/null
@@ -0,0 +1,65 @@
+#
+# TRACKER SCHEMA
+#
+
+# Class automatically gets these properties:
+# creation = Date()
+# activity = Date()
+# creator = Link('user')
+# actor = Link('user')
+
+# 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")
+#
+# TRACKER SECURITY SETTINGS
+#
+# See the configuration and customisation document for information
+# about security setup.
+
+#
+# REGULAR USERS
+#
+# Give the regular users access to the web and email interface
+db.security.addPermissionToRole('User', 'Web Access')
+db.security.addPermissionToRole('User', 'Email Access')
+
+# May users view other user information?
+# Comment these lines out if you don't want them to
+db.security.addPermissionToRole('User', 'View', 'user')
+
+# Users should be able to edit their own details -- this permission is
+# limited to only the situation where the Viewed or Edited item is their own.
+def own_record(db, userid, itemid):
+ '''Determine whether the userid matches the item being accessed.'''
+ return userid == itemid
+p = db.security.addPermission(name='View', klass='user', check=own_record,
+ description="User is allowed to view their own user details")
+db.security.addPermissionToRole('User', p)
+p = db.security.addPermission(name='Edit', klass='user', check=own_record,
+ description="User is allowed to edit their own user details")
+db.security.addPermissionToRole('User', p)
+
+#
+# ANONYMOUS USER PERMISSIONS
+#
+# Let anonymous users access the web interface. Note that almost all
+# trackers will need this Permission. The only situation where it's not
+# required is in a tracker that uses an HTTP Basic Authenticated front-end.
+db.security.addPermissionToRole('Anonymous', 'Web Access')
+
+# Let anonymous users access the email interface (note that this implies
+# that they will be registered automatically, hence they will need the
+# "Create" user Permission below)
+db.security.addPermissionToRole('Anonymous', 'Email Access')
+
+# Assign the appropriate permissions to the anonymous user's
+# Anonymous Role. Choices here are:
+# - Allow anonymous users to register
+db.security.addPermissionToRole('Anonymous', 'Create', 'user')
+
+# vim: set et sts=4 sw=4 :
diff --git a/templates/classic/.cvsignore b/templates/classic/.cvsignore
+++ /dev/null
@@ -1,4 +0,0 @@
-*.pyc
-*.pyo
-htmlbase.py
-*.cover
diff --git a/templates/classic/TEMPLATE-INFO.txt b/templates/classic/TEMPLATE-INFO.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-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/detectors/.cvsignore b/templates/classic/detectors/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-*.pyc
-*.pyo
-*.cover
diff --git a/templates/classic/detectors/messagesummary.py b/templates/classic/detectors/messagesummary.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#$Id: messagesummary.py,v 1.2 2007-04-03 06:47:21 a1s 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'], config=db.config)
- 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
+++ /dev/null
@@ -1,143 +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.4 2005-04-04 08:47:14 richard Exp $
-
-import sets
-
-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_nosy = sets.Set()
- 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:
- current_nosy.add(value)
-
- # 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
- current_nosy.add(value)
-
- new_nosy = sets.Set(current_nosy)
-
- # 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:
- new_nosy.add(assignedto_id)
-
- # 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
- oldmessages = cl.get(nodeid, 'messages')
- 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')
- new_nosy.add(authid)
-
- # add on the recipients of the message
- if add_recips in ok:
- for recipient in msg.get(msgid, 'recipients'):
- new_nosy.add(recipient)
-
- if current_nosy != new_nosy:
- # that's it, save off the new nosy list
- newvalues['nosy'] = list(new_nosy)
-
-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
+++ /dev/null
@@ -1,85 +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.5 2004-03-27 00:01:48 richard Exp $
-
-def chatty(db, cl, nodeid, newvalues):
- ''' If the issue is currently 'unread', 'resolved', 'done-cbb' or None,
- 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'):
- 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'):
- # 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 + [None]:
- # 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
-
- # get the unread state ID
- try:
- unread_id = db.status.lookup('unread')
- except KeyError:
- # no unread state, ignore all this stuff
- return
-
- # ok, do it
- newvalues['status'] = unread_id
-
-
-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/detectors/userauditor.py b/templates/classic/detectors/userauditor.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# Copyright (c) 2003 Richard Jones (richard@mechanicalcat.net)
-#
-# 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: userauditor.py,v 1.9 2007-09-12 21:11:13 jpend Exp $
-
-import re
-
-# regular expression thanks to: http://www.regular-expressions.info/email.html
-# this is the "99.99% solution for syntax only".
-email_regexp = (r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*", r"(localhost|(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9]))")
-email_rfc = re.compile('^' + email_regexp[0] + '@' + email_regexp[1] + '$', re.IGNORECASE)
-email_local = re.compile('^' + email_regexp[0] + '$', re.IGNORECASE)
-
-def valid_address(address):
- ''' If we see an @-symbol in the address then check against the full
- RFC syntax. Otherwise it is a local-only address so only check
- the local part of the RFC syntax.
- '''
- if '@' in address:
- return email_rfc.match(address)
- else:
- return email_local.match(address)
-
-def get_addresses(user):
- ''' iterate over all known addresses in a newvalues dict
- this takes of the address/alterate_addresses handling
- '''
- if user.has_key('address'):
- yield user['address']
- if user.get('alternate_addresses', None):
- for address in user['alternate_addresses'].split('\n'):
- yield address
-
-def audit_user_fields(db, cl, nodeid, newvalues):
- ''' Make sure user properties are valid.
-
- - email address is syntactically valid
- - email address is unique
- - roles specified exist
- - timezone is valid
- '''
-
- for address in get_addresses(newvalues):
- if not valid_address(address):
- raise ValueError, 'Email address syntax is invalid'
-
- check_main = db.user.stringFind(address=address)
- # make sure none of the alts are owned by anyone other than us (x!=nodeid)
- check_alts = [x for x in db.user.filter(None, {'alternate_addresses' : address}) if x != nodeid]
- if check_main or check_alts:
- raise ValueError, 'Email address %s already in use' % address
-
- for rolename in [r.lower().strip() for r in newvalues.get('roles', '').split(',')]:
- if rolename and not db.security.role.has_key(rolename):
- raise ValueError, 'Role "%s" does not exist'%rolename
-
- tz = newvalues.get('timezone', None)
- if tz:
- # if they set a new timezone validate the timezone by attempting to
- # use it before we store it to the db.
- import roundup.date
- import datetime
- try:
- TZ = roundup.date.get_timezone(tz)
- dt = datetime.datetime.now()
- local = TZ.localize(dt).utctimetuple()
- except IOError:
- raise ValueError, 'Timezone "%s" does not exist' % tz
- except ValueError:
- raise ValueError, 'Timezone "%s" exceeds valid range [-23...23]' % tz
-
-def init(db):
- # fire before changes are made
- db.user.audit('set', audit_user_fields)
- db.user.audit('create', audit_user_fields)
-
-# vim: sts=4 sw=4 et si
diff --git a/templates/classic/extensions/README.txt b/templates/classic/extensions/README.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This directory is for tracker extensions:
-
-- CGI Actions
-- Templating functions
-
-See the customisation doc for more information.
diff --git a/templates/classic/html/_generic.404.html b/templates/classic/html/_generic.404.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html>
-<head>
-<title>Item Not Found</title>
-</head>
-
-<body>
-There is no <span tal:content="context/_classname" /> with id <span tal:content="context/id"/>
-</body>
-</html>
diff --git a/templates/classic/html/_generic.calendar.html b/templates/classic/html/_generic.calendar.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html>
- <head>
- <link rel="stylesheet" type="text/css" href="@@file/style.css" />
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8;" />
- <title tal:content="string:Roundup Calendar"></title>
- <script language="Javascript"
- type="text/javascript"
- tal:content="structure string:
- // this is the name of the field in the original form that we're working on
- form = window.opener.document.${request/form/form/value};
- field = '${request/form/property/value}';" >
- </script>
- </head>
- <body class="body"
- tal:content="structure python:utils.html_calendar(request)">
- </body>
-</html>
diff --git a/templates/classic/html/_generic.collision.html b/templates/classic/html/_generic.collision.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title" i18n:translate=""
- ><span tal:replace="python:context._classname.capitalize()"
- i18n:name="class" /> Edit Collision - <span i18n:name="tracker"
- tal:replace="config/TRACKER_NAME" /></title>
-<tal:block metal:fill-slot="body_title" i18n:translate=""
- ><span tal:replace="python:context._classname.capitalize()"
- i18n:name="class" /> Edit Collision</tal:block>
-
-<td class="content" metal:fill-slot="content" i18n:translate="
- There has been a collision. Another user updated this node
- while you were editing. Please <a href='${context}'>reload</a>
- the node and review your edits.
-"><span tal:replace="context/designator" i18n:name="context" />
-</td>
-</tal:block>
diff --git a/templates/classic/html/_generic.help-empty.html b/templates/classic/html/_generic.help-empty.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<html>
- <head>
- <title>Empty page (no search performed yet)</title>
- </head>
- <body>
- <p i18n:translate="">Please specify your search parameters!</p>
- </body>
-</html>
diff --git a/templates/classic/html/_generic.help-list.html b/templates/classic/html/_generic.help-list.html
+++ /dev/null
@@ -1,83 +0,0 @@
-<!-- $Id: _generic.help-list.html,v 1.2 2008-03-01 08:18:07 richard Exp $ vim: sw=2 ts=8 et
---><html tal:define="vok context/is_view_ok">
- <head>
- <title>Search result for user helper</title>
- <link rel="stylesheet" type="text/css" href="@@file/style.css" />
- <script language="Javascript" type="text/javascript"
- tal:content="structure string:<!--
- // this is the name of the field in the original form that we're working on
- form = parent.opener.document.${request/form/form/value};
- field = '${request/form/property/value}';
- //-->"></script>
- <script src="@@file/help_controls.js" type="text/javascript"></script>
-<script type="text/javascript"><!--
-var text_field = parent.submit.document.frm_help.text_preview;
-//--></script>
- </head>
- <body>
- <pre tal:content="request/env/QUERY_STRING" tal:condition=false />
-
- <p tal:condition="not:vok" i18n:translate="">You are not
- allowed to view this page.</p>
-
- <tal:if condition="context/is_view_ok">
- <tal:def define="batch request/batch;">
- <form name=dummyform>
- <table width="100%"
- tal:define="template string:help-list"
- metal:use-macro="templates/help/macros/batch_navi"
- >
- <tr class="navigation">
- <th>
- <a href="#"><< previous</a>
- </th>
- <th i18n:translate="">1..25 out of 50
- </th>
- <th>
- <a href="#">next >></a>
- </th>
- </tr>
- </table>
-
- <form name=dummyform>
- <table class="classhelp"
- tal:define="
- props python:request.form['properties'].value.split(',');
- legend templates/help/macros/legend;
- "><thead>
- <tr metal:use-macro="legend">
- <th> <b>x</b></th>
- <th tal:repeat="prop props" tal:content="prop" i18n:translate=""></th>
- </tr>
- </thead>
- <tfoot tal:condition=true>
- <tr metal:use-macro="legend" />
- </tfoot>
- <tbody>
- <tr tal:repeat="item batch">
- <tal:block tal:define="attr python:item[props[0]]" >
- <td>
- <input name="check"
- onclick="switch_val(text_field, this);" type="checkbox"
- tal:attributes="value attr; id string:id_$attr" />
- </td>
- <td tal:repeat="prop props">
- <label class="classhelp-label"
- tal:attributes="for string:id_$attr"
- tal:content="python:item[prop]"></label>
- </td>
- </tal:block>
- </tr>
- </tbody>
- </table>
- </form>
- </tal:def>
- </tal:if>
-
- <pre tal:content=request tal:condition=false />
- <script type="text/javascript"><!--
- parent.submit.document.frm_help.cb_listpresent.checked=true;
- reviseList_framed(document.dummyform, text_field)
- //--></script>
- </body>
-</html>
diff --git a/templates/classic/html/_generic.help-search.html b/templates/classic/html/_generic.help-search.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<html>
- <head>
- <title>Frame for search input fields</title>
- </head>
- <body>
- <p i18n:translate="">Generic template
- <span tal:replace="request/template" i18n:name="template">help-search</span>
- or version for class
- <span tal:replace="request/classname" i18n:name="classname">user</span>
- is not yet implemented</p>
- </body>
-</html>
-
diff --git a/templates/classic/html/_generic.help-submit.html b/templates/classic/html/_generic.help-submit.html
+++ /dev/null
@@ -1,73 +0,0 @@
-<html>
- <head>
- <link rel="stylesheet" type="text/css" href="@@file/style.css" />
- <meta http-equiv="Content-Type"
- tal:attributes="content string:text/html;; charset=${request/client/charset}" />
- <tal:block tal:condition="python:request.form.has_key('property')">
- <title>Generic submit page for framed helper windows</title>
- <script language="Javascript" type="text/javascript"
- tal:content="structure string:<!--
-// this is the name of the field in the original form that we're working on
-form = parent.opener.document.${request/form/form/value};
-callingform=form
-field = '${request/form/property/value}';
-var listform = null
-function listPresent() {
- return document.frm_help.cb_listpresent.checked
-}
-function getListForm() {
- if (listPresent()) {
- return parent.list.document.forms.dummyform
- } else {
- return null
- }
-}
-
-
-function checkListForm() {
- // global listform
- if (listform != null)
- if (parent.list.document.dummyform) {
- listform = parent.list.document.dummyform
- alert(listform)
- }
-
- var bol= listform != null
- alert('checkListForm: bol='+bol)
- return bol
-}
-//-->">
- </script>
- <script src="@@file/help_controls.js" type="text/javascript"></script>
- </tal:block>
- </head>
- <body class="body" onload="parent.focus();" id="submit">
- <pre tal:content="request/env/QUERY_STRING" tal:condition=false />
- <form name="frm_help"
- tal:define="batch request/batch;
- props python:request.form['properties'].value.split(',')"
- class="help-submit"
- id="classhelp-controls">
- <div style="width:100%;text-align:left;margin-bottom:0.2em">
- <input type="text" name="text_preview" size="24" class="preview"
- onchange="f=getListForm();if(f){ reviseList_framed(f, this)};"
- />
- </div>
- <input type=checkbox name="cb_listpresent" readonly="readonly" style="display:none">
- <input type="button" id="btn_cancel"
- value=" Cancel " onclick="parent.close();return false;"
- i18n:attributes="value" />
- <input type="reset" id="btn_reset"
- onclick="text_field.value=original_field;f=getListForm();if (f) {reviseList_framed(f, this)};return false"
- />
- <input type="submit" id="btn_apply" class="apply"
- value=" Apply " onclick="callingform[field].value=text_field.value; parent.close();"
- i18n:attributes="value" />
- </form>
- <script type="text/javascript"><!--
-var text_field = document.frm_help.text_preview;
-original_field=form[field].value;
-text_field.value=original_field;
-//--></script>
- </body>
-</html>
diff --git a/templates/classic/html/_generic.help.html b/templates/classic/html/_generic.help.html
+++ /dev/null
@@ -1,98 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html tal:define="property request/form/property/value" >
- <head>
- <link rel="stylesheet" type="text/css" href="@@file/style.css" />
- <meta http-equiv="Content-Type"
- tal:attributes="content string:text/html;; charset=${request/client/charset}" />
- <tal:block tal:condition="python:request.form.has_key('property')">
- <title i18n:translate=""><tal:x i18n:name="property"
- tal:content="property" i18n:translate="" /> help - <span i18n:name="tracker"
- tal:replace="config/TRACKER_NAME" /></title>
- <script language="Javascript" type="text/javascript"
- tal:content="structure string:
- // this is the name of the field in the original form that we're working on
- form = window.opener.document.${request/form/form/value};
- field = '${request/form/property/value}';">
- </script>
- <script src="@@file/help_controls.js" type="text/javascript"><!--
- //--></script>
- </tal:block>
- </head>
- <body class="body" onload="resetList();">
- <form name="frm_help" tal:attributes="action request/base"
- tal:define="batch request/batch;
- props python:request.form['properties'].value.split(',')">
-
- <div id="classhelp-controls">
- <!--input type="button" name="btn_clear"
- value="Clear" onClick="clearList()"/ -->
- <input type="text" name="text_preview" size="24" class="preview"
- onchange="reviseList(this.value);"/>
- <input type="button" name="btn_reset"
- value=" Cancel " onclick="resetList(); window.close();"
- i18n:attributes="value" />
- <input type="button" name="btn_apply" class="apply"
- value=" Apply " onclick="updateList(); window.close();"
- i18n:attributes="value" />
- </div>
- <table width="100%">
- <tr class="navigation">
- <th>
- <a tal:define="prev batch/previous" tal:condition="prev"
- tal:attributes="href python:request.indexargs_url(request.classname,
- {'@template':'help', 'property': request.form['property'].value,
- 'properties': request.form['properties'].value,
- 'form': request.form['form'].value,
- 'type': request.form['type'].value,
- '@startwith':prev.first, '@pagesize':prev.size})"
- i18n:translate="" ><< previous</a>
-
- </th>
- <th i18n:translate=""><span tal:replace="batch/start" i18n:name="start"
- />..<span tal:replace="python: batch.start + batch.length -1" i18n:name="end"
- /> out of <span tal:replace="batch/sequence_length" i18n:name="total"
- />
- </th>
- <th>
- <a tal:define="next batch/next" tal:condition="next"
- tal:attributes="href python:request.indexargs_url(request.classname,
- {'@template':'help', 'property': request.form['property'].value,
- 'properties': request.form['properties'].value,
- 'form': request.form['form'].value,
- 'type': request.form['type'].value,
- '@startwith':next.first, '@pagesize':next.size})"
- i18n:translate="" >next >></a>
-
- </th>
- </tr>
- </table>
-
- <table class="classhelp">
- <tr>
- <th> <b>x</b></th>
- <th tal:repeat="prop props" tal:content="prop" i18n:translate=""></th>
- </tr>
- <tr tal:repeat="item batch">
- <tal:block tal:define="attr python:item[props[0]]" >
- <td>
- <input name="check"
- onclick="updatePreview();"
- tal:attributes="type python:request.form['type'].value;
- value attr; id string:id_$attr" />
- </td>
- <td tal:repeat="prop props">
- <label class="classhelp-label"
- tal:attributes="for string:id_$attr"
- tal:content="python:item[prop]"></label>
- </td>
- </tal:block>
- </tr>
- <tr>
- <th> <b>x</b></th>
- <th tal:repeat="prop props" tal:content="prop" i18n:translate=""></th>
- </tr>
- </table>
-
- </form>
- </body>
-</html>
diff --git a/templates/classic/html/_generic.index.html b/templates/classic/html/_generic.index.html
+++ /dev/null
@@ -1,70 +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" i18n:translate=""
- ><span tal:replace="python:context._classname.capitalize()"
- i18n:name="class" /> editing - <span i18n:name="tracker"
- tal:replace="config/TRACKER_NAME" /></title>
-<tal:block metal:fill-slot="body_title" i18n:translate=""
- ><span tal:replace="python:context._classname.capitalize()"
- i18n:name="class" /> editing</tal:block>
-
-<td class="content" metal:fill-slot="content">
-
-<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok()
- or request.user.hasRole('Anonymous'))"
- tal:omit-tag="python:1" i18n:translate=""
->You are not allowed to view this page.</span>
-
-<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())
- and request.user.hasRole('Anonymous')"
- tal:omit-tag="python:1" i18n:translate=""
->Please login with your username and password.</span>
-
-<tal:block tal:condition="context/is_edit_ok">
-<tal:block i18n:translate="">
-<p class="form-help">
- You may edit the contents of the
- <span tal:replace="request/classname" i18n:name="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>
-</tal:block>
-<form onSubmit="return submit_once()" method="POST"
- tal:attributes="action context/designator">
-<textarea rows="15" style="width:90%" name="rows" tal:content="context/csv"></textarea>
-<br>
-<input type="hidden" name="@action" value="editCSV">
-<input type="submit" value="Edit Items" i18n:attributes="value">
-</form>
-</tal:block>
-
-<table tal:condition="context/is_only_view_ok" width="100%" class="list">
- <tr>
- <th tal:repeat="property context/propnames" tal:content="property"> </th>
- </tr>
- <tal:block repeat="item context/list">
- <tr tal:condition="item/is_view_ok"
- tal:attributes="class python:['normal', 'alt'][repeat['item'].index%6/3]">
- <td tal:repeat="property context/propnames"
- tal:content="python: item[property] or default"
- > </td>
- </tr>
- </tal:block>
-</table>
-
-</td>
-
-</tal:block>
diff --git a/templates/classic/html/_generic.item.html b/templates/classic/html/_generic.item.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title" i18n:translate=""
- ><span tal:replace="python:context._classname.capitalize()"
- i18n:name="class" /> editing - <span i18n:name="tracker"
- tal:replace="config/TRACKER_NAME" /></title>
-<tal:block metal:fill-slot="body_title" i18n:translate=""
- ><span tal:replace="python:context._classname.capitalize()"
- i18n:name="class" /> editing</tal:block>
-
-<td class="content" metal:fill-slot="content">
-
-<p tal:condition="python:not (context.is_view_ok()
- or request.user.hasRole('Anonymous'))" i18n:translate="">
- You are not allowed to view this page.</p>
-
-<p tal:condition="python:not context.is_view_ok()
- and request.user.hasRole('Anonymous')" i18n:translate="">
- Please login with your username and password.</p>
-
-<div tal:condition="context/is_view_ok">
-
-<form method="POST" onSubmit="return submit_once()"
- enctype="multipart/form-data" tal:condition="context/is_view_ok"
- tal:attributes="action context/designator">
-
-<input type="hidden" name="@template" value="item">
-
-<table class="form">
-
-<tr tal:repeat="prop python:db[context._classname].properties()">
- <tal:block tal:condition="python:prop._name not in ('id',
- 'creator', 'creation', 'actor', 'activity')">
- <th tal:content="prop/_name"></th>
- <td tal:content="structure python:context[prop._name].field()"></td>
- </tal:block>
-</tr>
-<tr>
- <td> </td>
- <td colspan=3 tal:content="structure context/submit">
- submit button will go here
- </td>
-</tr>
-</table>
-
-</form>
-
-<tal:block tal:condition="context/id" tal:replace="structure context/history" />
-
-</div>
-
-</td>
-
-</tal:block>
diff --git a/templates/classic/html/file.index.html b/templates/classic/html/file.index.html
+++ /dev/null
@@ -1,31 +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" i18n:translate=""
- >List of files - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">List of files</span>
-<td class="content" metal:fill-slot="content">
-
-<table class="otherinfo" tal:define="batch request/batch">
- <tr><th style="padding-right: 10" i18n:translate="">Download</th>
- <th style="padding-right: 10" i18n:translate="">Content Type</th>
- <th style="padding-right: 10" i18n:translate="">Uploaded By</th>
- <th style="padding-right: 10" i18n:translate="">Date</th>
- </tr>
- <tr tal:repeat="file batch" tal:attributes="class python:['normal', 'alt'][repeat['file'].index%6/3]">
- <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>
-
- <metal:block use-macro="templates/issue.index/macros/batch-footer" />
-
-</table>
-
-</td>
-
-</tal:block>
diff --git a/templates/classic/html/file.item.html b/templates/classic/html/file.item.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title" i18n:translate="">File display - <span
- i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">File display</span>
-
-<td class="content" metal:fill-slot="content">
-
-<p tal:condition="python:not (context.is_view_ok()
- or request.user.hasRole('Anonymous'))" i18n:translate="">
- You are not allowed to view this page.</p>
-
-<p tal:condition="python:not context.is_view_ok()
- and request.user.hasRole('Anonymous')" i18n:translate="">
- Please login with your username and password.</p>
-
-<form method="POST" onSubmit="return submit_once()"
- enctype="multipart/form-data" tal:condition="context/is_view_ok"
- tal:attributes="action context/designator">
-
-<table class="form">
- <tr>
- <th i18n:translate="">Name</th>
- <td tal:content="structure context/name/field"></td>
- </tr>
- <tr>
- <th i18n:translate="">Content Type</th>
- <td tal:content="structure context/type/field"></td>
- </tr>
-
- <tr>
- <td>
-
- <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">
- </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}"
- i18n:translate="">download</a>
-
-<tal:block tal:condition="context/id" tal:replace="structure context/history" />
-
-</td>
-
-</tal:block>
diff --git a/templates/classic/html/help.html b/templates/classic/html/help.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!--
-Macros for framed help windows
--->
-
-<!-- legend for helper search results -->
-<thead>
-<tr metal:define-macro="legend">
- <th><b>x</b></th>
- <th tal:repeat="prop props" tal:content="prop" i18n:translate=""></th>
-</tr>
-</thead>
-
-<table width="100%"
- metal:define-macro="batch_navi"
- tal:define="prev batch/previous;
- next batch/next;
- "
- tal:condition="python:prev or next">
- <tr class="navigation">
- <th width="30%">
- <a tal:condition="prev"
- tal:attributes="href python:request.indexargs_url(request.classname, {'@template':'help-list', 'property': request.form['property'].value, 'properties': request.form['properties'].value, 'form': request.form['form'].value, '@startwith':prev.first, '@pagesize':prev.size})"
- i18n:translate="" ><< previous</a>
-
- </th>
- <th i18n:translate="" width="40%"><span tal:replace="batch/start" i18n:name="start"
- />..<span tal:replace="python: batch.start + batch.length -1" i18n:name="end"
- /> out of <span tal:replace="batch/sequence_length" i18n:name="total"
- />
- </th>
- <th width="30%">
- <a tal:condition="next"
- tal:attributes="href python:request.indexargs_url(request.classname, {'@template':'help-list', 'property': request.form['property'].value, 'properties': request.form['properties'].value, 'form': request.form['form'].value, '@startwith':next.first, '@pagesize':next.size})"
- i18n:translate="" >next >></a>
-
- </th>
- </tr>
- </table>
diff --git a/templates/classic/html/help_controls.js b/templates/classic/html/help_controls.js
+++ /dev/null
@@ -1,324 +0,0 @@
-// initial values for either Nosy, Superseder, Keyword and Waiting On,
-// depending on which has called
-original_field = form[field].value;
-
-// Some browsers (ok, IE) don't define the "undefined" variable.
-undefined = document.geez_IE_is_really_friggin_annoying;
-
-function trim(value) {
- var temp = value;
- var obj = /^(\s*)([\W\w]*)(\b\s*$)/;
- if (obj.test(temp)) { temp = temp.replace(obj, '$2'); }
- var obj = / /g;
- while (temp.match(obj)) { temp = temp.replace(obj, " "); }
- return temp;
-}
-
-function determineList() {
- // generate a comma-separated list of the checked items
- var list = new String('');
-
- // either a checkbox object or an array of checkboxes
- var check = document.frm_help.check;
-
- if ((check.length == undefined) && (check.checked != undefined)) {
- // only one checkbox on page
- if (check.checked) {
- list = check.value;
- }
- } else {
- // array of checkboxes
- for (box=0; box < check.length; box++) {
- if (check[box].checked) {
- if (list.length == 0) {
- separator = '';
- }
- else {
- separator = ',';
- }
- // we used to use an Array and push / join, but IE5.0 sux
- list = list + separator + check[box].value;
- }
- }
- }
- return list;
-}
-
-/**
- * update the field in the opening window;
- * the text_field variable must be set in the calling page
- */
-function updateOpener() {
- // write back to opener window
- if (document.frm_help.check==undefined) { return; }
- form[field].value = text_field.value;
-}
-
-function updateList() {
- // write back to opener window
- if (document.frm_help.check==undefined) { return; }
- form[field].value = determineList();
-}
-
-function updatePreview() {
- // update the preview box
- if (document.frm_help.check==undefined) { return; }
- writePreview(determineList());
-}
-
-function clearList() {
- // uncheck all checkboxes
- if (document.frm_help.check==undefined) { return; }
- for (box=0; box < document.frm_help.check.length; box++) {
- document.frm_help.check[box].checked = false;
- }
-}
-
-function reviseList_framed(form, textfield) {
- // update the checkboxes based on the preview field
- // alert('reviseList_framed')
- // alert(form)
- if (form.check==undefined)
- return;
- // alert(textfield)
- var to_check;
- var list = textfield.value.split(",");
- if (form.check.length==undefined) {
- check = form.check;
- to_check = false;
- for (val in list) {
- if (check.value==trim(list[val])) {
- to_check = true;
- break;
- }
- }
- check.checked = to_check;
- } else {
- for (box=0; box < form.check.length; box++) {
- check = form.check[box];
- to_check = false;
- for (val in list) {
- if (check.value==trim(list[val])) {
- to_check = true;
- break;
- }
- }
- check.checked = to_check;
- }
- }
-}
-
-function reviseList(vals) {
- // update the checkboxes based on the preview field
- if (document.frm_help.check==undefined) { return; }
- var to_check;
- var list = vals.split(",");
- if (document.frm_help.check.length==undefined) {
- check = document.frm_help.check;
- to_check = false;
- for (val in list) {
- if (check.value==trim(list[val])) {
- to_check = true;
- break;
- }
- }
- check.checked = to_check;
- } else {
- for (box=0; box < document.frm_help.check.length; box++) {
- check = document.frm_help.check[box];
- to_check = false;
- for (val in list) {
- if (check.value==trim(list[val])) {
- to_check = true;
- break;
- }
- }
- check.checked = to_check;
- }
- }
-}
-
-function resetList() {
- // reset preview and check boxes to initial values
- if (document.frm_help.check==undefined) { return; }
- writePreview(original_field);
- reviseList(original_field);
-}
-
-function writePreview(val) {
- // writes a value to the text_preview
- document.frm_help.text_preview.value = val;
-}
-
-function focusField(name) {
- for(i=0; i < document.forms.length; ++i) {
- var obj = document.forms[i].elements[name];
- if (obj && obj.focus) {obj.focus();}
- }
-}
-
-function selectField(name) {
- for(i=0; i < document.forms.length; ++i) {
- var obj = document.forms[i].elements[name];
- if (obj && obj.focus){obj.focus();}
- if (obj && obj.select){obj.select();}
- }
-}
-
-function checkRequiredFields(fields)
-{
- var bonk='';
- var res='';
- var argv = checkRequiredFields.arguments;
- var argc = argv.length;
- var input = '';
- var val='';
-
- for (var i=0; i < argc; i++) {
- fi = argv[i];
- input = document.getElementById(fi);
- if (input) {
- val = input.value
- if (val == '' || val == '-1' || val == -1) {
- if (res == '') {
- res = fi;
- bonk = input;
- } else {
- res += ', '+fi;
- }
- }
- } else {
- alert('Field with id='+fi+' not found!')
- }
- }
- if (res == '') {
- return submit_once();
- } else {
- alert('Missing value here ('+res+')!');
- if (window.event && window.event.returnvalue) {
- event.returnValue = 0; // work-around for IE
- }
- bonk.focus();
- return false;
- }
-}
-
-/**
- * seeks the given value (2nd argument)
- * in the value of the given input element (1st argument),
- * which is considered a list of values, separated by commas
- */
-function has_value(input, val)
-{
- var actval = input.value
- var arr = feld.value.split(',');
- var max = arr.length;
- for (i=0;i<max;i++) {
- if (trim(arr[i]) == val) {
- return true
- }
- }
- return false
-}
-
-/**
- * Switch Value:
- * change the value of the given input field (might be of type text or hidden),
- * adding or removing the value of the given checkbox field (might be a radio
- * button as well)
- *
- * This function doesn't care whether or not the checkboxes of all values of
- * interest are present; but of course it doesn't have total control of the
- * text field.
- */
-function switch_val(text, check)
-{
- var switched_val = check.value
- var arr = text.value.split(',')
- var max = arr.length
- if (check.checked) {
- for (i=0; i<max; i++) {
- if (trim(arr[i]) == switched_val) {
- return
- }
- }
- if (text.value)
- text.value = text.value+','+switched_val
- else
- text.value = switched_val
- } else {
- var neu = ''
- var changed = false
- for (i=0; i<max; i++) {
- if (trim(arr[i]) == switched_val) {
- changed=true
- } else {
- neu = neu+','+trim(arr[i])
- }
- }
- if (changed) {
- text.value = neu.substr(1)
- }
- }
-}
-
-/**
- * append the given value (2nd argument) to an input field
- * (1st argument) which contains comma-separated values;
- * see --> remove_val()
- *
- * This will work nicely even for batched lists
- */
-function append_val(name, val)
-{
- var feld = document.itemSynopsis[name];
- var actval = feld.value;
- if (actval == '') {
- feld.value = val
- } else {
- var arr = feld.value.split(',');
- var max = arr.length;
- for (i=0;i<max;i++) {
- if (trim(arr[i]) == val) {
- return
- }
- }
- feld.value = actval+','+val
- }
-}
-
-/**
- * remove the given value (2nd argument) from the comma-separated values
- * of the given input element (1st argument); see --> append_val()
- */
-function remove_val(name, val)
-{
- var feld = document.itemSynopsis[name];
- var actval = feld.value;
- var changed=false;
- if (actval == '') {
- return
- } else {
- var arr = feld.value.split(',');
- var max = arr.length;
- var neu = ''
- for (i=0;i<max;i++) {
- if (trim(arr[i]) == val) {
- changed=true
- } else {
- neu = neu+','+trim(arr[i])
- }
- }
- if (changed) {
- feld.value = neu.substr(1)
- }
- }
-}
-
-/**
- * give the focus to the element given by id
- */
-function focus2id(name)
-{
- document.getElementById(name).focus();
-}
diff --git a/templates/classic/html/home.classlist.html b/templates/classic/html/home.classlist.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title" i18n:translate="">List of classes - <span
- i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">List of classes</span>
-<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
+++ /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/templates/classic/html/issue.index.html b/templates/classic/html/issue.index.html
+++ /dev/null
@@ -1,166 +0,0 @@
-<!-- $Id: issue.index.html,v 1.29 2007-09-18 17:44:26 jpend Exp $ -->
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title" >
- <span tal:omit-tag="true" i18n:translate="" >List of issues</span>
- <span tal:condition="request/dispname"
- tal:replace="python:' - %s '%request.dispname"
- /> - <span tal:replace="config/TRACKER_NAME" />
-</title>
-<span metal:fill-slot="body_title" tal:omit-tag="true">
- <span tal:omit-tag="true" i18n:translate="" >List of issues</span>
- <span tal:condition="request/dispname"
- tal:replace="python:' - %s' % request.dispname" />
-</span>
-<td class="content" metal:fill-slot="content">
-
-<p tal:condition="python:not (context.is_view_ok()
- or request.user.hasRole('Anonymous'))" i18n:translate="">
- You are not allowed to view this page.</p>
-
-<p tal:condition="python:not context.is_view_ok()
- and request.user.hasRole('Anonymous')" i18n:translate="">
- Please login with your username and password.</p>
-
-<tal:block tal:define="batch request/batch" tal:condition="context/is_view_ok">
- <table class="list">
- <tr>
- <th tal:condition="request/show/priority" i18n:translate="">Priority</th>
- <th tal:condition="request/show/id" i18n:translate="">ID</th>
- <th tal:condition="request/show/creation" i18n:translate="">Creation</th>
- <th tal:condition="request/show/activity" i18n:translate="">Activity</th>
- <th tal:condition="request/show/actor" i18n:translate="">Actor</th>
- <th tal:condition="request/show/keyword" i18n:translate="">Keyword</th>
- <th tal:condition="request/show/title" i18n:translate="">Title</th>
- <th tal:condition="request/show/status" i18n:translate="">Status</th>
- <th tal:condition="request/show/creator" i18n:translate="">Creator</th>
- <th tal:condition="request/show/assignedto" i18n:translate="">Assigned To</th>
- </tr>
- <tal:block tal:repeat="i batch" condition=true>
- <tr tal:define="group python:[r[1] for r in request.group]"
- tal:condition="python:group and batch.propchanged(*group)">
- <th tal:attributes="colspan python:len(request.columns)" class="group">
- <tal:block tal:repeat="g group">
- <tal:block i18n:translate="" tal:content="python:str(i[g]) or '(no %s set)'%g"/>
- </tal:block>
- </th>
- </tr>
-
- <tr>
- <td tal:condition="request/show/priority"
- tal:content="python:i.priority.plain() or default"> </td>
- <td tal:condition="request/show/id" tal:content="i/id"> </td>
- <td class="date" tal:condition="request/show/creation"
- tal:content="i/creation/reldate"> </td>
- <td class="date" tal:condition="request/show/activity"
- tal:content="i/activity/reldate"> </td>
- <td class="date" tal:condition="request/show/actor"
- tal:content="python:i.actor.plain() or default"> </td>
- <td tal:condition="request/show/keyword"
- tal:content="python:i.keyword.plain() or default"> </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"
- i18n:translate=""
- tal:content="python:i.status.plain() or default"> </td>
- <td tal:condition="request/show/creator"
- tal:content="python:i.creator.plain() or default"> </td>
- <td tal:condition="request/show/assignedto"
- tal:content="python:i.assignedto.plain() or default"> </td>
- </tr>
-
- </tal:block>
-
- <metal:index define-macro="batch-footer">
- <tr tal:condition="batch">
- <th tal:attributes="colspan python:len(request.columns)">
- <table width="100%">
- <tr class="navigation">
- <th>
- <a tal:define="prev batch/previous" tal:condition="prev"
- tal:attributes="href python:request.indexargs_url(request.classname,
- {'@startwith':prev.first, '@pagesize':prev.size})"
- i18n:translate=""><< previous</a>
-
- </th>
- <th i18n:translate=""><span tal:replace="batch/start" i18n:name="start"
- />..<span tal:replace="python: batch.start + batch.length -1" i18n:name="end"
- /> out of <span tal:replace="batch/sequence_length" i18n:name="total"
- /></th>
- <th>
- <a tal:define="next batch/next" tal:condition="next"
- tal:attributes="href python:request.indexargs_url(request.classname,
- {'@startwith':next.first, '@pagesize':next.size})"
- i18n:translate="">next >></a>
-
- </th>
- </tr>
- </table>
- </th>
- </tr>
- </metal:index>
-</table>
-
-<a tal:attributes="href python:request.indexargs_url('issue',
- {'@action':'export_csv'})" i18n:translate="">Download as CSV</a>
-
-<form method="GET" class="index-controls"
- tal:attributes="action request/classname">
-
- <table class="form" tal:define="n_sort python:2">
- <tal:block tal:repeat="n python:range(n_sort)" tal:condition="batch">
- <tr tal:define="key python:len(request.sort)>n and request.sort[n]">
- <th>
- <tal:block tal:condition="not:n" i18n:translate="">Sort on:</tal:block>
- </th>
- <td>
- <select tal:attributes="name python:'@sort%d'%n">
- <option value="" i18n:translate="">- nothing -</option>
- <option tal:repeat="col context/properties"
- tal:attributes="value col/_name;
- selected python:key and col._name == key[1]"
- tal:content="col/_name"
- i18n:translate="">column</option>
- </select>
- </td>
- <th i18n:translate="">Descending:</th>
- <td><input type="checkbox" tal:attributes="name python:'@sortdir%d'%n;
- checked python:key and key[0] == '-'">
- </td>
- </tr>
- </tal:block>
- <tal:block tal:repeat="n python:range(n_sort)" tal:condition="batch">
- <tr tal:define="key python:len(request.group)>n and request.group[n]">
- <th>
- <tal:block tal:condition="not:n" i18n:translate="">Group on:</tal:block>
- </th>
- <td>
- <select tal:attributes="name python:'@group%d'%n">
- <option value="" i18n:translate="">- nothing -</option>
- <option tal:repeat="col context/properties"
- tal:attributes="value col/_name;
- selected python:key and col._name == key[1]"
- tal:content="col/_name"
- i18n:translate="">column</option>
- </select>
- </td>
- <th i18n:translate="">Descending:</th>
- <td><input type="checkbox" tal:attributes="name python:'@groupdir%d'%n;
- checked python:key and key[0] == '-'">
- </td>
- </tr>
- </tal:block>
- <tr><td colspan="4">
- <input type="submit" value="Redisplay" i18n:attributes="value">
- <tal:block tal:replace="structure
- python:request.indexargs_form(sort=0, group=0)" />
- </td></tr>
- </table>
-</form>
-
-</tal:block>
-
-</td>
-</tal:block><tal:comment condition=false> vim: sw=1 ts=8 et si
-</tal:comment>
diff --git a/templates/classic/html/issue.item.html b/templates/classic/html/issue.item.html
+++ /dev/null
@@ -1,197 +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">
-<tal:block condition="context/id" i18n:translate=""
- >Issue <tal:x tal:content="context/id" i18n:name="id"
- />: <tal:x content="context/title" i18n:name="title"
- /> - <tal:x content="config/TRACKER_NAME" i18n:name="tracker"
-/></tal:block>
-<tal:block condition="not:context/id" i18n:translate=""
- >New Issue - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker"
-/></tal:block>
-</title>
-<tal:block metal:fill-slot="body_title">
- <span tal:condition="python: not (context.id or context.is_edit_ok())"
- tal:omit-tag="python:1" i18n:translate="">New Issue</span>
- <span tal:condition="python: not context.id and context.is_edit_ok()"
- tal:omit-tag="python:1" i18n:translate="">New Issue Editing</span>
- <span tal:condition="python: context.id and not context.is_edit_ok()"
- tal:omit-tag="python:1" i18n:translate="">Issue<tal:x
- replace="context/id" i18n:name="id" /></span>
- <span tal:condition="python: context.id and context.is_edit_ok()"
- tal:omit-tag="python:1" i18n:translate="">Issue<tal:x
- replace="context/id" i18n:name="id" /> Editing</span>
-</tal:block>
-
-<td class="content" metal:fill-slot="content">
-
-<p tal:condition="python:not (context.is_view_ok()
- or request.user.hasRole('Anonymous'))" i18n:translate="">
- You are not allowed to view this page.</p>
-
-<p tal:condition="python:not context.is_view_ok()
- and request.user.hasRole('Anonymous')" i18n:translate="">
- Please login with your username and password.</p>
-
-<div tal:condition="context/is_view_ok">
-
-<form method="POST" name="itemSynopsis"
- onSubmit="return submit_once()" enctype="multipart/form-data"
- tal:attributes="action context/designator">
-
-<table class="form">
-<tr>
- <th class="required" i18n:translate="">Title</th>
- <td colspan=3 tal:content="structure python:context.title.field(size=60)">title</td>
-</tr>
-
-<tr>
- <th class="required" i18n:translate="">Priority</th>
- <td tal:content="structure context/priority/menu">priority</td>
- <th i18n:translate="">Status</th>
- <td tal:content="structure context/status/menu">status</td>
-</tr>
-
-<tr>
- <th i18n:translate="">Superseder</th>
- <td>
- <span tal:replace="structure python:context.superseder.field(showid=1, size=20)" />
- <span tal:condition="context/is_edit_ok" tal:replace="structure python:db.issue.classhelp('id,title', property='superseder')" />
- <span tal:condition="context/superseder">
- <br><span i18n:translate="">View:</span>
- <a tal:repeat="sup context/superseder"
- tal:content="python:sup['id'] + ', '*(not repeat['sup'].end)"
- tal:attributes="href string:issue${sup/id}"></a>
- </span>
- </td>
- <th i18n:translate="">Nosy List</th>
- <td>
- <span tal:replace="structure context/nosy/field" />
- <span tal:condition="context/is_edit_ok" tal:replace="structure
-python:db.user.classhelp('username,realname,address', property='nosy', width='600')" /><br>
- </td>
-</tr>
-
-<tr>
- <th i18n:translate="">Assigned To</th>
- <td tal:content="structure context/assignedto/menu">assignedto menu</td>
- <th i18n:translate="">Keywords</th>
- <td>
- <span tal:replace="structure context/keyword/field" />
- <span tal:condition="context/is_edit_ok" tal:replace="structure python:db.keyword.classhelp(property='keyword')" />
- </td>
-</tr>
-
-<tr tal:condition="context/is_edit_ok">
- <th i18n:translate="">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 tal:condition="context/is_edit_ok">
- <th i18n:translate="">File</th>
- <td colspan=3><input type="file" name="@file" size="40"></td>
-</tr>
-
-<tr tal:condition="context/is_edit_ok">
- <td>
-
- <input type="hidden" name="@template" value="item">
- <input type="hidden" name="@required" value="title,priority">
- </td>
- <td colspan=3>
- <span tal:replace="structure context/submit">submit button</span>
- <a tal:condition="context/id" tal:attributes="href context/copy_url"
- i18n:translate="">Make a copy</a>
- </td>
-</tr>
-
-</table>
-</form>
-
-<tal:block tal:condition="not:context/id" i18n:translate="">
-<table class="form">
-<tr>
- <td>Note: </td>
- <th class="required">highlighted</th>
- <td> fields are required.</td>
-</tr>
-</table>
-</tal:block>
-
-<p tal:condition="context/id" i18n:translate="">
- Created on <b tal:content="context/creation" i18n:name="creation" />
- by <b tal:content="context/creator" i18n:name="creator" />,
- last changed <b content="context/activity" i18n:name="activity" />
- by <b tal:content="context/actor" i18n:name="actor" />.
-</p>
-
-<table class="files" tal:condition="context/files">
- <tr><th colspan="5" class="header" i18n:translate="">Files</th></tr>
- <tr>
- <th i18n:translate="">File name</th>
- <th i18n:translate="">Uploaded</th>
- <th i18n:translate="">Type</th>
- <th i18n:translate="">Edit</th>
- <th i18n:translate="">Remove</th>
- </tr>
- <tr tal:repeat="file context/files">
- <td>
- <a tal:attributes="href file/download_url"
- 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>
- <td tal:content="file/type" />
- <td><a tal:condition="file/is_edit_ok"
- tal:attributes="href string:file${file/id}">edit</a>
- </td>
- <td>
- <form style="padding:0" tal:condition="context/is_edit_ok"
- tal:attributes="action string:issue${context/id}">
- <input type="hidden" name="@remove@files" tal:attributes="value file/id">
- <input type="hidden" name="@action" value="edit">
- <input type="submit" value="remove" i18n:attributes="value">
- </form>
- </td>
- </tr>
-</table>
-
-<table class="messages" tal:condition="context/messages">
- <tr><th colspan="4" class="header" i18n:translate="">Messages</th></tr>
- <tal:block tal:repeat="msg context/messages/reverse">
- <tr>
- <th><a tal:attributes="href string:msg${msg/id}"
- i18n:translate="">msg<tal:x replace="msg/id" i18n:name="id" /> (view)</a></th>
- <th i18n:translate="">Author: <tal:x replace="msg/author"
- i18n:name="author" /></th>
- <th i18n:translate="">Date: <tal:x replace="msg/date"
- i18n:name="date" /></th>
- <th>
- <form style="padding:0" tal:condition="context/is_edit_ok"
- tal:attributes="action string:issue${context/id}">
- <input type="hidden" name="@remove@messages" tal:attributes="value msg/id">
- <input type="hidden" name="@action" value="edit">
- <input type="submit" value="remove" i18n:attributes="value">
- </form>
- </th>
- </tr>
- <tr>
- <td colspan="4" class="content">
- <pre tal:content="structure msg/content/hyperlinked">content</pre>
- </td>
- </tr>
- </tal:block>
-</table>
-
-<tal:block tal:condition="context/id" tal:replace="structure context/history" />
-
-</div>
-
-</td>
-
-</tal:block>
diff --git a/templates/classic/html/issue.search.html b/templates/classic/html/issue.search.html
+++ /dev/null
@@ -1,234 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title" i18n:translate="">Issue searching - <span
- i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">Issue searching</span>
-<td class="content" metal:fill-slot="content">
-
-<form method="GET" name="itemSynopsis"
- tal:attributes="action request/classname">
-
-<table class="form" tal:define="
- cols python:request.columns or 'id activity title status assignedto'.split();
- sort_on python:request.sort and request.sort[0] or nothing;
- sort_desc python:sort_on and sort_on[0] == '-';
- sort_on python:(sort_on and sort_on[1]) or 'activity';
- group_on python:request.group and request.group[0] or nothing;
- group_desc python:group_on and group_on[0] == '-';
- group_on python:(group_on and group_on[1]) or 'priority';
-
- search_input templates/page/macros/search_input;
- search_date templates/page/macros/search_date;
- column_input templates/page/macros/column_input;
- sort_input templates/page/macros/sort_input;
- group_input templates/page/macros/group_input;
- search_select templates/page/macros/search_select;
- search_select_translated templates/page/macros/search_select_translated;
- search_multiselect templates/page/macros/search_multiselect;">
-
-<tr>
- <th class="header"> </th>
- <th class="header" i18n:translate="">Filter on</th>
- <th class="header" i18n:translate="">Display</th>
- <th class="header" i18n:translate="">Sort on</th>
- <th class="header" i18n:translate="">Group on</th>
-</tr>
-
-<tr tal:define="name string:@search_text">
- <th i18n:translate="">All text*:</th>
- <td metal:use-macro="search_input"></td>
- <td> </td>
- <td> </td>
- <td> </td>
-</tr>
-
-<tr tal:define="name string:title">
- <th i18n:translate="">Title:</th>
- <td metal:use-macro="search_input"></td>
- <td metal:use-macro="column_input"></td>
- <td metal:use-macro="sort_input"></td>
- <td> </td>
-</tr>
-
-<tr tal:define="name string:keyword;
- db_klass string:keyword;
- db_content string:name;">
- <th i18n:translate="">Keyword:</th>
- <td metal:use-macro="search_select">
- <option metal:fill-slot="extra_options" value="-1" i18n:translate=""
- tal:attributes="selected python:value == '-1'">not selected</option>
- </td>
- <td metal:use-macro="column_input"></td>
- <td metal:use-macro="sort_input"></td>
- <td metal:use-macro="group_input"></td>
-</tr>
-
-<tr tal:define="name string:id">
- <th i18n:translate="">ID:</th>
- <td metal:use-macro="search_input"></td>
- <td metal:use-macro="column_input"></td>
- <td metal:use-macro="sort_input"></td>
- <td> </td>
-</tr>
-
-<tr tal:define="name string:creation">
- <th i18n:translate="">Creation Date:</th>
- <td metal:use-macro="search_date"></td>
- <td metal:use-macro="column_input"></td>
- <td metal:use-macro="sort_input"></td>
- <td metal:use-macro="group_input"></td>
-</tr>
-
-<tr tal:define="name string:creator;
- db_klass string:user;
- db_content string:username;"
- tal:condition="db/user/is_view_ok">
- <th i18n:translate="">Creator:</th>
- <td metal:use-macro="search_select">
- <option metal:fill-slot="extra_options" i18n:translate=""
- tal:attributes="value request/user/id">created by me</option>
- </td>
- <td metal:use-macro="column_input"></td>
- <td metal:use-macro="sort_input"></td>
- <td metal:use-macro="group_input"></td>
-</tr>
-
-<tr tal:define="name string:activity">
- <th i18n:translate="">Activity:</th>
- <td metal:use-macro="search_date"></td>
- <td metal:use-macro="column_input"></td>
- <td metal:use-macro="sort_input"></td>
- <td> </td>
-</tr>
-
-<tr tal:define="name string:actor;
- db_klass string:user;
- db_content string:username;"
- tal:condition="db/user/is_view_ok">
- <th i18n:translate="">Actor:</th>
- <td metal:use-macro="search_select">
- <option metal:fill-slot="extra_options" i18n:translate=""
- tal:attributes="value request/user/id">done by me</option>
- </td>
- <td metal:use-macro="column_input"></td>
- <td metal:use-macro="sort_input"></td>
- <td> </td>
-</tr>
-
-<tr tal:define="name string:priority;
- db_klass string:priority;
- db_content string:name;">
- <th i18n:translate="">Priority:</th>
- <td metal:use-macro="search_select_translated">
- <option metal:fill-slot="extra_options" value="-1" i18n:translate=""
- tal:attributes="selected python:value == '-1'">not selected</option>
- </td>
- <td metal:use-macro="column_input"></td>
- <td metal:use-macro="sort_input"></td>
- <td metal:use-macro="group_input"></td>
-</tr>
-
-<tr tal:define="name string:status;
- db_klass string:status;
- db_content string:name;">
- <th i18n:translate="">Status:</th>
- <td metal:use-macro="search_select_translated">
- <tal:block metal:fill-slot="extra_options">
- <option value="-1,1,2,3,4,5,6,7" i18n:translate=""
- tal:attributes="selected python:value == '-1,1,2,3,4,5,6,7'">not resolved</option>
- <option value="-1" i18n:translate=""
- tal:attributes="selected python:value == '-1'">not selected</option>
- </tal:block>
- </td>
- <td metal:use-macro="column_input"></td>
- <td metal:use-macro="sort_input"></td>
- <td metal:use-macro="group_input"></td>
-</tr>
-
-<tr tal:define="name string:assignedto;
- db_klass string:user;
- db_content string:username;"
- tal:condition="db/user/is_view_ok">
- <th i18n:translate="">Assigned to:</th>
- <td metal:use-macro="search_select">
- <tal:block metal:fill-slot="extra_options">
- <option tal:attributes="value request/user/id"
- i18n:translate="">assigned to me</option>
- <option value="-1" tal:attributes="selected python:value == '-1'"
- i18n:translate="">unassigned</option>
- </tal:block>
- </td>
- <td metal:use-macro="column_input"></td>
- <td metal:use-macro="sort_input"></td>
- <td metal:use-macro="group_input"></td>
-</tr>
-
-<tr>
- <th i18n:translate="">No Sort or group:</th>
- <td> </td>
- <td> </td>
- <td><input type="radio" name="@sort" value=""></td>
- <td><input type="radio" name="@group" value=""></td>
-</tr>
-
-<tr>
-<th i18n:translate="">Pagesize:</th>
-<td><input name="@pagesize" size="3" value="50"
- tal:attributes="value request/form/@pagesize/value | default"></td>
-</tr>
-
-<tr>
-<th i18n:translate="">Start With:</th>
-<td><input name="@startwith" size="3" value="0"
- tal:attributes="value request/form/@startwith/value | default"></td>
-</tr>
-
-<tr>
-<th i18n:translate="">Sort Descending:</th>
-<td><input type="checkbox" name="@sortdir"
- tal:attributes="checked sort_desc">
-</td>
-</tr>
-
-<tr>
-<th i18n:translate="">Group Descending:</th>
-<td><input type="checkbox" name="@groupdir"
- tal:attributes="checked group_desc">
-</td>
-</tr>
-
-<tr tal:condition="python:request.user.hasPermission('Edit', 'query')">
- <th i18n:translate="">Query name**:</th>
- <td tal:define="value request/form/@queryname/value | nothing">
- <input name="@queryname" tal:attributes="value value">
- <input type="hidden" name="@old-queryname" tal:attributes="value value">
- </td>
-</tr>
-
-<tr>
- <td>
-
- <input type="hidden" name="@action" value="search">
- </td>
- <td><input type="submit" value="Search" i18n:attributes="value"></td>
-</tr>
-
-<tr><td> </td>
- <td colspan="4" class="help">
- <span i18n:translate="" tal:omit-tag="true">
- *: The "all text" field will look in message bodies and issue titles
- </span><br>
- <span tal:condition="python:request.user.hasPermission('Edit', 'query')"
- i18n:translate="" tal:omit-tag="true"
- >
- **: If you supply a name, the query will be saved off and available as a
- link in the sidebar
- </span>
- </td>
-</tr>
-</table>
-
-</form>
-</td>
-
-</tal:block>
diff --git a/templates/classic/html/keyword.item.html b/templates/classic/html/keyword.item.html
+++ /dev/null
@@ -1,55 +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" i18n:translate="">Keyword editing - <span
- i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">Keyword editing</span>
-<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" i18n:translate="">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" i18n:translate="">
- 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" i18n:translate="">
- 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"
- tal:attributes="action context/designator">
-
- <table class="form">
- <tr>
- <th i18n:translate="">Keyword</th>
- <td tal:content="structure context/name/field">name</td>
- </tr>
-
- <tr>
- <td>
-
- <input type="hidden" name="@required" value="name">
- <input type="hidden" name="@template" value="item">
- </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
+++ /dev/null
@@ -1,25 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title" i18n:translate=""
- >List of messages - <span tal:replace="config/TRACKER_NAME"
- i18n:name="tracker"/></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">Message listing</span>
-<td class="content" metal:fill-slot="content">
-<table tal:define="batch request/batch" class="messages">
- <tr><th colspan=2 class="header" i18n:translate="">Messages</th></tr>
- <tal:block tal:repeat="msg batch">
- <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>
-
- <metal:block use-macro="templates/issue.index/macros/batch-footer" />
-
-</table>
-</td>
-
-</tal:block>
diff --git a/templates/classic/html/msg.item.html b/templates/classic/html/msg.item.html
+++ /dev/null
@@ -1,83 +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">
-<tal:block condition="context/id" i18n:translate=""
- >Message <span tal:replace="context/id" i18n:name="id"
- /> - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker"
-/></tal:block>
-<tal:block condition="not:context/id" i18n:translate=""
- >New Message - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker"
-/></tal:block>
-</title>
-<tal:block metal:fill-slot="body_title">
- <span tal:condition="python: not (context.id or context.is_edit_ok())"
- tal:omit-tag="python:1" i18n:translate="">New Message</span>
- <span tal:condition="python: not context.id and context.is_edit_ok()"
- tal:omit-tag="python:1" i18n:translate="">New Message Editing</span>
- <span tal:condition="python: context.id and not context.is_edit_ok()"
- tal:omit-tag="python:1" i18n:translate="">Message<tal:x
- replace="context/id" i18n:name="id" /></span>
- <span tal:condition="python: context.id and context.is_edit_ok()"
- tal:omit-tag="python:1" i18n:translate="">Message<tal:x
- replace="context/id" i18n:name="id" /> Editing</span>
-</tal:block>
-<td class="content" metal:fill-slot="content">
-
-<p tal:condition="python:not (context.is_view_ok()
- or request.user.hasRole('Anonymous'))" i18n:translate="">
- You are not allowed to view this page.</p>
-
-<p tal:condition="python:not context.is_view_ok()
- and request.user.hasRole('Anonymous')" i18n:translate="">
- Please login with your username and password.</p>
-
-<div tal:condition="context/is_view_ok">
-<table class="form">
-
-<tr>
- <th i18n:translate="">Author</th>
- <td tal:content="context/author"></td>
-</tr>
-
-<tr>
- <th i18n:translate="">Recipients</th>
- <td tal:content="context/recipients"></td>
-</tr>
-
-<tr>
- <th i18n:translate="">Date</th>
- <td tal:content="context/date"></td>
-</tr>
-</table>
-
-<table class="messages">
- <tr><th colspan=2 class="header" i18n:translate="">Content</th></tr>
- <tr>
- <td class="content" colspan=2><pre tal:content="structure context/content/hyperlinked"></pre></td>
- </tr>
-</table>
-
-<table class="files" tal:condition="context/files">
- <tr><th colspan="2" class="header" i18n:translate="">Files</th></tr>
- <tr>
- <th i18n:translate="">File name</th>
- <th i18n:translate="">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" />
-
-</div>
-</td>
-
-</tal:block>
diff --git a/templates/classic/html/page.html b/templates/classic/html/page.html
+++ /dev/null
@@ -1,347 +0,0 @@
-<!-- vim:sw=2 sts=2
---><tal:block metal:define-macro="icing"
-><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<title metal:define-slot="head_title">title goes here</title>
-<link rel="stylesheet" type="text/css" href="@@file/style.css">
-<meta http-equiv="Content-Type"
- tal:attributes="content string:text/html;; charset=${request/client/charset}" />
-<script tal:replace="structure request/base_javascript">
-</script>
-<metal:x define-slot="more-javascript" />
-
-</head>
-<body class="body">
-
-<table class="body"
- tal:define="
-kw_edit python:request.user.hasPermission('Edit', 'keyword');
-kw_create python:request.user.hasPermission('Create', 'keyword');
-kw_edit_link python:kw_edit and db.keyword.list();
-columns string:id,activity,title,creator,status;
-columns_showall string:id,activity,title,creator,assignedto,status;
-status_notresolved string:-1,1,2,3,4,5,6,7;
-"
->
-
-<tr>
- <td class="page-header-left"> </td>
- <td class="page-header-top">
- <div id="body-title">
- <h2><span metal:define-slot="body_title">body title</span></h2>
- </div>
- <div id="searchbox">
- <form method="GET" action="issue">
- <input type="hidden" name="@columns"
- tal:attributes="value columns_showall"
- value="id,activity,title,creator,assignedto,status"/>
- <input type="hidden" name="@sort" value="activity"/>
- <input type="hidden" name="@group" value="priority"/>
- <input id="search-text" name="@search_text" size="10"
- tal:attributes="value request/search_text | default" />
- <input type="submit" id="submit" name="submit" value="Search"
- i18n:attributes="value" />
- </form>
- </div>
- </td>
-</tr>
-
-<tr>
- <td rowspan="2" valign="top" class="sidebar">
- <p class="classblock"
- tal:condition="python:request.user.hasPermission('View', 'query')">
- <span i18n:translate=""
- ><b>Your Queries</b> (<a href="query?@template=edit">edit</a>)</span><br>
- <tal:block tal:repeat="qs request/user/queries">
- <a href="#" tal:attributes="href string:${qs/klass}?${qs/url}&@dispname=${qs/name}"
- tal:content="qs/name">link</a><br>
- </tal:block>
- </p>
-
- <form method="POST" tal:attributes="action request/base">
- <p class="classblock"
- tal:condition="python:request.user.hasPermission('View', 'issue')">
- <b i18n:translate="">Issues</b><br>
- <span tal:condition="python:request.user.hasPermission('Create', 'issue')">
- <a href="issue?@template=item" i18n:translate="">Create New</a><br>
- </span>
- <a href="#"
- tal:attributes="href python:request.indexargs_url('issue', {
- '@sort': '-activity',
- '@group': 'priority',
- '@filter': 'status,assignedto',
- '@columns': columns,
- '@search_text': '',
- 'status': status_notresolved,
- 'assignedto': '-1',
- '@dispname': i18n.gettext('Show Unassigned'),
- })"
- i18n:translate="">Show Unassigned</a><br>
- <a href="#"
- tal:attributes="href python:request.indexargs_url('issue', {
- '@sort': '-activity',
- '@group': 'priority',
- '@filter': 'status',
- '@columns': columns_showall,
- '@search_text': '',
- 'status': status_notresolved,
- '@dispname': i18n.gettext('Show All'),
- })"
- i18n:translate="">Show All</a><br>
- <a href="issue?@template=search" i18n:translate="">Search</a><br>
- <input type="submit" class="form-small" value="Show issue:"
- i18n:attributes="value"><input class="form-small" 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:kw_edit or kw_create">
- <b i18n:translate="">Keywords</b><br>
- <span tal:condition="python:request.user.hasPermission('Create', 'keyword')">
- <a href="keyword?@template=item" i18n:translate="">Create New</a><br>
- </span>
- <span tal:condition="kw_edit_link">
- <a href="keyword?@template=item" i18n:translate="">Edit Existing</a><br>
- </span>
- </p>
-
- <p class="classblock"
- tal:condition="python:request.user.hasPermission('View', 'user')">
- <b i18n:translate="">Administration</b><br>
- <span tal:condition="python:request.user.hasPermission('Edit', None)">
- <a href="home?@template=classlist" i18n:translate="">Class List</a><br>
- </span>
- <span tal:condition="python:request.user.hasPermission('View', 'user')
- or request.user.hasPermission('Edit', 'user')">
- <a href="user" i18n:translate="">User List</a><br>
- </span>
- <a tal:condition="python:request.user.hasPermission('Create', 'user')"
- href="user?@template=item" i18n:translate="">Add User</a>
- </p>
-
- <form method="POST" tal:condition="python:request.user.username=='anonymous'"
- tal:attributes="action request/base">
- <p class="userblock">
- <b i18n:translate="">Login</b><br>
- <input size="10" name="__login_name"><br>
- <input size="10" type="password" name="__login_password"><br>
- <input type="hidden" name="@action" value="Login">
- <input type="checkbox" name="remember" id="remember">
- <label for="remember" i18n:translate="">Remember me?</label><br>
- <input type="submit" value="Login" i18n:attributes="value"><br>
- <input type="hidden" name="__came_from" tal:attributes="value string:${request/base}${request/env/PATH_INFO}">
- <span tal:replace="structure request/indexargs_form" />
- <a href="user?@template=register"
- tal:condition="python:request.user.hasPermission('Create', 'user')"
- i18n:translate="">Register</a><br>
- <a href="user?@template=forgotten" i18n:translate="">Lost your login?</a><br>
- </p>
- </form>
-
- <p class="userblock" tal:condition="python:request.user.username != 'anonymous'">
- <b i18n:translate="">Hello, <span i18n:name="user"
- tal:replace="python:request.user.username.plain(escape=1)">username</span></b><br>
- <a href="#"
- tal:attributes="href python:request.indexargs_url('issue', {
- '@sort': '-activity',
- '@group': 'priority',
- '@filter': 'status,assignedto',
- '@columns': 'id,activity,title,creator,status',
- '@search_text': '',
- 'status': status_notresolved,
- 'assignedto': request.user.id,
- '@dispname': i18n.gettext('Your Issues'),
- })"
- i18n:translate="">Your Issues</a><br>
- <a href="#" tal:attributes="href string:user${request/user/id}"
- i18n:translate="">Your Details</a><br>
- <a href="#" tal:attributes="href python:request.indexargs_url('',
- {'@action':'logout'})" i18n:translate="">Logout</a>
- </p>
- <p class="userblock">
- <b i18n:translate="">Help</b><br>
- <a href="http://roundup.sourceforge.net/doc-1.0/"
- i18n:translate="">Roundup docs</a>
- </p>
- </td>
- <td>
- <p tal:condition="options/error_message | nothing" class="error-message"
- tal:repeat="m options/error_message" tal:content="structure m" />
- <p tal:condition="options/ok_message | nothing" class="ok-message">
- <span tal:repeat="m options/ok_message"
- tal:content="structure string:$m <br/ > " />
- <a class="form-small" tal:attributes="href request/current_url"
- i18n:translate="">clear this message</a>
- </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>
-</tal:block>
-
-<!--
-The following macros are intended to be used in search pages.
-
-The invoking context must define a "name" variable which names the
-property being searched.
-
-See issue.search.html in the classic template for examples.
--->
-
-<!-- creates a th and a label: -->
-<th metal:define-macro="th_label"
- tal:define="required required | python:[]"
- tal:attributes="class python:(name in required) and 'required' or nothing">
- <label tal:attributes="for name" tal:content="label" i18n:translate="">text</label>
- <metal:x define-slot="behind_the_label" />
-</th>
-
-<td metal:define-macro="search_input">
- <input tal:attributes="value python:request.form.getvalue(name) or nothing;
- name name;
- id name">
-</td>
-
-<td metal:define-macro="search_date">
- <input tal:attributes="value python:request.form.getvalue(name) or nothing;
- name name;
- id name">
- <a class="classhelp"
- tal:attributes="href python:'''javascript:help_window('issue?@template=calendar&property=%s&form=itemSynopsis', 300, 200)'''%name">(cal)</a>
-</td>
-
-<td metal:define-macro="search_popup">
- <!--
- context needs to specify the popup "columns" as a comma-separated
- string (eg. "id,title" or "id,name,description") as well as name
- -->
- <input tal:attributes="value python:request.form.getvalue(name) or nothing;
- name name;
- id name">
- <span tal:replace="structure python:db.issue.classhelp(columns,
- property=name)" />
-</td>
-
-<td metal:define-macro="search_select">
- <select tal:attributes="name name; id name"
- tal:define="value python:request.form.getvalue(name)">
- <option value="" i18n:translate="">don't care</option>
- <metal:slot define-slot="extra_options" />
- <option value="" i18n:translate="" disabled="disabled">------------</option>
- <option tal:repeat="s python:db[db_klass].list()"
- tal:attributes="value s/id; selected python:value == s.id"
- tal:content="python:s[db_content]"></option>
- </select>
-</td>
-
-<!-- like search_select, but translates the further values.
-Could extend it (METAL 1.1 attribute "extend-macro")
--->
-<td metal:define-macro="search_select_translated">
- <select tal:attributes="name name; id name"
- tal:define="value python:request.form.getvalue(name)">
- <option value="" i18n:translate="">don't care</option>
- <metal:slot define-slot="extra_options" />
- <option value="" i18n:translate="" disabled="disabled">------------</option>
- <option tal:repeat="s python:db[db_klass].list()"
- tal:attributes="value s/id; selected python:value == s.id"
- tal:content="python:s[db_content]"
- i18n:translate=""></option>
- </select>
-</td>
-
-<!-- currently, there is no convenient API to get a list of all roles -->
-<td metal:define-macro="search_select_roles"
- tal:define="onchange onchange | nothing">
- <select name=roles id=roles tal:attributes="onchange onchange">
- <option value="" i18n:translate="">don't care</option>
- <option value="" i18n:translate="" disabled="disabled">------------</option>
- <option value="User">User</option>
- <option value="Admin">Admin</option>
- <option value="Anonymous">Anonymous</option>
- </select>
-</td>
-
-<td metal:define-macro="search_multiselect">
- <input tal:attributes="value python:request.form.getvalue(name) or nothing;
- name name;
- id name">
- <span tal:replace="structure python:db[db_klass].classhelp(db_content,
- property=name, width='600')" />
-</td>
-
-<td metal:define-macro="search_checkboxes">
- <ul class="search-checkboxes"
- tal:define="value python:request.form.getvalue(name);
- values python:value and value.split(',') or []">
- <li tal:repeat="s python:db[db_klass].list()">
- <input type="checkbox" tal:attributes="name name; id string:$name-${s/id};
- value s/id; checked python:s.id in values" />
- <label tal:attributes="for string:$name-${s/id}"
- tal:content="python:s[db_content]" />
- </li>
- <li metal:define-slot="no_value_item">
- <input type="checkbox" value="-1" tal:attributes="name name;
- id string:$name--1; checked python:value == '-1'" />
- <label tal:attributes="for string:$name--1" i18n:translate="">no value</label>
- </li>
- </ul>
-</td>
-
-<td metal:define-macro="column_input">
- <input type="checkbox" name="@columns"
- tal:attributes="value name;
- checked python:name in cols">
-</td>
-
-<td metal:define-macro="sort_input">
- <input type="radio" name="@sort"
- tal:attributes="value name;
- checked python:name == sort_on">
-</td>
-
-<td metal:define-macro="group_input">
- <input type="radio" name="@group"
- tal:attributes="value name;
- checked python:name == group_on">
-</td>
-
-<!--
-The following macros are intended for user editing.
-
-The invoking context must define a "name" variable which names the
-property being searched; the "edit_ok" variable tells whether the
-current user is allowed to edit.
-
-See user.item.html in the classic template for examples.
--->
-<script metal:define-macro="user_utils" type="text/javascript" src="@@file/user_utils.js"></script>
-
-<!-- src: value will be re-used for other input fields -->
-<input metal:define-macro="user_src_input"
- type="text" tal:attributes="onblur python:edit_ok and 'split_name(this)';
- id name; name name; value value; readonly not:edit_ok"
- value="heinz.kunz">
-<!-- normal: no re-using -->
-<input metal:define-macro="user_normal_input" type="text"
- tal:attributes="id name; name name; value value; readonly not:edit_ok"
- value="heinz">
-<!-- password: type; no initial value -->
- <input metal:define-macro="user_pw_input" type="password"
- tal:attributes="id name; name name; readonly not:edit_ok" value="">
- <input metal:define-macro="user_confirm_input" type="password"
- tal:attributes="id name; name string:@confirm@$name; readonly not:edit_ok" value="">
-
diff --git a/templates/classic/html/query.edit.html b/templates/classic/html/query.edit.html
+++ /dev/null
@@ -1,111 +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" i18n:translate=""
- >"Your Queries" Editing - <span tal:replace="config/TRACKER_NAME"
- i18n:name="tracker" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">"Your Queries" Editing</span>
-
-<td class="content" metal:fill-slot="content">
-
-<span tal:condition="not:context/is_edit_ok"
- i18n:translate="">You are not allowed to edit queries.</span>
-
-<script language="javascript">
-// This exists solely because I can't figure how to get the & into an
-// attributes TALES expression, and so it keeps getting quoted.
-function retire(qid) {
- window.location = 'query'+qid+'?@action=retire&@template=edit';
-}
-</script>
-
-<form method="POST" onSubmit="return submit_once()" action="query"
- enctype="multipart/form-data" tal:condition="context/is_edit_ok">
-
-<table class="list" width="100%"
- tal:define="uid request/user/id; mine request/user/queries">
-
-<tr><th i18n:translate="">Query</th>
- <th i18n:translate="">Include in "Your Queries"</th>
- <th i18n:translate="">Edit</th>
- <th i18n:translate="">Private to you?</th>
- <th> </th>
-</tr>
-
-<tr tal:repeat="query mine">
- <tal:block condition="query/is_retired">
-
- <td><a tal:attributes="href string:${query/klass}?${query/url}"
- tal:content="query/name">query</a></td>
-
- <td metal:define-macro="include">
- <select tal:condition="python:query.id not in mine"
- tal:attributes="name string:user${uid}@add@queries">
- <option value="" i18n:translate="">leave out</option>
- <option tal:attributes="value query/id" i18n:translate="">include</option>
- </select>
- <select tal:condition="python:query.id in mine"
- tal:attributes="name string:user${uid}@remove@queries">
- <option value="" i18n:translate="">leave in</option>
- <option tal:attributes="value query/id" i18n:translate="">remove</option>
- </select>
- </td>
-
- <td colspan="3" i18n:translate="">[query is retired]</td>
-
- <!-- <td> maybe offer "restore" some day </td> -->
- </tal:block>
-</tr>
-
-<tr tal:repeat="query mine">
- <tal:block condition="not:query/is_retired">
- <td><a tal:attributes="href string:${query/klass}?${query/url}"
- tal:content="query/name">query</a></td>
-
- <td metal:use-macro="template/macros/include" />
-
- <td><a tal:attributes="href string:query${query/id}" i18n:translate="">edit</a></td>
-
- <td>
- <select tal:attributes="name string:query${query/id}@private_for">
- <option tal:attributes="selected python:query.private_for == uid;
- value uid" i18n:translate="">yes</option>
- <option tal:attributes="selected python:query.private_for == None"
- value="-1" i18n:translate="">no</option>
- </select>
- </td>
-
- <td>
- <input type="button" value="Delete" i18n:attributes="value"
- tal:attributes="onClick python:'''retire('%s')'''%query.id">
- </td>
- </tal:block>
-</tr>
-
-<tr tal:define="queries python:db.query.filter(filterspec={'private_for':None})"
- tal:repeat="query queries">
- <tal:block condition="python: query.creator != uid">
- <td><a tal:attributes="href string:${query/klass}?${query/url}"
- tal:content="query/name">query</a></td>
-
- <td metal:use-macro="template/macros/include" />
-
- <td colspan="3" tal:condition="query/is_edit_ok">
- <a tal:attributes="href string:query${query/id}" i18n:translate="">edit</a>
- </td>
- <td tal:condition="not:query/is_edit_ok" colspan="3"
- i18n:translate="">[not yours to edit]</td>
- </tal:block>
-</tr>
-
-<tr><td colspan="5">
- <input type="hidden" name="@action" value="edit">
- <input type="hidden" name="@template" value="edit">
- <input type="submit" value="Save Selection" i18n:attributes="value">
-</td></tr>
-
-</table>
-
-</form>
-</td>
-</tal:block>
diff --git a/templates/classic/html/query.item.html b/templates/classic/html/query.item.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<!-- query.item -->
-<span tal:replace="structure context/renderQueryForm" />
-
diff --git a/templates/classic/html/style.css b/templates/classic/html/style.css
+++ /dev/null
@@ -1,433 +0,0 @@
-/* main page styles */
-body.body {
- font-family: sans-serif, Arial, Helvetica;
- background-color: white;
- color: #333;
- margin: 0;
-}
-a[href]:hover {
- color:blue;
- text-decoration: underline;
-}
-a[href], a[href]:link {
- color:blue;
- text-decoration: none;
-}
-
-table.body {
- border: 0;
- padding: 0;
- border-spacing: 0;
- border-collapse: separate;
-}
-
-td.page-header-left {
- padding: 5px;
- border-bottom: 1px solid #444;
-}
-td.sidebar {
- padding: 1px 0 0 1px;
- white-space: nowrap;
-}
-
-/* don't display the sidebar when printing */
-@media print {
- td.page-header-left {
- display: none;
- }
- td.sidebar {
- display: none;
- }
- .index-controls {
- display: none;
- }
- #searchbox {
- display: none;
- }
-}
-
-td.page-header-top {
- padding: 5px;
- border-bottom: 1px solid #444;
-}
-#searchbox {
- float: right;
-}
-
-div#body-title {
- float: left;
-}
-
-
-div#searchbox {
- float: right;
- padding-top: 1em;
-}
-
-div#searchbox input#search-text {
- width: 10em;
-}
-
-form {
- margin: 0;
-}
-
-textarea {
- font-family: monospace;
-}
-
-td.sidebar p.classblock {
- padding: 2px 5px 2px 5px;
- margin: 1px;
- border: 1px solid #444;
- background-color: #eee;
-}
-
-td.sidebar p.userblock {
- padding: 2px 5px 2px 5px;
- margin: 1px 1px 1px 1px;
- border: 1px solid #444;
- background-color: #eef;
-}
-
-.form-small {
- padding: 0;
- font-size: 75%;
-}
-
-
-td.content {
- padding: 1px 5px 1px 5px;
- vertical-align: top;
- width: 100%;
-}
-
-td.date, th.date {
- white-space: nowrap;
-}
-
-p.ok-message {
- background-color: #22bb22;
- padding: 5px;
- color: white;
- font-weight: bold;
-}
-p.error-message {
- background-color: #bb2222;
- padding: 5px;
- color: white;
- font-weight: bold;
-}
-p.error-message a[href] {
- color: white;
- text-decoration: underline;
-}
-
-
-/* style for search forms */
-ul.search-checkboxes {
- display: inline;
- padding: 0;
- list-style: none;
-}
-ul.search-checkboxes > li {
- display: inline;
- padding-right: .5em;
-}
-
-
-/* style for forms */
-table.form {
- padding: 2px;
- border-spacing: 0;
- border-collapse: separate;
-}
-
-table.form th {
- color: #338;
- text-align: right;
- vertical-align: top;
- font-weight: normal;
- white-space: nowrap;
-}
-
-table.form th.header {
- font-weight: bold;
- background-color: #eef;
- text-align: left;
-}
-
-table.form th.required {
- font-weight: bold;
-}
-
-table.form td {
- color: #333;
- empty-cells: show;
- vertical-align: top;
-}
-
-table.form td.optional {
- font-weight: bold;
- font-style: italic;
-}
-
-table.form td.html {
- color: #777;
-}
-
-/* style for lists */
-table.list {
- border-spacing: 0;
- border-collapse: separate;
- width: 100%;
-}
-
-table.list th {
- padding: 0 4px 0 4px;
- color: #404070;
- background-color: #eef;
- 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 4px 0 4px;
- border: 1px solid white;
- color: #404070;
- background-color: #efefef;
- vertical-align: top;
- empty-cells: show;
-}
-
-table.list tr.navigation th {
- width: 33%;
- border-style: hidden;
- text-align: center;
-}
-table.list tr.navigation td {
- border: none
-}
-table.list tr.navigation th:first-child {
- text-align: left;
-}
-table.list tr.navigation th:last-child {
- text-align: right;
-}
-
-
-/* style for message displays */
-table.messages {
- border-spacing: 0;
- 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: 2px 5px 2px 5px;
-}
-
-table.messages td:first-child {
- border-left: 1px solid #afafaf;
- border-right: 1px solid #afafaf;
-}
-
-/* style for file displays */
-table.files {
- border-spacing: 0;
- 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: 0;
- 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: 0;
- 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 { /* the table-layout: fixed; */
- table-layout: fixed; /* compromises quality for speed */
- overflow: hidden;
- font-size: .9em;
- padding-bottom: 3em;
-}
-
-table.classhelp th {
- font-weight: normal;
- text-align: left;
- color: #444;
- background-color: #efefef;
- border-bottom: 1px solid #afafaf;
- border-top: 1px solid #afafaf;
- text-transform: uppercase;
- vertical-align: middle;
- line-height:1.5em;
-}
-
-table.classhelp td {
- vertical-align: middle;
- padding-right: .2em;
- border-bottom: 1px solid #efefef;
- text-align: left;
- empty-cells: show;
- white-space: nowrap;
- vertical-align: middle;
-}
-
-table.classhelp tr:hover {
- background-color: #eee;
-}
-
-label.classhelp-label {
- cursor: pointer;
-}
-
-#classhelp-controls {
- position: fixed;
- display: block;
- top: auto;
- right: 0;
- bottom: 0;
- left: 0;
- padding: .5em;
- border-top: 2px solid #444;
- background-color: #eee;
-}
-
-#classhelp-controls input.apply {
- width: 7em;
- font-weight: bold;
- margin-right: 2em;
- margin-left: 2em;
-}
-
-#classhelp-controls input.preview {
- margin-right: 3em;
- margin-left: 1em;
-}
-
-/* style for "other" displays */
-table.otherinfo {
- border-spacing: 0;
- 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;
-}
-input[type="text"]:focus,
-input[type="checkbox"]:focus,
-input[type="radio"]:focus,
-input[type="password"]:focus,
-textarea:focus, select:focus {
- background-color: #ffffc0;
-}
-
-/* vim: sts=2 sw=2 et
-*/
diff --git a/templates/classic/html/user.forgotten.html b/templates/classic/html/user.forgotten.html
+++ /dev/null
@@ -1,43 +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" i18n:translate="">Password reset request - <span
- i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">Password reset request</span>
-<td class="content" metal:fill-slot="content">
-
-<p i18n:translate="">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()"
- tal:attributes="action context/designator">
- <table class="form">
- <tr>
- <th i18n:translate="">Email Address:</th>
- <td><input name="address"></td>
- </tr>
- <tr>
- <td> </td>
- <td>
- <input type="hidden" name="@action" value="passrst">
- <input type="hidden" name="@template" value="forgotten">
- <input type="submit" value="Request password reset"
- i18n:attributes="value">
- </td>
- </tr>
-</table>
-
-<p i18n:translate="">Or, if you know your username, then enter it below.</p>
-
-<table class="form">
- <tr><th i18n:translate="">Username:</th> <td><input name="username"></td> </tr>
- <tr><td></td><td><input type="submit" value="Request password reset"
- i18n:attributes="value"></td></tr>
-</table>
-</form>
-
-<p i18n:translate="">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.help-search.html b/templates/classic/html/user.help-search.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<html
- tal:define="form request/form/form/value;
- field request/form/property/value"
- >
- <head>
- <title>Search input for user helper</title>
- <script language="Javascript" type="text/javascript"
- tal:content="structure string:<!--
- // this is the name of the field in the original form that we're working on
- form = parent.opener.document.${form};
- field = '${field}';
- //-->">
- </script>
- <script type="text/javascript" src="@@file/help_controls.js"></script>
- <link rel="stylesheet" type="text/css" href="@@file/style.css" />
- </head>
- <body onload="parent.submit.url='...'"
- tal:define="
-qs request/env/QUERY_STRING;
-qs python:'&'.join([a for a in qs.split('&') if not a.startswith('@template=')])"
->
- <pre tal:content="request/env/QUERY_STRING" tal:condition=false />
- <form method="GET" name="itemSynopsis"
- target="list"
- tal:attributes="action request/classname"
- tal:define="
- property request/form/property/value;
- cols python:request.columns or 'id username address realname roles'.split();
- sort_on request/sort | nothing;
- sort_desc python:sort_on and request.sort[0][0] == '-';
- sort_on python:sort_on and request.sort[0][1] or 'lastname';
-
- search_input templates/page/macros/search_input;
- search_select templates/page/macros/search_select;
- search_select_roles templates/page/macros/search_select_roles;
- required python:[];
- th_label templates/page/macros/th_label;
- ">
- <input type="hidden" name="@template" value="help-list">
- <input type="hidden" name="property" value="" tal:attributes="value property">
- <input type="hidden" name="form" value="" tal:attributes="value request/form/form/value">
- <table>
-<tr tal:define="name string:username; label string:Username:">
- <th metal:use-macro="th_label">Name</th>
- <td metal:use-macro="search_input"><input type=text></td>
-</tr>
-
-<tr tal:define="name string:phone; label string:Phone number">
- <th metal:use-macro="th_label">Phone</th>
- <td metal:use-macro="search_input"><input type=text></td>
-</tr>
-
-<tr tal:define="name string:roles;
- onchange string:this.form.submit();
- label string:Roles:"
- >
- <th metal:use-macro="th_label">role</th>
- <td metal:use-macro="search_select_roles">
- <select>
- <option value="">jokester</option>
- </select>
- </td>
-</tr>
-
-<tr>
- <td> </td>
- <td>
- <input type="hidden" name="@action" value="search">
- <input type="submit" value="Search" i18n:attributes="value">
- <input type="reset">
- <input type="hidden" value="username,realname,phone,organisation,roles" name="properties">
- <input type="text" name="@pagesize" id="sp-pagesize" value="25" size="2">
- <label for="sp-pagesize" i18n:translate="">Pagesize</label>
- </td>
-</tr>
-
- </table>
-
-</form>
-<pre tal:content="request" tal:condition=false />
-<script type="text/javascript"><!--
- focus2id('username');
-//--></script>
- </body>
-</html>
diff --git a/templates/classic/html/user.help.html b/templates/classic/html/user.help.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html tal:define="property request/form/property/value;
-qs request/env/QUERY_STRING;
-qs python:'&'.join([a for a in qs.split('&') if not a.startswith('@template=')]);
-form request/form/form/value;
-field request/form/property/value">
- <head>
- <link rel="stylesheet" type="text/css" href="@@file/style.css" />
- <meta http-equiv="Content-Type"
- tal:attributes="content string:text/html;; charset=${request/client/charset}" />
- <tal:block tal:condition="python:request.form.has_key('property')">
- <title><tal:x i18n:translate=""><tal:x i18n:name="property"
- tal:content="property" i18n:translate="" /> help - <span i18n:name="tracker"
- tal:replace="config/TRACKER_NAME" /></tal:x></title>
- <script language="Javascript" type="text/javascript"
- tal:condition=false
- tal:content="structure string:<!--
- // this is the name of the field in the original form that we're working on
- form = window.opener.document.${form};
- field = '${field}';
- //-->">
- </script>
- <script src="@@file/help_controls.js"
- tal:condition=false type="text/javascript"><!--
- //--></script>
- </tal:block>
- </head>
-<frameset rows="123,*,62">
- <frame src="#" tal:attributes="src string:?@template=help-search&${qs}" name="search">
- <!-- for search results: help-list -->
- <frame
- tal:attributes="src string:?@template=help-empty&${qs}"
- name="list">
- <frame
- tal:attributes="src string:?@template=help-submit&${qs}"
- name="submit">
- <!-- -->
-</frameset>
-<noframes>
- <body>
-<p i18n:translate="">
-Your browser is not capable of using frames; you should be redirected immediately,
-or visit <a href="#" tal:attributes="href string:?${qs}&template=help-noframes"
-i18n:name="link">this link</a>.
-</p>
-</body>
-</noframes>
-
-</html>
diff --git a/templates/classic/html/user.index.html b/templates/classic/html/user.index.html
+++ /dev/null
@@ -1,45 +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" i18n:translate="">User listing - <span
- i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">User listing</span>
-<td class="content" metal:fill-slot="content">
-
-<span tal:condition="python:not (context.is_view_ok()
- or request.user.hasRole('Anonymous'))"
- i18n:translate="">You are not allowed to view this page.</span>
-
-<span tal:condition="python:not context.is_view_ok()
- and request.user.hasRole('Anonymous')"
- i18n:translate="">Please login with your username and password.</span>
-
-<table width="100%" tal:condition="context/is_view_ok" class="list">
-<tr>
- <th i18n:translate="">Username</th>
- <th i18n:translate="">Real name</th>
- <th i18n:translate="">Organisation</th>
- <th i18n:translate="">Email address</th>
- <th i18n:translate="">Phone number</th>
- <th tal:condition="context/is_edit_ok" i18n:translate="">Retire</th>
-</tr>
-<tal:block repeat="user context/list">
-<tr 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.realname.plain() or default"> </td>
- <td tal:content="python:user.organisation.plain() or default"> </td>
- <td tal:content="python:user.address.email() or default"> </td>
- <td tal:content="python:user.phone.plain() or default"> </td>
- <td tal:condition="context/is_edit_ok">
- <a tal:attributes="href string:user${user/id}?@action=retire&@template=index"
- i18n:translate="">retire</a>
- </td>
-</tr>
-</tal:block>
-</table>
-</td>
-
-</tal:block>
diff --git a/templates/classic/html/user.item.html b/templates/classic/html/user.item.html
+++ /dev/null
@@ -1,169 +0,0 @@
-<!-- dollarId: user.item,v 1.7 2002/08/16 04:29:04 richard Exp dollar-->
-<tal:doc metal:use-macro="templates/page/macros/icing"
-define="edit_ok context/is_edit_ok"
->
-<title metal:fill-slot="head_title">
-<tal:if condition="context/id" i18n:translate=""
- >User <tal:x content="context/id" i18n:name="id"
- />: <tal:x content="context/username" i18n:name="title"
- /> - <tal:x content="config/TRACKER_NAME" i18n:name="tracker"
-/></tal:if>
-<tal:if condition="not:context/id" i18n:translate=""
- >New User - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker"
-/></tal:if>
-</title>
-<metal:slot fill-slot="more-javascript">
-<script metal:use-macro="templates/page/macros/user_utils"></script>
-<script type="text/javascript" src="@@file/help_controls.js"></script>
-</metal:slot>
-<tal:block metal:fill-slot="body_title"
- define="edit_ok context/is_edit_ok">
- <span tal:condition="python: not (context.id or edit_ok)"
- tal:omit-tag="python:1" i18n:translate="">New User</span>
- <span tal:condition="python: not context.id and edit_ok"
- tal:omit-tag="python:1" i18n:translate="">New User Editing</span>
- <span tal:condition="python: context.id and not edit_ok"
- tal:omit-tag="python:1" i18n:translate="">User<tal:x
- replace="context/id" i18n:name="id" /></span>
- <span tal:condition="python: context.id and edit_ok"
- tal:omit-tag="python:1" i18n:translate="">User<tal:x
- replace="context/id" i18n:name="id" /> Editing</span>
-</tal:block>
-
-<td class="content" metal:fill-slot="content">
-
-<p tal:condition="python:not (context.is_view_ok()
- or request.user.hasRole('Anonymous'))" i18n:translate="">
- You are not allowed to view this page.</p>
-
-<p tal:condition="python:not context.is_view_ok()
- and request.user.hasRole('Anonymous')" i18n:translate="">
- Please login with your username and password.</p>
-
-<div tal:condition="context/is_view_ok">
-
-<form method="POST"
- name="itemSynopsis"
- tal:define="required python:'username address'.split()"
- enctype="multipart/form-data"
- tal:attributes="action context/designator;
- onSubmit python:'return checkRequiredFields(\'%s\')'%'\', \''.join(required);
- ">
-<table class="form" tal:define="
- th_label templates/page/macros/th_label;
- src_input templates/page/macros/user_src_input;
- normal_input templates/page/macros/user_normal_input;
- pw_input templates/page/macros/user_pw_input;
- confirm_input templates/page/macros/user_confirm_input;
- edit_ok context/is_edit_ok;
- ">
- <tr tal:define="name string:realname; label string:Name; value context/realname; edit_ok edit_ok">
- <th metal:use-macro="th_label">Name</th>
- <td><input name="realname" metal:use-macro="src_input"></td>
- </tr>
- <tr tal:define="name string:username; label string:Login Name; value context/username">
- <th metal:use-macro="th_label">Login Name</th>
- <td><input metal:use-macro="src_input"></td>
- </tr>
- <tal:if condition="edit_ok">
- <tr tal:define="name string:password; label string:Login Password">
- <th metal:use-macro="th_label">Login Password</th>
- <td><input metal:use-macro="pw_input" type="password"></td>
- </tr>
- <tr tal:define="name string:password; label string:Confirm Password">
- <th metal:use-macro="th_label">Confirm Password</th>
- <td><input metal:use-macro="confirm_input" type="password"></td>
- </tr>
- </tal:if>
- <tal:if condition="python:request.user.hasPermission('Web Roles')">
- <tr tal:define="name string:roles; label string:Roles;">
- <th><label for="roles" i18n:translate="">Roles</label></th>
- <td tal:define="gips context/id">
- <tal:subif condition=gips define="value context/roles">
- <input metal:use-macro="normal_input">
- </tal:subif>
- <tal:subif condition="not:gips" define="value db/config/NEW_WEB_USER_ROLES">
- <input metal:use-macro="normal_input">
- </tal:subif>
- <tal:block i18n:translate="">(to give the user more than one role,
- enter a comma,separated,list)</tal:block>
- </td>
- </tr>
- </tal:if>
-
- <tr tal:define="name string:phone; label string:Phone; value context/phone">
- <th metal:use-macro="th_label">Phone</th>
- <td><input name="phone" metal:use-macro="normal_input"></td>
- </tr>
-
- <tr tal:define="name string:organisation; label string:Organisation; value context/organisation">
- <th metal:use-macro="th_label">Organisation</th>
- <td><input name="organisation" metal:use-macro="normal_input"></td>
- </tr>
-
- <tr tal:condition="python:edit_ok or context.timezone"
- tal:define="name string:timezone; label string:Timezone; value context/timezone">
- <th metal:use-macro="th_label">Timezone</th>
- <td><input name="timezone" metal:use-macro="normal_input">
- <tal:block tal:condition="edit_ok" i18n:translate="">(this is a numeric hour offset, the default is
- <span tal:replace="db/config/DEFAULT_TIMEZONE" i18n:name="zone"
- />)</tal:block>
- </td>
- </tr>
-
- <tr tal:define="name string:address; label string:E-mail address; value context/address">
- <th metal:use-macro="th_label">E-mail address</th>
- <td tal:define="mailto python:context.address.field(id='address');
- mklink python:mailto and not edit_ok">
- <a href="mailto:calvin@the-z.org"
- tal:attributes="href string:mailto:$value"
- tal:content="value"
- tal:condition="python:mklink">calvin@the-z.org</a>
- <tal:if condition=edit_ok>
- <input metal:use-macro="src_input" value="calvin@the-z.org">
- </tal:if>
-
- </td>
- </tr>
-
- <tr>
- <th><label for="alternate_addresses" i18n:translate="">Alternate E-mail addresses<br>One address per line</label></th>
- <td>
- <textarea rows=5 cols=40 tal:replace="structure context/alternate_addresses/multiline">nobody@nowhere.org
-anybody@everywhere.net
-(alternate_addresses)
- </textarea>
- </td>
- </tr>
-
- <tr tal:condition="edit_ok">
- <td>
-
- <input type="hidden" name="@template" value="item">
- <input type="hidden" name="@required" value="username,address"
- tal:attributes="value python:','.join(required)">
- </td>
- <td><input type="submit" value="save" tal:replace="structure context/submit"><!--submit button here-->
- <input type=reset>
- </td>
- </tr>
-</table>
-</form>
-
-<tal:block tal:condition="not:context/id" i18n:translate="">
-<table class="form">
-<tr>
- <td>Note: </td>
- <th class="required">highlighted</th>
- <td> fields are required.</td>
-</tr>
-</table>
-</tal:block>
-
-<tal:block tal:condition="context/id" tal:replace="structure context/history" />
-
-</div>
-
-</td>
-
-</tal:doc>
diff --git a/templates/classic/html/user.register.html b/templates/classic/html/user.register.html
+++ /dev/null
@@ -1,81 +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"
- i18n:translate="">Registering with <span i18n:name="tracker"
- tal:replace="db/config/TRACKER_NAME" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">Registering with <span i18n:name="tracker"
- tal:replace="db/config/TRACKER_NAME" /></span>
-<td class="content" metal:fill-slot="content">
-
-<form method="POST" onSubmit="return submit_once()"
- enctype="multipart/form-data"
- tal:attributes="action context/designator">
-
-<table class="form">
- <tr>
- <th i18n:translate="">Name</th>
- <td tal:content="structure context/realname/field">realname</td>
- </tr>
- <tr>
- <th class="required" i18n:translate="">Login Name</th>
- <td tal:content="structure context/username/field">username</td>
- </tr>
- <tr>
- <th class="required" i18n:translate="">Login Password</th>
- <td tal:content="structure context/password/field">password</td>
- </tr>
- <tr>
- <th class="required" i18n:translate="">Confirm Password</th>
- <td tal:content="structure context/password/confirm">password</td>
- </tr>
- <tr tal:condition="python:request.user.hasPermission('Web Roles')">
- <th i18n:translate="">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 i18n:translate="">Phone</th>
- <td tal:content="structure context/phone/field">phone</td>
- </tr>
- <tr>
- <th i18n:translate="">Organisation</th>
- <td tal:content="structure context/organisation/field">organisation</td>
- </tr>
- <tr>
- <th class="required" i18n:translate="">E-mail address</th>
- <td tal:content="structure context/address/field">address</td>
- </tr>
- <tr>
- <th i18n:translate="">Alternate E-mail addresses<br>One address per line</th>
- <td tal:content="structure context/alternate_addresses/multiline">alternate_addresses</td>
- </tr>
-
- <tr>
- <td> </td>
- <td>
- <input type="hidden" name="@template" value="register">
- <input type="hidden" name="@required" value="username,password,address">
- <input type="hidden" name="@action" value="register">
- <input type="submit" name="submit" value="Register" i18n:attributes="value">
- </td>
- </tr>
-</table>
-</form>
-
-<tal:block tal:condition="not:context/id" i18n:translate="">
-<table class="form">
-<tr>
- <td>Note: </td>
- <th class="required">highlighted</th>
- <td> fields are required.</td>
-</tr>
-</table>
-</tal:block>
-
-</td>
-
-</tal:block>
diff --git a/templates/classic/html/user.rego_progress.html b/templates/classic/html/user.rego_progress.html
+++ /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"
- i18n:translate="">Registration in progress - <span i18n:name="tracker"
- tal:replace="config/TRACKER_NAME" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">Registration in progress...</span>
-<td class="content" metal:fill-slot="content">
-
-<p i18n:translate="">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/html/user_utils.js b/templates/classic/html/user_utils.js
+++ /dev/null
@@ -1,114 +0,0 @@
-// User Editing Utilities
-
-/**
- * for new users:
- * Depending on the input field which calls it, takes the value
- * and dispatches it to certain other input fields:
- *
- * address
- * +-> username
- * | `-> realname
- * `-> organisation
- */
-function split_name(that) {
- var raw = that.value
- var val = trim(raw)
- if (val == '') {
- return
- }
- var username=''
- var realname=''
- var address=''
- switch (that.name) {
- case 'address':
- address=val
- break
- case 'username':
- username=val
- break
- case 'realname':
- realname=val
- break
- case 'firstname':
- case 'lastname':
- return
- default:
- alert('Ooops - unknown name field '+that.name+'!')
- return
- }
- var the_form = that.form;
-
- function field_empty(name) {
- return the_form[name].value == ''
- }
-
- // no break statements - on purpose!
- switch (that.name) {
- case 'address':
- var split1 = address.split('@')
- if (field_empty('username')) {
- username = split1[0]
- the_form.username.value = username
- }
- if (field_empty('organisation')) {
- the_form.organisation.value = default_organisation(split1[1])
- }
- case 'username':
- if (field_empty('realname')) {
- realname = Cap(username.split('.').join(' '))
- the_form.realname.value = realname
- }
- case 'realname':
- if (field_empty('username')) {
- username = Cap(realname.replace(' ', '.'))
- the_form.username.value = username
- }
- if (the_form.firstname && the_form.lastname) {
- var split2 = realname.split(' ')
- var firstname='', lastname=''
- firstname = split2[0]
- lastname = split2.slice(1).join(' ')
- if (field_empty('firstname')) {
- the_form.firstname.value = firstname
- }
- if (field_empty('lastname')) {
- the_form.lastname.value = lastname
- }
- }
- }
-}
-
-function SubCap(str) {
- switch (str) {
- case 'de': case 'do': case 'da':
- case 'du': case 'von':
- return str;
- }
- if (str.toLowerCase().slice(0,2) == 'mc') {
- return 'Mc'+str.slice(2,3).toUpperCase()+str.slice(3).toLowerCase()
- }
- return str.slice(0,1).toUpperCase()+str.slice(1).toLowerCase()
-}
-
-function Cap(str) {
- var liz = str.split(' ')
- for (var i=0; i<liz.length; i++) {
- liz[i] = SubCap(liz[i])
- }
- return liz.join(' ')
-}
-
-/**
- * Takes a domain name (behind the @ part of an email address)
- * Customise this to handle the mail domains you're interested in
- */
-function default_organisation(orga) {
- switch (orga.toLowerCase()) {
- case 'gmx':
- case 'yahoo':
- return ''
- default:
- return orga
- }
-}
-
diff --git a/templates/classic/initial_data.py b/templates/classic/initial_data.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# TRACKER 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=admin_email, roles='Admin')
-user.create(username="anonymous", roles='Anonymous')
-
-# add any additional database creation steps here - but only if you
-# haven't initialised the database with the admin "initialise" command
-
-
-# vim: set filetype=python sts=4 sw=4 et si
-#SHA: b1da2e72a7fe9f26086f243eb744135b085101d9
diff --git a/templates/classic/schema.py b/templates/classic/schema.py
+++ /dev/null
@@ -1,169 +0,0 @@
-
-#
-# TRACKER SCHEMA
-#
-
-# Class automatically gets these properties:
-# creation = Date()
-# activity = Date()
-# creator = Link('user')
-# actor = Link('user')
-
-# Priorities
-pri = Class(db, "priority",
- name=String(),
- order=Number())
-pri.setkey("name")
-
-# Statuses
-stat = Class(db, "status",
- name=String(),
- order=Number())
-stat.setkey("name")
-
-# Keywords
-keyword = Class(db, "keyword",
- name=String())
-keyword.setkey("name")
-
-# User-defined saved searches
-query = Class(db, "query",
- klass=String(),
- name=String(),
- url=String(),
- private_for=Link('user'))
-
-# add any additional database schema configuration here
-
-user = Class(db, "user",
- username=String(),
- password=Password(),
- address=String(),
- realname=String(),
- phone=String(),
- organisation=String(),
- alternate_addresses=String(),
- queries=Multilink('query'),
- roles=String(), # comma-separated string of Role names
- timezone=String())
-user.setkey("username")
-
-# FileClass automatically gets this property in addition to the Class ones:
-# content = String() [saved to disk in <tracker home>/db/files/]
-# type = String() [MIME type of the content, default 'text/plain']
-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())
-
-# IssueClass automatically gets these properties in addition to the Class ones:
-# title = String()
-# messages = Multilink("msg")
-# files = Multilink("file")
-# nosy = Multilink("user")
-# superseder = Multilink("issue")
-issue = IssueClass(db, "issue",
- assignedto=Link("user"),
- keyword=Multilink("keyword"),
- priority=Link("priority"),
- status=Link("status"))
-
-#
-# TRACKER SECURITY SETTINGS
-#
-# See the configuration and customisation document for information
-# about security setup.
-
-#
-# REGULAR USERS
-#
-# Give the regular users access to the web and email interface
-db.security.addPermissionToRole('User', 'Web Access')
-db.security.addPermissionToRole('User', 'Email Access')
-
-# Assign the access and edit Permissions for issue, file and message
-# to regular users now
-for cl in 'issue', 'file', 'msg', 'keyword':
- db.security.addPermissionToRole('User', 'View', cl)
- db.security.addPermissionToRole('User', 'Edit', cl)
- db.security.addPermissionToRole('User', 'Create', cl)
-for cl in 'priority', 'status':
- db.security.addPermissionToRole('User', 'View', cl)
-
-# May users view other user information? Comment these lines out
-# if you don't want them to
-db.security.addPermissionToRole('User', 'View', 'user')
-
-# Users should be able to edit their own details -- this permission is
-# limited to only the situation where the Viewed or Edited item is their own.
-def own_record(db, userid, itemid):
- '''Determine whether the userid matches the item being accessed.'''
- return userid == itemid
-p = db.security.addPermission(name='View', klass='user', check=own_record,
- description="User is allowed to view their own user details")
-db.security.addPermissionToRole('User', p)
-p = db.security.addPermission(name='Edit', klass='user', check=own_record,
- description="User is allowed to edit their own user details")
-db.security.addPermissionToRole('User', p)
-
-# Users should be able to edit and view their own queries. They should also
-# be able to view any marked as not private. They should not be able to
-# edit others' queries, even if they're not private
-def view_query(db, userid, itemid):
- private_for = db.query.get(itemid, 'private_for')
- if not private_for: return True
- return userid == private_for
-def edit_query(db, userid, itemid):
- return userid == db.query.get(itemid, 'creator')
-p = db.security.addPermission(name='View', klass='query', check=view_query,
- description="User is allowed to view their own and public queries")
-db.security.addPermissionToRole('User', p)
-p = db.security.addPermission(name='Edit', klass='query', check=edit_query,
- description="User is allowed to edit their queries")
-db.security.addPermissionToRole('User', p)
-p = db.security.addPermission(name='Create', klass='query',
- description="User is allowed to create queries")
-db.security.addPermissionToRole('User', p)
-
-
-#
-# ANONYMOUS USER PERMISSIONS
-#
-# Let anonymous users access the web interface. Note that almost all
-# trackers will need this Permission. The only situation where it's not
-# required is in a tracker that uses an HTTP Basic Authenticated front-end.
-db.security.addPermissionToRole('Anonymous', 'Web Access')
-
-# Let anonymous users access the email interface (note that this implies
-# that they will be registered automatically, hence they will need the
-# "Create" user Permission below)
-# This is disabled by default to stop spam from auto-registering users on
-# public trackers.
-#db.security.addPermissionToRole('Anonymous', 'Email Access')
-
-# Assign the appropriate permissions to the anonymous user's Anonymous
-# Role. Choices here are:
-# - Allow anonymous users to register
-db.security.addPermissionToRole('Anonymous', 'Create', 'user')
-
-# Allow anonymous users access to view issues (and the related, linked
-# information)
-for cl in 'issue', 'file', 'msg', 'keyword', 'priority', 'status':
- db.security.addPermissionToRole('Anonymous', 'View', cl)
-
-# [OPTIONAL]
-# Allow anonymous users access to create or edit "issue" items (and the
-# related file and message items)
-#for cl in 'issue', 'file', 'msg':
-# db.security.addPermissionToRole('Anonymous', 'Create', cl)
-# db.security.addPermissionToRole('Anonymous', 'Edit', cl)
-
-
-# vim: set filetype=python sts=4 sw=4 et si :
diff --git a/templates/minimal/.cvsignore b/templates/minimal/.cvsignore
+++ /dev/null
@@ -1,4 +0,0 @@
-*.pyc
-*.pyo
-htmlbase.py
-*.cover
diff --git a/templates/minimal/TEMPLATE-INFO.txt b/templates/minimal/TEMPLATE-INFO.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-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/detectors/.cvsignore b/templates/minimal/detectors/.cvsignore
+++ /dev/null
@@ -1,3 +0,0 @@
-*.pyc
-*.pyo
-*.cover
diff --git a/templates/minimal/detectors/userauditor.py b/templates/minimal/detectors/userauditor.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# Copyright (c) 2003 Richard Jones (richard@mechanicalcat.net)
-#
-# 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: userauditor.py,v 1.8 2007-09-12 21:11:14 jpend Exp $
-
-import re
-
-# regular expression thanks to: http://www.regular-expressions.info/email.html
-# this is the "99.99% solution for syntax only".
-email_regexp = (r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*", r"(localhost|(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9]))")
-email_rfc = re.compile('^' + email_regexp[0] + '@' + email_regexp[1] + '$', re.IGNORECASE)
-email_local = re.compile('^' + email_regexp[0] + '$', re.IGNORECASE)
-
-def valid_address(address):
- ''' If we see an @-symbol in the address then check against the full
- RFC syntax. Otherwise it is a local-only address so only check
- the local part of the RFC syntax.
- '''
- if '@' in address:
- return email_rfc.match(address)
- else:
- return email_local.match(address)
-
-def get_addresses(user):
- ''' iterate over all known addresses in a newvalues dict
- this takes of the address/alterate_addresses handling
- '''
- if user.has_key('address'):
- yield user['address']
- if user.get('alternate_addresses', None):
- for address in user['alternate_addresses'].split('\n'):
- yield address
-
-def audit_user_fields(db, cl, nodeid, newvalues):
- ''' Make sure user properties are valid.
-
- - email address is syntactically valid
- - email address is unique
- - roles specified exist
- - timezone is valid
- '''
-
- for address in get_addresses(newvalues):
- if not valid_address(address):
- raise ValueError, 'Email address syntax is invalid'
-
- check_main = db.user.stringFind(address=address)
- # make sure none of the alts are owned by anyone other than us (x!=nodeid)
- check_alts = [x for x in db.user.filter(None, {'alternate_addresses' : address}) if x != nodeid]
- if check_main or check_alts:
- raise ValueError, 'Email address %s already in use' % address
-
- for rolename in [r.lower().strip() for r in newvalues.get('roles', '').split(',')]:
- if rolename and not db.security.role.has_key(rolename):
- raise ValueError, 'Role "%s" does not exist'%rolename
-
- tz = newvalues.get('timezone', None)
- if tz:
- # if they set a new timezone validate the timezone by attempting to
- # use it before we store it to the db.
- import roundup.date
- import datetime
- try:
- TZ = roundup.date.get_timezone(tz)
- dt = datetime.datetime.now()
- local = TZ.localize(dt).utctimetuple()
- except IOError:
- raise ValueError, 'Timezone "%s" does not exist' % tz
- except ValueError:
- raise ValueError, 'Timezone "%s" exceeds valid range [-23...23]' % tz
-
-def init(db):
- # fire before changes are made
- db.user.audit('set', audit_user_fields)
- db.user.audit('create', audit_user_fields)
-
-# vim: sts=4 sw=4 et si
diff --git a/templates/minimal/extensions/README.txt b/templates/minimal/extensions/README.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This directory is for tracker extensions:
-
-- CGI Actions
-- Templating functions
-
-See the customisation doc for more information.
diff --git a/templates/minimal/html/_generic.404.html b/templates/minimal/html/_generic.404.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html>
-<head>
-<title>Item Not Found</title>
-</head>
-
-<body>
-There is no <span tal:content="context/_classname" /> with id <span tal:content="context/id"/>
-</body>
-</html>
diff --git a/templates/minimal/html/_generic.calendar.html b/templates/minimal/html/_generic.calendar.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html>
- <head>
- <link rel="stylesheet" type="text/css" href="@@file/style.css" />
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8;" />
- <title tal:content="string:Roundup Calendar"></title>
- <script language="Javascript"
- type="text/javascript"
- tal:content="structure string:
- // this is the name of the field in the original form that we're working on
- form = window.opener.document.${request/form/form/value};
- field = '${request/form/property/value}';" >
- </script>
- </head>
- <body class="body"
- tal:content="structure python:utils.html_calendar (request)">
- </body>
-</html>
diff --git a/templates/minimal/html/_generic.collision.html b/templates/minimal/html/_generic.collision.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title" i18n:translate=""
- ><span tal:replace="python:context._classname.capitalize()"
- i18n:name="class" /> Edit Collision - <span i18n:name="tracker"
- tal:replace="config/TRACKER_NAME" /></title>
-<tal:block metal:fill-slot="body_title" i18n:translate=""
- ><span tal:replace="python:context._classname.capitalize()"
- i18n:name="class" /> Edit Collision</tal:block>
-
-<td class="content" metal:fill-slot="content" i18n:translate="
- There has been a collision. Another user updated this node
- while you were editing. Please <a href='${context}'>reload</a>
- the node and review your edits.
-"><span tal:replace="context/designator" i18n:name="context" />
-</td>
-</tal:block>
diff --git a/templates/minimal/html/_generic.help.html b/templates/minimal/html/_generic.help.html
+++ /dev/null
@@ -1,98 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html tal:define="property request/form/property/value" >
- <head>
- <link rel="stylesheet" type="text/css" href="@@file/style.css" />
- <meta http-equiv="Content-Type"
- tal:attributes="content string:text/html;; charset=${request/client/charset}" />
- <tal:block tal:condition="python:request.form.has_key('property')">
- <title i18n:translate=""><tal:x i18n:name="property"
- tal:content="property" i18n:translate="" /> help - <span i18n:name="tracker"
- tal:replace="config/TRACKER_NAME" /></title>
- <script language="Javascript" type="text/javascript"
- tal:content="structure string:
- // this is the name of the field in the original form that we're working on
- form = window.opener.document.${request/form/form/value};
- field = '${request/form/property/value}';">
- </script>
- <script src="@@file/help_controls.js" type="text/javascript"><!--
- //--></script>
- </tal:block>
- </head>
- <body class="body" onload="resetList();">
- <form name="frm_help" tal:attributes="action request/base"
- tal:define="batch request/batch;
- props python:request.form['properties'].value.split(',')">
-
- <div id="classhelp-controls">
- <!--input type="button" name="btn_clear"
- value="Clear" onClick="clearList()"/ -->
- <input type="text" name="text_preview" size="24" class="preview"
- onchange="reviseList(this.value);"/>
- <input type="button" name="btn_reset"
- value=" Cancel " onclick="resetList(); window.close();"
- i18n:attributes="value" />
- <input type="button" name="btn_apply" class="apply"
- value=" Apply " onclick="updateList(); window.close();"
- i18n:attributes="value" />
- </div>
- <table width="100%">
- <tr class="navigation">
- <th>
- <a tal:define="prev batch/previous" tal:condition="prev"
- tal:attributes="href python:request.indexargs_url(request.classname,
- {'@template':'help', 'property': request.form['property'].value,
- 'properties': request.form['properties'].value,
- 'form': request.form['form'].value,
- 'type': request.form['type'].value,
- '@startwith':prev.first, '@pagesize':prev.size})"
- i18n:translate="" ><< previous</a>
-
- </th>
- <th i18n:translate=""><span tal:replace="batch/start" i18n:name="start"
- />..<span tal:replace="python: batch.start + batch.length -1" i18n:name="end"
- /> out of <span tal:replace="batch/sequence_length" i18n:name="total"
- />
- </th>
- <th>
- <a tal:define="next batch/next" tal:condition="next"
- tal:attributes="href python:request.indexargs_url(request.classname,
- {'@template':'help', 'property': request.form['property'].value,
- 'properties': request.form['properties'].value,
- 'form': request.form['form'].value,
- 'type': request.form['type'].value,
- '@startwith':next.first, '@pagesize':next.size})"
- i18n:translate="" >next >></a>
-
- </th>
- </tr>
- </table>
-
- <table class="classhelp">
- <tr>
- <th> <b>x</b></th>
- <th tal:repeat="prop props" tal:content="prop" i18n:translate=""></th>
- </tr>
- <tr tal:repeat="item batch">
- <tal:block tal:define="attr python:item[props[0]]" >
- <td>
- <input name="check"
- onclick="updatePreview();"
- tal:attributes="type python:request.form['type'].value;
- value attr; id string:id_$attr" />
- </td>
- <td tal:repeat="prop props">
- <label class="classhelp-label"
- tal:attributes="for string:id_$attr"
- tal:content="python:item[prop]"></label>
- </td>
- </tal:block>
- </tr>
- <tr>
- <th> <b>x</b></th>
- <th tal:repeat="prop props" tal:content="prop" i18n:translate=""></th>
- </tr>
- </table>
-
- </form>
- </body>
-</html>
diff --git a/templates/minimal/html/_generic.index.html b/templates/minimal/html/_generic.index.html
+++ /dev/null
@@ -1,70 +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" i18n:translate=""
- ><span tal:replace="python:context._classname.capitalize()"
- i18n:name="class" /> editing - <span i18n:name="tracker"
- tal:replace="config/TRACKER_NAME" /></title>
-<tal:block metal:fill-slot="body_title" i18n:translate=""
- ><span tal:replace="python:context._classname.capitalize()"
- i18n:name="class" /> editing</tal:block>
-
-<td class="content" metal:fill-slot="content">
-
-<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok()
- or request.user.hasRole('Anonymous'))"
- tal:omit-tag="python:1" i18n:translate=""
->You are not allowed to view this page.</span>
-
-<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())
- and request.user.hasRole('Anonymous')"
- tal:omit-tag="python:1" i18n:translate=""
->Please login with your username and password.</span>
-
-<tal:block tal:condition="context/is_edit_ok">
-<tal:block i18n:translate="">
-<p class="form-help">
- You may edit the contents of the
- <span tal:replace="request/classname" i18n:name="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>
-</tal:block>
-<form onSubmit="return submit_once()" method="POST"
- tal:attributes="action context/designator">
-<textarea rows="15" style="width:90%" name="rows" tal:content="context/csv"></textarea>
-<br>
-<input type="hidden" name="@action" value="editCSV">
-<input type="submit" value="Edit Items" i18n:attributes="value">
-</form>
-</tal:block>
-
-<table tal:condition="context/is_only_view_ok" width="100%" class="list">
- <tr>
- <th tal:repeat="property context/propnames" tal:content="property"> </th>
- </tr>
- <tal:block repeat="item context/list">
- <tr tal:condition="item/is_view_ok"
- tal:attributes="class python:['normal', 'alt'][repeat['item'].index%6/3]">
- <td tal:repeat="property context/propnames"
- tal:content="python: item[property] or default"
- > </td>
- </tr>
- </tal:block>
-</table>
-
-</td>
-
-</tal:block>
diff --git a/templates/minimal/html/_generic.item.html b/templates/minimal/html/_generic.item.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title" i18n:translate=""
- ><span tal:replace="python:context._classname.capitalize()"
- i18n:name="class" /> editing - <span i18n:name="tracker"
- tal:replace="config/TRACKER_NAME" /></title>
-<tal:block metal:fill-slot="body_title" i18n:translate=""
- ><span tal:replace="python:context._classname.capitalize()"
- i18n:name="class" /> editing</tal:block>
-
-<td class="content" metal:fill-slot="content">
-
-<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok()
- or request.user.hasRole('Anonymous'))"
- tal:omit-tag="python:1" i18n:translate=""
->You are not allowed to view this page.</span>
-
-<span tal:condition="python:not (context.is_view_ok() or context.is_edit_ok())
- and request.user.hasRole('Anonymous')"
- tal:omit-tag="python:1" i18n:translate=""
->Please login with your username and password.</span>
-
-<form method="POST" onSubmit="return submit_once()"
- enctype="multipart/form-data" tal:condition="context/is_edit_ok"
- tal:attributes="action context/designator">
-
-<input type="hidden" name="@template" value="item">
-
-<table class="form">
-
-<tr tal:repeat="prop python:db[context._classname].properties()">
- <tal:block tal:condition="python:prop._name not in ('id',
- 'creator', 'creation', 'actor', 'activity')">
- <th tal:content="prop/_name"></th>
- <td tal:content="structure python:context[prop._name].field()"></td>
- </tal:block>
-</tr>
-<tr>
- <td> </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/help_controls.js b/templates/minimal/html/help_controls.js
+++ /dev/null
@@ -1,111 +0,0 @@
-// initial values for either Nosy, Superseder, Keyword and Waiting On,
-// depending on which has called
-original_field = form[field].value;
-
-// Some browsers (ok, IE) don't define the "undefined" variable.
-undefined = document.geez_IE_is_really_friggin_annoying;
-
-function trim(value) {
- var temp = value;
- var obj = /^(\s*)([\W\w]*)(\b\s*$)/;
- if (obj.test(temp)) { temp = temp.replace(obj, '$2'); }
- var obj = / /g;
- while (temp.match(obj)) { temp = temp.replace(obj, " "); }
- return temp;
-}
-
-function determineList() {
- // generate a comma-separated list of the checked items
- var list = new String('');
- for (box=0; box < document.frm_help.check.length; box++) {
- if (document.frm_help.check[box].checked) {
- if (list.length == 0) {
- separator = '';
- }
- else {
- separator = ',';
- }
- // we used to use an Array and push / join, but IE5.0 sux
- list = list + separator + document.frm_help.check[box].value;
- }
- }
- return list;
-}
-
-function updateList() {
- // write back to opener window
- if (document.frm_help.check==undefined) { return; }
- form[field].value = determineList();
-}
-
-function updatePreview() {
- // update the preview box
- if (document.frm_help.check==undefined) { return; }
- writePreview(determineList());
-}
-
-function clearList() {
- // uncheck all checkboxes
- if (document.frm_help.check==undefined) { return; }
- for (box=0; box < document.frm_help.check.length; box++) {
- document.frm_help.check[box].checked = false;
- }
-}
-
-function reviseList(vals) {
- // update the checkboxes based on the preview field
- if (document.frm_help.check==undefined) { return; }
- var to_check;
- var list = vals.split(",");
- if (document.frm_help.check.length==undefined) {
- check = document.frm_help.check;
- to_check = false;
- for (val in list) {
- if (check.value==trim(list[val])) {
- to_check = true;
- break;
- }
- }
- check.checked = to_check;
- } else {
- for (box=0; box < document.frm_help.check.length; box++) {
- check = document.frm_help.check[box];
- to_check = false;
- for (val in list) {
- if (check.value==trim(list[val])) {
- to_check = true;
- break;
- }
- }
- check.checked = to_check;
- }
- }
-}
-
-function resetList() {
- // reset preview and check boxes to initial values
- if (document.frm_help.check==undefined) { return; }
- writePreview(original_field);
- reviseList(original_field);
-}
-
-function writePreview(val) {
- // writes a value to the text_preview
- document.frm_help.text_preview.value = val;
-}
-
-function focusField(name) {
- for(i=0; i < document.forms.length; ++i) {
- var obj = document.forms[i].elements[name];
- if (obj && obj.focus) {obj.focus();}
- }
-}
-
-function selectField(name) {
- for(i=0; i < document.forms.length; ++i) {
- var obj = document.forms[i].elements[name];
- if (obj && obj.focus){obj.focus();}
- if (obj && obj.select){obj.select();}
- }
-}
-
diff --git a/templates/minimal/html/home.classlist.html b/templates/minimal/html/home.classlist.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title" i18n:translate="">List of classes - <span
- i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">List of classes</span>
-<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
+++ /dev/null
@@ -1,25 +0,0 @@
-<tal:block metal:use-macro="templates/page/macros/icing">
-<title metal:fill-slot="head_title" i18n:translate="">Tracker home - <span
- i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">Tracker home</span>
-<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" i18n:translate="">
-Please select from one of the menu options on the left.
-</p>
-<p tal:condition="anon" class="help" i18n:translate="">
-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
+++ /dev/null
@@ -1,334 +0,0 @@
-<!-- vim:sw=2 sts=2
---><tal:block metal:define-macro="icing"
-><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<title metal:define-slot="head_title">title goes here</title>
-<link rel="stylesheet" type="text/css" href="@@file/style.css">
-<meta http-equiv="Content-Type"
- tal:attributes="content string:text/html;; charset=${request/client/charset}" />
-<script tal:replace="structure request/base_javascript">
-</script>
-<metal:x define-slot="more-javascript" />
-
-</head>
-<body class="body">
-
-<table class="body"
- tal:define="
-kw_edit python:request.user.hasPermission('Edit', 'keyword');
-kw_create python:request.user.hasPermission('Create', 'keyword');
-kw_edit_link python:kw_edit and db.keyword.list();
-columns string:id,activity,title,creator,status;
-columns_showall string:id,activity,title,creator,assignedto,status;
-status_notresolved string:-1,1,2,3,4,5,6,7;
-"
->
-
-<tr>
- <td class="page-header-left"> </td>
- <td class="page-header-top">
- <div id="body-title">
- <h2><span metal:define-slot="body_title">body title</span></h2>
- </div>
- <div id="searchbox">
- <form method="GET" action="issue">
- <input type="hidden" name="@columns"
- tal:attributes="value columns_showall"
- value="id,activity,title,creator,assignedto,status"/>
- <input type="hidden" name="@sort" value="activity"/>
- <input type="hidden" name="@group" value="priority"/>
- <input id="search-text" name="@search_text" size="10"
- tal:attributes="value request/search_text"/>
- <input type="submit" id="submit" name="submit" value="Search" i18n:attributes="value" />
- </form>
- </div>
- </td>
-</tr>
-
-<tr>
- <td rowspan="2" valign="top" class="sidebar">
- <p class="classblock"
- tal:condition="python:request.user.hasPermission('View', 'query')">
- <span i18n:translate=""
- ><b>Your Queries</b> (<a href="query?@template=edit">edit</a>)</span><br>
- <tal:block tal:repeat="qs request/user/queries">
- <a href="#" tal:attributes="href string:${qs/klass}?${qs/url}&@dispname=${qs/name}"
- tal:content="qs/name">link</a><br>
- </tal:block>
- </p>
-
- <form method="POST" tal:attributes="action request/base">
- <p class="classblock"
- tal:condition="python:request.user.hasPermission('View', 'issue')">
- <b i18n:translate="">Issues</b><br>
- <span tal:condition="python:request.user.hasPermission('Create', 'issue')">
- <a href="issue?@template=item" i18n:translate="">Create New</a><br>
- </span>
- <a href="#"
- tal:attributes="href python:request.indexargs_url('issue', {
- '@sort': '-activity',
- '@group': 'priority',
- '@filter': 'status,assignedto',
- '@columns': columns,
- '@search_text': '',
- 'status': status_notresolved,
- 'assignedto': '-1',
- '@dispname': i18n.gettext('Show Unassigned'),
- })"
- i18n:translate="">Show Unassigned</a><br>
- <a href="#"
- tal:attributes="href python:request.indexargs_url('issue', {
- '@sort': '-activity',
- '@group': 'priority',
- '@filter': 'status',
- '@columns': columns_showall,
- '@search_text': '',
- 'status': status_notresolved,
- '@dispname': i18n.gettext('Show All'),
- })"
- i18n:translate="">Show All</a><br>
- <a href="issue?@template=search" i18n:translate="">Search</a><br>
- <input type="submit" class="form-small" value="Show issue:"
- i18n:attributes="value"><input class="form-small" 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:kw_edit or kw_create">
- <b i18n:translate="">Keywords</b><br>
- <span tal:condition="python:request.user.hasPermission('Create', 'keyword')">
- <a href="keyword?@template=item" i18n:translate="">Create New</a><br>
- </span>
- <span tal:condition="kw_edit_link">
- <a href="keyword?@template=item" i18n:translate="">Edit Existing</a><br>
- </span>
- </p>
-
- <p class="classblock"
- tal:condition="python:request.user.hasPermission('View', 'user')">
- <b i18n:translate="">Administration</b><br>
- <span tal:condition="python:request.user.hasPermission('Edit', None)">
- <a href="home?@template=classlist" i18n:translate="">Class List</a><br>
- </span>
- <span tal:condition="python:request.user.hasPermission('View', 'user')
- or request.user.hasPermission('Edit', 'user')">
- <a href="user" i18n:translate="">User List</a><br>
- </span>
- <a tal:condition="python:request.user.hasPermission('Create', 'user')"
- href="user?@template=item" i18n:translate="">Add User</a>
- </p>
-
- <form method="POST" tal:condition="python:request.user.username=='anonymous'"
- tal:attributes="action request/base">
- <p class="userblock">
- <b i18n:translate="">Login</b><br>
- <input size="10" name="__login_name"><br>
- <input size="10" type="password" name="__login_password"><br>
- <input type="hidden" name="@action" value="Login">
- <input type="checkbox" name="remember" id="remember">
- <label for="remember" i18n:translate="">Remember me?</label><br>
- <input type="submit" value="Login" i18n:attributes="value"><br>
- <input type="hidden" name="__came_from" tal:attributes="value string:${request/base}${request/env/PATH_INFO}">
- <span tal:replace="structure request/indexargs_form" />
- <a href="user?@template=register"
- tal:condition="python:request.user.hasPermission('Create', 'user')"
- i18n:translate="">Register</a><br>
- <a href="user?@template=forgotten" i18n:translate="">Lost your login?</a><br>
- </p>
- </form>
-
- <p class="userblock" tal:condition="python:request.user.username != 'anonymous'">
- <b i18n:translate="">Hello, <span i18n:name="user"
- tal:replace="python:request.user.username.plain(escape=1)">username</span></b><br>
- <a href="#" tal:attributes="href string:user${request/user/id}"
- i18n:translate="">Your Details</a><br>
- <a href="#" tal:attributes="href python:request.indexargs_url('',
- {'@action':'logout'})" i18n:translate="">Logout</a>
- </p>
- <p class="userblock">
- <b i18n:translate="">Help</b><br>
- <a href="http://roundup.sourceforge.net/doc-1.0/"
- i18n:translate="">Roundup docs</a>
- </p>
- </td>
- <td>
- <p tal:condition="options/error_message | nothing" class="error-message"
- tal:repeat="m options/error_message" tal:content="structure m" />
- <p tal:condition="options/ok_message | nothing" class="ok-message">
- <span tal:repeat="m options/ok_message"
- tal:content="structure string:$m <br/ > " />
- <a class="form-small" tal:attributes="href request/current_url"
- i18n:translate="">clear this message</a>
- </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>
-</tal:block>
-
-<!--
-The following macros are intended to be used in search pages.
-
-The invoking context must define a "name" variable which names the
-property being searched.
-
-See issue.search.html in the classic template for examples.
--->
-
-<!-- creates a th and a label: -->
-<th metal:define-macro="th_label"
- tal:define="required required | python:[]"
- tal:attributes="class python:(name in required) and 'required' or nothing">
- <label tal:attributes="for name" tal:content="label" i18n:translate="">text</label>
- <metal:x define-slot="behind_the_label" />
-</th>
-
-<td metal:define-macro="search_input">
- <input tal:attributes="value python:request.form.getvalue(name) or nothing;
- name name;
- id name">
-</td>
-
-<td metal:define-macro="search_date">
- <input tal:attributes="value python:request.form.getvalue(name) or nothing;
- name name;
- id name">
- <a class="classhelp"
- tal:attributes="href python:'''javascript:help_window('issue?@template=calendar&property=%s&form=itemSynopsis', 300, 200)'''%name">(cal)</a>
-</td>
-
-<td metal:define-macro="search_popup">
- <!--
- context needs to specify the popup "columns" as a comma-separated
- string (eg. "id,title" or "id,name,description") as well as name
- -->
- <input tal:attributes="value python:request.form.getvalue(name) or nothing;
- name name;
- id name">
- <span tal:replace="structure python:db.issue.classhelp(columns,
- property=name)" />
-</td>
-
-<td metal:define-macro="search_select">
- <select tal:attributes="name name; id name"
- tal:define="value python:request.form.getvalue(name)">
- <option value="" i18n:translate="">don't care</option>
- <metal:slot define-slot="extra_options" />
- <option value="" i18n:translate="" disabled="disabled">------------</option>
- <option tal:repeat="s python:db[db_klass].list()"
- tal:attributes="value s/id; selected python:value == s.id"
- tal:content="python:s[db_content]"></option>
- </select>
-</td>
-
-<!-- like search_select, but translates the further values.
-Could extend it (METAL 1.1 attribute "extend-macro")
--->
-<td metal:define-macro="search_select_translated">
- <select tal:attributes="name name; id name"
- tal:define="value python:request.form.getvalue(name)">
- <option value="" i18n:translate="">don't care</option>
- <metal:slot define-slot="extra_options" />
- <option value="" i18n:translate="" disabled="disabled">------------</option>
- <option tal:repeat="s python:db[db_klass].list()"
- tal:attributes="value s/id; selected python:value == s.id"
- tal:content="python:s[db_content]"
- i18n:translate=""></option>
- </select>
-</td>
-
-<!-- currently, there is no convenient API to get a list of all roles -->
-<td metal:define-macro="search_select_roles"
- tal:define="onchange onchange | nothing">
- <select name=roles id=roles tal:attributes="onchange onchange">
- <option value="" i18n:translate="">don't care</option>
- <option value="" i18n:translate="" disabled="disabled">------------</option>
- <option value="User">User</option>
- <option value="Admin">Admin</option>
- <option value="Anonymous">Anonymous</option>
- </select>
-</td>
-
-<td metal:define-macro="search_multiselect">
- <input tal:attributes="value python:request.form.getvalue(name) or nothing;
- name name;
- id name">
- <span tal:replace="structure python:db[db_klass].classhelp(db_content,
- property=name, width='600')" />
-</td>
-
-<td metal:define-macro="search_checkboxes">
- <ul class="search-checkboxes"
- tal:define="value python:request.form.getvalue(name);
- values python:value and value.split(',') or []">
- <li tal:repeat="s python:db[db_klass].list()">
- <input type="checkbox" tal:attributes="name name; id string:$name-${s/id};
- value s/id; checked python:s.id in values" />
- <label tal:attributes="for string:$name-${s/id}"
- tal:content="python:s[db_content]" />
- </li>
- <li metal:define-slot="no_value_item">
- <input type="checkbox" value="-1" tal:attributes="name name;
- id string:$name--1; checked python:value == '-1'" />
- <label tal:attributes="for string:$name--1" i18n:translate="">no value</label>
- </li>
- </ul>
-</td>
-
-<td metal:define-macro="column_input">
- <input type="checkbox" name="@columns"
- tal:attributes="value name;
- checked python:name in cols">
-</td>
-
-<td metal:define-macro="sort_input">
- <input type="radio" name="@sort"
- tal:attributes="value name;
- checked python:name == sort_on">
-</td>
-
-<td metal:define-macro="group_input">
- <input type="radio" name="@group"
- tal:attributes="value name;
- checked python:name == group_on">
-</td>
-
-<!--
-The following macros are intended for user editing.
-
-The invoking context must define a "name" variable which names the
-property being searched; the "edit_ok" variable tells whether the
-current user is allowed to edit.
-
-See user.item.html in the classic template for examples.
--->
-<script metal:define-macro="user_utils" type="text/javascript" src="@@file/user_utils.js"></script>
-
-<!-- src: value will be re-used for other input fields -->
-<input metal:define-macro="user_src_input"
- type="text" tal:attributes="onblur python:edit_ok and 'split_name(this)';
- id name; name name; value value; readonly not:edit_ok"
- value="heinz.kunz">
-<!-- normal: no re-using -->
-<input metal:define-macro="user_normal_input" type="text"
- tal:attributes="id name; name name; value value; readonly not:edit_ok"
- value="heinz">
-<!-- password: type; no initial value -->
- <input metal:define-macro="user_pw_input" type="password"
- tal:attributes="id name; name name; readonly not:edit_ok" value="">
- <input metal:define-macro="user_confirm_input" type="password"
- tal:attributes="id name; name string:@confirm@$name; readonly not:edit_ok" value="">
-
diff --git a/templates/minimal/html/style.css b/templates/minimal/html/style.css
+++ /dev/null
@@ -1,423 +0,0 @@
-/* main page styles */
-body.body {
- font-family: sans-serif, Arial, Helvetica;
- background-color: white;
- color: #333;
- margin: 0;
-}
-a[href]:hover {
- color:blue;
- text-decoration: underline;
-}
-a[href], a[href]:link {
- color:blue;
- text-decoration: none;
-}
-
-table.body {
- border: 0;
- padding: 0;
- border-spacing: 0;
- border-collapse: separate;
-}
-
-td.page-header-left {
- padding: 5px;
- border-bottom: 1px solid #444;
-}
-td.sidebar {
- padding: 1px 0 0 1px;
- white-space: nowrap;
-}
-
-/* don't display the sidebar when printing */
-@media print {
- td.page-header-left {
- display: none;
- }
- td.sidebar {
- display: none;
- }
- .index-controls {
- display: none;
- }
- #searchbox {
- display: none;
- }
-}
-
-td.page-header-top {
- padding: 5px;
- border-bottom: 1px solid #444;
-}
-#searchbox {
- float: right;
-}
-
-div#body-title {
- float: left;
-}
-
-
-div#searchbox {
- float: right;
- padding-top: 1em;
-}
-
-div#searchbox input#search-text {
- width: 10em;
-}
-
-form {
- margin: 0;
-}
-
-textarea {
- font-family: monospace;
-}
-
-td.sidebar p.classblock {
- padding: 2px 5px 2px 5px;
- margin: 1px;
- border: 1px solid #444;
- background-color: #eee;
-}
-
-td.sidebar p.userblock {
- padding: 2px 5px 2px 5px;
- margin: 1px 1px 1px 1px;
- border: 1px solid #444;
- background-color: #eef;
-}
-
-.form-small {
- padding: 0;
- font-size: 75%;
-}
-
-
-td.content {
- padding: 1px 5px 1px 5px;
- vertical-align: top;
- width: 100%;
-}
-
-td.date, th.date {
- white-space: nowrap;
-}
-
-p.ok-message {
- background-color: #22bb22;
- padding: 5px;
- color: white;
- font-weight: bold;
-}
-p.error-message {
- background-color: #bb2222;
- padding: 5px;
- color: white;
- font-weight: bold;
-}
-p.error-message a[href] {
- color: white;
- text-decoration: underline;
-}
-
-
-/* style for search forms */
-ul.search-checkboxes {
- display: inline;
- padding: none;
- list-style: none;
-}
-ul.search-checkboxes > li {
- display: inline;
- padding-right: .5em;
-}
-
-
-/* style for forms */
-table.form {
- padding: 2px;
- border-spacing: 0;
- border-collapse: separate;
-}
-
-table.form th {
- color: #338;
- text-align: right;
- vertical-align: top;
- font-weight: normal;
- white-space: nowrap;
-}
-
-table.form th.header {
- font-weight: bold;
- background-color: #eef;
- text-align: left;
-}
-
-table.form th.required {
- font-weight: bold;
-}
-
-table.form td {
- color: #333;
- empty-cells: show;
- vertical-align: top;
-}
-
-table.form td.optional {
- font-weight: bold;
- font-style: italic;
-}
-
-table.form td.html {
- color: #777;
-}
-
-/* style for lists */
-table.list {
- border-spacing: 0;
- border-collapse: separate;
- width: 100%;
-}
-
-table.list th {
- padding: 0 4px 0 4px;
- color: #404070;
- background-color: #eef;
- 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 4px 0 4px;
- border: 1px solid white;
- color: #404070;
- background-color: #efefef;
- vertical-align: top;
- empty-cells: show;
-}
-
-table.list tr.navigation th {
- width: 33%;
- border-style: hidden;
- text-align: center;
-}
-table.list tr.navigation td {
- border: none
-}
-table.list tr.navigation th:first-child {
- text-align: left;
-}
-table.list tr.navigation th:last-child {
- text-align: right;
-}
-
-
-/* style for message displays */
-table.messages {
- border-spacing: 0;
- 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: 2px 5px 2px 5px;
-}
-
-table.messages td:first-child {
- border-left: 1px solid #afafaf;
- border-right: 1px solid #afafaf;
-}
-
-/* style for file displays */
-table.files {
- border-spacing: 0;
- 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: 0;
- 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: 0;
- 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 { /* the table-layout: fixed; */
- table-layout: fixed; /* compromises quality for speed */
- overflow: hidden;
- font-size: .9em;
- padding-bottom: 3em;
-}
-
-table.classhelp th {
- font-weight: normal;
- text-align: left;
- color: #444;
- background-color: #efefef;
- border-bottom: 1px solid #afafaf;
- border-top: 1px solid #afafaf;
- text-transform: uppercase;
- vertical-align: middle;
- line-height:1.5em;
-}
-
-table.classhelp td {
- vertical-align: middle;
- padding-right: .2em;
- border-bottom: 1px solid #efefef;
- text-align: left;
- empty-cells: show;
- white-space: nowrap;
- vertical-align: middle;
-}
-
-table.classhelp tr:hover {
- background-color: #eee;
-}
-
-label.classhelp-label {
- cursor: pointer;
-}
-
-#classhelp-controls {
- position: fixed;
- display: block;
- top: auto;
- right: 0;
- bottom: 0;
- left: 0;
- padding: .5em;
- border-top: 2px solid #444;
- background-color: #eee;
-}
-
-#classhelp-controls input.apply {
- width: 7em;
- font-weight: bold;
- margin-right: 2em;
- margin-left: 2em;
-}
-
-#classhelp-controls input.preview {
- margin-right: 3em;
- margin-left: 1em;
-}
-
-/* style for "other" displays */
-table.otherinfo {
- border-spacing: 0;
- 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
+++ /dev/null
@@ -1,35 +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" i18n:translate="">User listing - <span
- i18n:name="tracker" tal:replace="config/TRACKER_NAME" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">User listing</span>
-<td class="content" metal:fill-slot="content">
-
-<span tal:condition="python:not (context.is_view_ok()
- or request.user.hasRole('Anonymous'))"
- i18n:translate="">You are not allowed to view this page.</span>
-
-<span tal:condition="python:not context.is_view_ok()
- and request.user.hasRole('Anonymous')"
- i18n:translate="">Please login with your username and password.</span>
-
-<table width="100%" tal:condition="context/is_view_ok" class="list">
-<tr>
- <th i18n:translate="">Username</th>
- <th i18n:translate="">Email address</th>
-</tr>
-<tal:block repeat="user context/list">
- <tr tal:condition="user/is_view_ok"
- 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>
-</tal:block>
-</table>
-</td>
-
-</tal:block>
diff --git a/templates/minimal/html/user.item.html b/templates/minimal/html/user.item.html
+++ /dev/null
@@ -1,169 +0,0 @@
-<!-- dollarId: user.item,v 1.7 2002/08/16 04:29:04 richard Exp dollar-->
-<tal:doc metal:use-macro="templates/page/macros/icing"
-define="edit_ok context/is_edit_ok"
->
-<title metal:fill-slot="head_title">
-<tal:if condition="context/id" i18n:translate=""
- >User <tal:x content="context/id" i18n:name="id"
- />: <tal:x content="context/username" i18n:name="title"
- /> - <tal:x content="config/TRACKER_NAME" i18n:name="tracker"
-/></tal:if>
-<tal:if condition="not:context/id" i18n:translate=""
- >New User - <span tal:replace="config/TRACKER_NAME" i18n:name="tracker"
-/></tal:if>
-</title>
-<metal:slot fill-slot="more-javascript">
-<script metal:use-macro="templates/page/macros/user_utils"></script>
-<script type="text/javascript" src="@@file/help_controls.js"></script>
-</metal:slot>
-<tal:block metal:fill-slot="body_title"
- define="edit_ok context/is_edit_ok">
- <span tal:condition="python: not (context.id or edit_ok)"
- tal:omit-tag="python:1" i18n:translate="">New User</span>
- <span tal:condition="python: not context.id and edit_ok"
- tal:omit-tag="python:1" i18n:translate="">New User Editing</span>
- <span tal:condition="python: context.id and not edit_ok"
- tal:omit-tag="python:1" i18n:translate="">User<tal:x
- replace="context/id" i18n:name="id" /></span>
- <span tal:condition="python: context.id and edit_ok"
- tal:omit-tag="python:1" i18n:translate="">User<tal:x
- replace="context/id" i18n:name="id" /> Editing</span>
-</tal:block>
-
-<td class="content" metal:fill-slot="content">
-
-<p tal:condition="python:not (context.is_view_ok()
- or request.user.hasRole('Anonymous'))" i18n:translate="">
- You are not allowed to view this page.</p>
-
-<p tal:condition="python:not context.is_view_ok()
- and request.user.hasRole('Anonymous')" i18n:translate="">
- Please login with your username and password.</p>
-
-<div tal:condition="context/is_view_ok">
-
-<form method="POST"
- name="itemSynopsis"
- tal:define="required python:'username address'.split()"
- enctype="multipart/form-data"
- tal:attributes="action context/designator;
- onSubmit python:'return checkRequiredFields(\'%s\')'%'\', \''.join(required);
- ">
-<table class="form" tal:define="
- th_label templates/page/macros/th_label;
- src_input templates/page/macros/user_src_input;
- normal_input templates/page/macros/user_normal_input;
- pw_input templates/page/macros/user_pw_input;
- confirm_input templates/page/macros/user_confirm_input;
- edit_ok context/is_edit_ok;
- ">
- <tr tal:define="name string:realname; label string:Name; value context/realname; edit_ok edit_ok">
- <th metal:use-macro="th_label">Name</th>
- <td><input name="realname" metal:use-macro="src_input"></td>
- </tr>
- <tr tal:define="name string:username; label string:Login Name; value context/username">
- <th metal:use-macro="th_label">Login Name</th>
- <td><input metal:use-macro="src_input"></td>
- </tr>
- <tal:if condition="edit_ok">
- <tr tal:define="name string:password; label string:Login Password">
- <th metal:use-macro="th_label">Login Password</th>
- <td><input metal:use-macro="pw_input" type="password"></td>
- </tr>
- <tr tal:define="name string:password; label string:Confirm Password">
- <th metal:use-macro="th_label">Confirm Password</th>
- <td><input metal:use-macro="confirm_input" type="password"></td>
- </tr>
- </tal:if>
- <tal:if condition="python:request.user.hasPermission('Web Roles')">
- <tr tal:define="name string:roles; label string:Roles;">
- <th><label for="roles" i18n:translate="">Roles</label></th>
- <td tal:define="gips context/id">
- <tal:subif condition=gips define="value context/roles">
- <input metal:use-macro="normal_input">
- </tal:subif>
- <tal:subif condition="not:gips" define="value db/config/NEW_WEB_USER_ROLES">
- <input metal:use-macro="normal_input">
- </tal:subif>
- <tal:block i18n:translate="">(to give the user more than one role,
- enter a comma,separated,list)</tal:block>
- </td>
- </tr>
- </tal:if>
-
- <tr tal:define="name string:phone; label string:Phone; value context/phone">
- <th metal:use-macro="th_label">Phone</th>
- <td><input name="phone" metal:use-macro="normal_input"></td>
- </tr>
-
- <tr tal:define="name string:organisation; label string:Organisation; value context/organisation">
- <th metal:use-macro="th_label">Organisation</th>
- <td><input name="organisation" metal:use-macro="normal_input"></td>
- </tr>
-
- <tr tal:condition="python:edit_ok or context.timezone"
- tal:define="name string:timezone; label string:Timezone; value context/timezone">
- <th metal:use-macro="th_label">Timezone</th>
- <td><input name="timezone" metal:use-macro="normal_input">
- <tal:block tal:condition="edit_ok" i18n:translate="">(this is a numeric hour offset, the default is
- <span tal:replace="db/config/DEFAULT_TIMEZONE" i18n:name="zone"
- />)</tal:block>
- </td>
- </tr>
-
- <tr tal:define="name string:address; label string:E-mail address; value context/address">
- <th metal:use-macro="th_label">E-mail address</th>
- <td tal:define="mailto python:context.address.field(id='address');
- mklink python:mailto and not edit_ok">
- <a href="mailto:calvin@the-z.org"
- tal:attributes="href string:mailto:$value"
- tal:content="value"
- tal:condition="python:mklink">calvin@the-z.org</a>
- <tal:if condition=edit_ok>
- <input metal:use-macro="src_input" value="calvin@the-z.org">
- </tal:if>
-
- </td>
- </tr>
-
- <tr>
- <th><label for="alternate_addresses" i18n:translate="">Alternate E-mail addresses<br>One address per line</label></th>
- <td>
- <textarea rows=5 cols=40 tal:replace="structure context/alternate_addresses/multiline">nobody@nowhere.org
-anybody@everywhere.net
-(alternate_addresses)
- </textarea>
- </td>
- </tr>
-
- <tr tal:condition="edit_ok">
- <td>
-
- <input type="hidden" name="@template" value="item">
- <input type="hidden" name="@required" value="username,address"
- tal:attributes="value python:','.join(required)">
- </td>
- <td><input type="submit" value="save" tal:replace="structure context/submit"><!--submit button here-->
- <input type=reset>
- </td>
- </tr>
-</table>
-</form>
-
-<tal:block tal:condition="not:context/id" i18n:translate="">
-<table class="form">
-<tr>
- <td>Note: </td>
- <th class="required">highlighted</th>
- <td> fields are required.</td>
-</tr>
-</table>
-</tal:block>
-
-<tal:block tal:condition="context/id" tal:replace="structure context/history" />
-
-</div>
-
-</td>
-
-</tal:doc>
diff --git a/templates/minimal/html/user.register.html b/templates/minimal/html/user.register.html
+++ /dev/null
@@ -1,73 +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"
- i18n:translate="">Registering with <span i18n:name="tracker"
- tal:replace="db/config/TRACKER_NAME" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">Registering with <span i18n:name="tracker"
- tal:replace="db/config/TRACKER_NAME" /></span>
-<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 or request.user.hasRole('Anonymous'))"
- i18n:translate="">You are not allowed to view this page.</span>
-
-<span tal:condition="python:not editok and request.user.hasRole('Anonymous')"
- i18n:translate="">Please login with your username and password.</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 i18n:translate="">Login Name</th>
- <td tal:content="structure context/username/field">username</td>
- </tr>
- <tr>
- <th i18n:translate="">Login Password</th>
- <td tal:content="structure context/password/field">password</td>
- </tr>
- <tr>
- <th i18n:translate="">Confirm Password</th>
- <td tal:content="structure context/password/confirm">password</td>
- </tr>
- <tr tal:condition="python:request.user.hasPermission('Web Roles')">
- <th i18n:translate="">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 i18n:translate="">E-mail address</th>
- <td tal:content="structure context/address/field">address</td>
- </tr>
- <tr>
- <th i18n:translate="">Alternate E-mail addresses<br>One address per line</th>
- <td tal:content="structure context/alternate_addresses/multiline">alternate_addresses</td>
- </tr>
-
- <tr>
- <td> </td>
- <td>
- <input type="hidden" name=":action" value="register">
- <input type="submit" name="submit" value="Register" i18n:attributes="value">
- </td>
- </tr>
-</table>
-</form>
-
-</tal:block>
-
-</tal:block>
-
-</td>
-
-</tal:block>
diff --git a/templates/minimal/html/user.rego_progress.html b/templates/minimal/html/user.rego_progress.html
+++ /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"
- i18n:translate="">Registration in progress - <span i18n:name="tracker"
- tal:replace="config/TRACKER_NAME" /></title>
-<span metal:fill-slot="body_title" tal:omit-tag="python:1"
- i18n:translate="">Registration in progress...</span>
-<td class="content" metal:fill-slot="content">
-
-<p i18n:translate="">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/minimal/initial_data.py b/templates/minimal/initial_data.py
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# TRACKER DATABASE INITIALIZATION
-#
-
-# create the two default users
-user = db.getclass('user')
-user.create(username="admin", password=adminpw,
- address=admin_email, roles='Admin')
-user.create(username="anonymous", roles='Anonymous')
-
-# add any additional database creation steps here - but only if you
-# haven't initialised the database with the admin "initialise" command
-
-# vim: set et sts=4 sw=4 :
diff --git a/templates/minimal/schema.py b/templates/minimal/schema.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#
-# TRACKER SCHEMA
-#
-
-# Class automatically gets these properties:
-# creation = Date()
-# activity = Date()
-# creator = Link('user')
-# actor = Link('user')
-
-# 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")
-#
-# TRACKER SECURITY SETTINGS
-#
-# See the configuration and customisation document for information
-# about security setup.
-
-#
-# REGULAR USERS
-#
-# Give the regular users access to the web and email interface
-db.security.addPermissionToRole('User', 'Web Access')
-db.security.addPermissionToRole('User', 'Email Access')
-
-# May users view other user information?
-# Comment these lines out if you don't want them to
-db.security.addPermissionToRole('User', 'View', 'user')
-
-# Users should be able to edit their own details -- this permission is
-# limited to only the situation where the Viewed or Edited item is their own.
-def own_record(db, userid, itemid):
- '''Determine whether the userid matches the item being accessed.'''
- return userid == itemid
-p = db.security.addPermission(name='View', klass='user', check=own_record,
- description="User is allowed to view their own user details")
-db.security.addPermissionToRole('User', p)
-p = db.security.addPermission(name='Edit', klass='user', check=own_record,
- description="User is allowed to edit their own user details")
-db.security.addPermissionToRole('User', p)
-
-#
-# ANONYMOUS USER PERMISSIONS
-#
-# Let anonymous users access the web interface. Note that almost all
-# trackers will need this Permission. The only situation where it's not
-# required is in a tracker that uses an HTTP Basic Authenticated front-end.
-db.security.addPermissionToRole('Anonymous', 'Web Access')
-
-# Let anonymous users access the email interface (note that this implies
-# that they will be registered automatically, hence they will need the
-# "Create" user Permission below)
-db.security.addPermissionToRole('Anonymous', 'Email Access')
-
-# Assign the appropriate permissions to the anonymous user's
-# Anonymous Role. Choices here are:
-# - Allow anonymous users to register
-db.security.addPermissionToRole('Anonymous', 'Create', 'user')
-
-# vim: set et sts=4 sw=4 :