1515# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717#
18- # $Id: cgi_client.py,v 1.102 2002-02-15 07:08:44 richard Exp $
18+ # $Id: cgi_client.py,v 1.103 2002-02-20 05:05:28 richard Exp $
1919
2020__doc__ = """
2121WWW request handler (also used in the stand-alone server).
@@ -298,10 +298,88 @@ def list(self, sort=None, group=None, filter=None, columns=None,
298298 show_customization = self .customization_widget ()
299299
300300 index = htmltemplate .IndexTemplate (self , self .instance .TEMPLATES , cn )
301- index .render (filterspec , filter , columns , sort , group ,
302- show_customization = show_customization )
301+ try :
302+ index .render (filterspec , filter , columns , sort , group ,
303+ show_customization = show_customization )
304+ except htmltemplate .MissingTemplateError :
305+ self .basicClassEditPage ()
303306 self .pagefoot ()
304307
308+ def basicClassEditPage (self ):
309+ '''Display a basic edit page that allows simple editing of the
310+ nodes of the current class
311+ '''
312+ if self .user != 'admin' :
313+ raise Unauthorised
314+ w = self .write
315+ cn = self .classname
316+ cl = self .db .classes [cn ]
317+ props = ['id' ] + cl .getprops (protected = 0 ).keys ()
318+
319+ # get the CSV module
320+ try :
321+ import csv
322+ except ImportError :
323+ w (_ ('Sorry, you need the csv module to use this function.<br>\n '
324+ 'Get it from: <a href="http://www.object-craft.com.au/projects/csv/">http://www.object-craft.com.au/projects/csv/' ))
325+ return
326+
327+ # do the edit
328+ if self .form .has_key ('rows' ):
329+ rows = self .form ['rows' ].value .splitlines ()
330+ p = csv .parser ()
331+ idlessprops = props [1 :]
332+ found = {}
333+ for row in rows :
334+ values = p .parse (row )
335+ # not a complete row, keep going
336+ if not values : continue
337+
338+ # extract the nodeid
339+ nodeid , values = values [0 ], values [1 :]
340+ found [nodeid ] = 1
341+
342+ # extract the new values
343+ d = {}
344+ for name , value in zip (idlessprops , values ):
345+ d [name ] = value .strip ()
346+
347+ # perform the edit
348+ if cl .hasnode (nodeid ):
349+ # edit existing
350+ cl .set (nodeid , ** d )
351+ else :
352+ # new node
353+ found [cl .create (** d )] = 1
354+
355+ # retire the removed entries
356+ for nodeid in cl .list ():
357+ if not found .has_key (nodeid ):
358+ cl .retire (nodeid )
359+
360+ w (_ ('''<p class="form-help">You may edit the contents of the
361+ "%(classname)s" class using this form.</p>
362+ <p class="form-help">Remove entries by deleting their line. Add
363+ new entries by appending
364+ them to the table - put an X in the id column.</p>''' )% {'classname' :cn })
365+
366+ l = []
367+ for name in props :
368+ l .append (name )
369+ w ('<tt>' )
370+ w (', ' .join (l ) + '\n ' )
371+ w ('</tt>' )
372+
373+ w ('<form onSubmit="return submit_once()" method="POST">' )
374+ w ('<textarea name="rows" cols=80 rows=15>' )
375+ for nodeid in cl .list ():
376+ l = []
377+ for name in props :
378+ l .append (cgi .escape (str (cl .get (nodeid , name ))))
379+ w (', ' .join (l ) + '\n ' )
380+
381+ w (_ ('</textarea><br><input type="submit" value="Save Changes"></form>' ))
382+
305383 def shownode (self , message = None ):
306384 ''' display an item
307385 '''
@@ -744,7 +822,8 @@ def classes(self, message=None):
744822 self .write ('<table border=0 cellspacing=0 cellpadding=2>\n ' )
745823 for cn in classnames :
746824 cl = self .db .getclass (cn )
747- self .write ('<tr class="list-header"><th colspan=2 align=left>%s</th></tr>' % cn .capitalize ())
825+ self .write ('<tr class="list-header"><th colspan=2 align=left>'
826+ '<a href="%s">%s</a></th></tr>' % (cn , cn .capitalize ()))
748827 for key , value in cl .properties .items ():
749828 if value is None : value = ''
750829 else : value = str (value )
@@ -1012,6 +1091,8 @@ def do_action(self, action, dre=re.compile(r'([^\d]+)(\d+)'),
10121091 if action == 'logout' :
10131092 self .logout ()
10141093 return
1094+
1095+ # see if we're to display an existing node
10151096 m = dre .match (action )
10161097 if m :
10171098 self .classname = m .group (1 )
@@ -1030,6 +1111,8 @@ def do_action(self, action, dre=re.compile(r'([^\d]+)(\d+)'),
10301111 raise NotFound
10311112 func ()
10321113 return
1114+
1115+ # see if we're to put up the new node page
10331116 m = nre .match (action )
10341117 if m :
10351118 self .classname = m .group (1 )
@@ -1039,6 +1122,8 @@ def do_action(self, action, dre=re.compile(r'([^\d]+)(\d+)'),
10391122 raise NotFound
10401123 func ()
10411124 return
1125+
1126+ # otherwise, display the named class
10421127 self .classname = action
10431128 try :
10441129 self .db .getclass (self .classname )
@@ -1202,6 +1287,10 @@ def parsePropsFromForm(db, cl, form, nodeid=0):
12021287
12031288#
12041289# $Log: not supported by cvs2svn $
1290+ # Revision 1.102 2002/02/15 07:08:44 richard
1291+ # . Alternate email addresses are now available for users. See the MIGRATION
1292+ # file for info on how to activate the feature.
1293+ #
12051294# Revision 1.101 2002/02/14 23:39:18 richard
12061295# . All forms now have "double-submit" protection when Javascript is enabled
12071296# on the client-side.
0 commit comments