Code

sort HTMLClass.properties results by name (sf feature 724738)
[roundup.git] / roundup / cgi / templating.py
index 0984bc137a2f1e6681e63b577e400e36a89f4fce..cd4a87194f2705904a0b65e21607d3e79a9ccd3c 100644 (file)
@@ -38,9 +38,9 @@ class Templates:
             if os.path.isdir(filename): continue
             if '.' in filename:
                 name, extension = filename.split('.')
-                self.getTemplate(name, extension)
+                self.get(name, extension)
             else:
-                self.getTemplate(filename, None)
+                self.get(filename, None)
 
     def get(self, name, extension=None):
         ''' Interface to get a template, possibly loading a compiled template.
@@ -66,27 +66,31 @@ class Templates:
             filename = name
 
         src = os.path.join(self.dir, filename)
+        if not os.path.exists(src):
+            filename = filename + '.html'
+            src = os.path.join(self.dir, filename)
+            if not os.path.exists(src):
+                if not extension:
+                    raise NoTemplate, 'Template file "%s" doesn\'t exist'%name
+
+                # try for a generic template
+                generic = '_generic.%s'%extension
+                src = os.path.join(self.dir, generic)
+                if not os.path.exists(src):
+                    generic = '_generic.%s.html'%extension
+                    src = os.path.join(self.dir, generic)
+                    if not os.path.exists(src):
+                        raise NoTemplate, 'No template file exists for '\
+                            'templating "%s" with template "%s" (neither '\
+                            '"%s" nor "%s")'%(name, extension, filename,
+                            generic)
+                filename = generic
+
         try:
             stime = os.stat(src)[os.path.stat.ST_MTIME]
         except os.error, error:
             if error.errno != errno.ENOENT:
                 raise
-            if not extension:
-                raise NoTemplate, 'Template file "%s" doesn\'t exist'%name
-
-            # try for a generic template
-            generic = '_generic.%s'%extension
-            src = os.path.join(self.dir, generic)
-            try:
-                stime = os.stat(src)[os.path.stat.ST_MTIME]
-            except os.error, error:
-                if error.errno != errno.ENOENT:
-                    raise
-                # nicer error
-                raise NoTemplate, 'No template file exists for templating '\
-                    '"%s" with template "%s" (neither "%s" nor "%s")'%(name,
-                    extension, filename, generic)
-            filename = generic
 
         if self.templates.has_key(src) and \
                 stime < self.templates[src].mtime:
@@ -334,7 +338,7 @@ class HTMLClass(HTMLPermissions):
 
         return klass(self._client, self.classname, itemid)
 
-    def properties(self):
+    def properties(self, sort=1):
         ''' Return HTMLProperty for all of this class' properties.
         '''
         l = []
@@ -347,6 +351,8 @@ class HTMLClass(HTMLPermissions):
                 if isinstance(prop, klass):
                     l.append(htmlklass(self._client, self._classname, '',
                         prop, name, value, self._anonymous))
+        if sort:
+            l.sort(lambda a,b:cmp(a._name, b._name))
         return l
 
     def list(self):
@@ -403,6 +409,7 @@ class HTMLClass(HTMLPermissions):
         ''' Return a list of items from this class, filtered and sorted
             by the current requested filterspec/filter/sort/group args
         '''
+        # XXX allow direct specification of the filterspec etc.
         if request is not None:
             filterspec = request.filterspec
             sort = request.sort
@@ -419,8 +426,8 @@ class HTMLClass(HTMLPermissions):
              for x in self._klass.filter(None, filterspec, sort, group)]
         return l
 
-    def classhelp(self, properties=None, label='list', width='500',
-            height='400'):
+    def classhelp(self, properties=None, label='(list)', width='500',
+            height='400', property=''):
         ''' Pop up a javascript window with class help
 
             This generates a link to a popup window which displays the 
@@ -432,14 +439,19 @@ class HTMLClass(HTMLPermissions):
 
             You may optionally override the label displayed, the width and
             height. The popup window will be resizable and scrollable.
+
+            If the "property" arg is given, it's passed through to the
+            javascript help_window function.
         '''
         if properties is None:
             properties = self._klass.getprops(protected=0).keys()
             properties.sort()
             properties = ','.join(properties)
-        return '<a href="javascript:help_window(\'%s?:template=help&' \
-            'properties=%s\', \'%s\', \'%s\')"><b>(%s)</b></a>'%(
-            self.classname, properties, width, height, label)
+        if property:
+            property = '&property=%s'%property
+        return '<a class="classhelp" href="javascript:help_window(\'%s?:'\
+            'template=help&properties=%s%s\', \'%s\', \'%s\')">%s</a>'%(
+            self.classname, properties, property, width, height, label)
 
     def submit(self, label="Submit New Entry"):
         ''' Generate a submit button (and action hidden element)
@@ -924,6 +936,17 @@ class NumberHTMLProperty(HTMLProperty):
             value = '&quot;'.join(value.split('"'))
         return '<input name="%s" value="%s" size="%s">'%(self._formname, value, size)
 
+    def __int__(self):
+        ''' Return an int of me
+        '''
+        return int(self._value)
+
+    def __float__(self):
+        ''' Return a float of me
+        '''
+        return float(self._value)
+
+
 class BooleanHTMLProperty(HTMLProperty):
     def plain(self):
         ''' Render a "plain" representation of the property
@@ -1436,13 +1459,17 @@ class HTMLRequest:
         if self.classname is not None:
             props = db.getclass(self.classname).getprops()
             for name in self.filter:
-                if self.form.has_key(name):
-                    prop = props[name]
-                    fv = self.form[name]
-                    if (isinstance(prop, hyperdb.Link) or
-                            isinstance(prop, hyperdb.Multilink)):
-                        self.filterspec[name] = lookupIds(db, prop,
-                            handleListCGIValue(fv))
+                if not self.form.has_key(name):
+                    continue
+                prop = props[name]
+                fv = self.form[name]
+                if (isinstance(prop, hyperdb.Link) or
+                        isinstance(prop, hyperdb.Multilink)):
+                    self.filterspec[name] = lookupIds(db, prop,
+                        handleListCGIValue(fv))
+                else:
+                    if isinstance(fv, type([])):
+                        self.filterspec[name] = [v.value for v in fv]
                     else:
                         self.filterspec[name] = fv.value