Code

. #527416 ] roundup-admin uses undefined value
[roundup.git] / roundup / cgi_client.py
index 0e446d48c3416eba68af6f936306d1c5e1bed7cd..aeb5fd64e50b34e9f6c7c5197b2f0899be85bdba 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: cgi_client.py,v 1.103 2002-02-20 05:05:28 richard Exp $
+# $Id: cgi_client.py,v 1.111 2002-02-25 04:32:21 richard Exp $
 
 __doc__ = """
 WWW request handler (also used in the stand-alone server).
@@ -52,6 +52,13 @@ class Client:
         self.env = env
         self.path = env['PATH_INFO']
         self.split_path = self.path.split('/')
+        self.instance_path_name = env['INSTANCE_NAME']
+        url = self.env['SCRIPT_NAME'] + '/'
+        machine = self.env['SERVER_NAME']
+        port = self.env['SERVER_PORT']
+        if port != '80': machine = machine + ':' + port
+        self.base = urlparse.urlunparse(('http', env['HTTP_HOST'], url,
+           None, None, None))
 
         if form is None:
             self.form = cgi.FieldStorage(environ=env)
@@ -80,7 +87,7 @@ class Client:
         if self.debug:
             self.headers_sent = headers
 
-    single_submit_script = '''
+    global_javascript = '''
 <script language="javascript">
 submitted = false;
 function submit_once() {
@@ -91,15 +98,15 @@ function submit_once() {
     submitted = true;
     return 1;
 }
+
+function help_window(helpurl, width, height) {
+    HelpWin = window.open('%(base)s%(instance_path_name)s/' + helpurl, 'HelpWindow', 'scrollbars=yes,resizable=yes,toolbar=no,height='+height+',width='+width);
+}
+
 </script>
 '''
 
     def pagehead(self, title, message=None):
-        url = self.env['SCRIPT_NAME'] + '/'
-        machine = self.env['SERVER_NAME']
-        port = self.env['SERVER_PORT']
-        if port != '80': machine = machine + ':' + port
-        base = urlparse.urlunparse(('http', machine, url, None, None, None))
         if message is not None:
             message = _('<div class="system-msg">%(message)s</div>')%locals()
         else:
@@ -127,12 +134,12 @@ function submit_once() {
 ''')
         else:
             add_links = ''
-        single_submit_script = self.single_submit_script
+        global_javascript = self.global_javascript%self.__dict__
         self.write(_('''<html><head>
 <title>%(title)s</title>
 <style type="text/css">%(style)s</style>
 </head>
-%(single_submit_script)s
+%(global_javascript)s
 <body bgcolor=#ffffff>
 %(message)s
 <table width=100%% border=0 cellspacing=0 cellpadding=2>
@@ -314,7 +321,9 @@ function submit_once() {
         w = self.write
         cn = self.classname
         cl = self.db.classes[cn]
-        props = ['id'] + cl.getprops(protected=0).keys()
+        idlessprops = cl.getprops(protected=0).keys()
+        props = ['id'] + idlessprops
+
 
         # get the CSV module
         try:
@@ -328,9 +337,10 @@ function submit_once() {
         if self.form.has_key('rows'):
             rows = self.form['rows'].value.splitlines()
             p = csv.parser()
-            idlessprops = props[1:]
             found = {}
+            line = 0
             for row in rows:
+                line += 1
                 values = p.parse(row)
                 # not a complete row, keep going
                 if not values: continue
@@ -339,6 +349,11 @@ function submit_once() {
                 nodeid, values = values[0], values[1:]
                 found[nodeid] = 1
 
+                # confirm correct weight
+                if len(idlessprops) != len(values):
+                    w(_('Not enough values on line %(line)s'%{'line':line}))
+                    return
+
                 # extract the new values
                 d = {}
                 for name, value in zip(idlessprops, values):
@@ -358,7 +373,10 @@ function submit_once() {
                     cl.retire(nodeid)
 
         w(_('''<p class="form-help">You may edit the contents of the
-        "%(classname)s" class using this form.</p>
+        "%(classname)s" class using this form. The lines are full-featured
+        Comma-Separated-Value lines, so you may include commas and even
+        newlines by enclosing the values in double-quotes ("). Double
+        quotes themselves must be quoted by doubling ("").</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>''')%{'classname':cn})
@@ -371,15 +389,37 @@ function submit_once() {
         w('</tt>')
 
         w('<form onSubmit="return submit_once()" method="POST">')
-       w('<textarea name="rows" cols=80 rows=15>')
+        w('<textarea name="rows" cols=80 rows=15>')
+        p = csv.parser()
         for nodeid in cl.list():
             l = []
             for name in props:
                 l.append(cgi.escape(str(cl.get(nodeid, name))))
-            w(', '.join(l) + '\n')
+            w(p.join(l) + '\n')
 
         w(_('</textarea><br><input type="submit" value="Save Changes"></form>'))
 
+    def classhelp(self):
+        '''Display a table of class info
+        '''
+        w = self.write
+        cn = self.form['classname'].value
+        cl = self.db.classes[cn]
+        props = self.form['properties'].value.split(',')
+
+        w('<table border=1 cellspacing=0 cellpaddin=2>')
+        w('<tr>')
+        for name in props:
+            w('<th align=left>%s</th>'%name)
+        w('</tr>')
+        for nodeid in cl.list():
+            w('<tr>')
+            for name in props:
+                value = cgi.escape(str(cl.get(nodeid, name)))
+                w('<td align="left" valign="top">%s</td>'%value)
+            w('</tr>')
+        w('</table>')
+
     def shownode(self, message=None):
         ''' display an item
         '''
@@ -1085,6 +1125,9 @@ function submit_once() {
         if action == 'list_classes':
             self.classes()
             return
+        if action == 'classhelp':
+            self.classhelp()
+            return
         if action == 'login':
             self.login()
             return
@@ -1148,11 +1191,6 @@ class ExtendedClient(Client):
     default_index_filterspec = {'status': ['1', '2', '3', '4', '5', '6', '7']}
 
     def pagehead(self, title, message=None):
-        url = self.env['SCRIPT_NAME'] + '/' #self.env.get('PATH_INFO', '/')
-        machine = self.env['SERVER_NAME']
-        port = self.env['SERVER_PORT']
-        if port != '80': machine = machine + ':' + port
-        base = urlparse.urlunparse(('http', machine, url, None, None, None))
         if message is not None:
             message = _('<div class="system-msg">%(message)s</div>')%locals()
         else:
@@ -1182,12 +1220,12 @@ class ExtendedClient(Client):
 ''')
         else:
             add_links = ''
-        single_submit_script = self.single_submit_script
+        global_javascript = self.global_javascript%self.__dict__
         self.write(_('''<html><head>
 <title>%(title)s</title>
 <style type="text/css">%(style)s</style>
 </head>
-%(single_submit_script)s
+%(global_javascript)s
 <body bgcolor=#ffffff>
 %(message)s
 <table width=100%% border=0 cellspacing=0 cellpadding=2>
@@ -1287,6 +1325,39 @@ def parsePropsFromForm(db, cl, form, nodeid=0):
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.110  2002/02/21 07:19:08  richard
+# ... and label, width and height control for extra flavour!
+#
+# Revision 1.109  2002/02/21 07:08:19  richard
+# oops
+#
+# Revision 1.108  2002/02/21 07:02:54  richard
+# The correct var is "HTTP_HOST"
+#
+# Revision 1.107  2002/02/21 06:57:38  richard
+#  . Added popup help for classes using the classhelp html template function.
+#    - add <display call="classhelp('priority', 'id,name,description')">
+#      to an item page, and it generates a link to a popup window which displays
+#      the id, name and description for the priority class. The description
+#      field won't exist in most installations, but it will be added to the
+#      default templates.
+#
+# Revision 1.106  2002/02/21 06:23:00  richard
+# *** empty log message ***
+#
+# Revision 1.105  2002/02/20 05:52:10  richard
+# better error handling
+#
+# Revision 1.104  2002/02/20 05:45:17  richard
+# Use the csv module for generating the form entry so it's correct.
+# [also noted the sf.net feature request id in the change log]
+#
+# Revision 1.103  2002/02/20 05:05:28  richard
+#  . Added simple editing for classes that don't define a templated interface.
+#    - access using the admin "class list" interface
+#    - limited to admin-only
+#    - requires the csv module from object-craft (url given if it's missing)
+#
 # Revision 1.102  2002/02/15 07:08:44  richard
 #  . Alternate email addresses are now available for users. See the MIGRATION
 #    file for info on how to activate the feature.