Code

oops, fubared the confirm password field
[roundup.git] / roundup / cgi / templating.py
index bf2552eac27a515f5445567007d35a96df478fa7..54bf622e8d0ae9316c43a20323f79ca81f25f76e 100644 (file)
@@ -391,6 +391,10 @@ class HTMLClass(HTMLPermissions):
             filterspec = request.filterspec
             sort = request.sort
             group = request.group
+        else:
+            filterspec = {}
+            sort = (None,None)
+            group = (None,None)
         if self.classname == 'user':
             klass = HTMLUser
         else:
@@ -515,6 +519,7 @@ class HTMLItem(HTMLPermissions):
         comments = {}
         history = self._klass.history(self._nodeid)
         history.sort()
+        timezone = self._db.getUserTimezone()
         if direction == 'descending':
             history.reverse()
             for prop_n in self._props.keys():
@@ -530,7 +535,7 @@ class HTMLItem(HTMLPermissions):
                                 self._klass.get(self._nodeid, prop_n, None), current[prop_n])
  
         for id, evt_date, user, action, args in history:
-            date_s = str(evt_date).replace("."," ")
+            date_s = str(evt_date.local(timezone)).replace("."," ")
             arg_s = ''
             if action == 'link' and type(args) == type(()):
                 if len(args) == 3:
@@ -632,10 +637,12 @@ class HTMLItem(HTMLPermissions):
                                     current[k] = old
 
                         elif isinstance(prop, hyperdb.Date) and args[k]:
-                            d = date.Date(args[k])
+                            d = date.Date(args[k]).local(timezone)
                             cell.append('%s: %s'%(k, str(d)))
                             if current.has_key(k):
-                                cell[-1] += ' -> %s'%current[k]
+                                if not current[k] == '(no value)' and current[k]:
+                                    current[k] = date.Date(current[k]).local(timezone)
+                                cell[-1] += ' -> %s' % current[k]
                                 current[k] = str(d)
 
                         elif isinstance(prop, hyperdb.Interval) and args[k]:
@@ -766,25 +773,26 @@ class HTMLProperty:
         return cmp(self._value, other)
 
 class StringHTMLProperty(HTMLProperty):
-    url_re = re.compile(r'\w{3,6}://\S+')
-    email_re = re.compile(r'[\w\.]+@[\w\.\-]+')
-    designator_re = re.compile(r'([a-z_]+)(\d+)')
-    def _url_repl(self, match):
-        s = match.group(0)
-        return '<a href="%s">%s</a>'%(s, s)
-    def _email_repl(self, match):
-        s = match.group(0)
-        return '<a href="mailto:%s">%s</a>'%(s, s)
-    def _designator_repl(self, match):
-        s = match.group(0)
-        s1 = match.group(1)
-        s2 = match.group(2)
-        try:
-            # make sure s1 is a valid tracker classname
-            self._db.getclass(s1)
-            return '<a href="%s">%s %s</a>'%(s, s1, s2)
-        except KeyError:
-            return '%s%s'%(s1, s2)
+    hyper_re = re.compile(r'((?P<url>\w{3,6}://\S+)|'
+                          r'(?P<email>[\w\.]+@[\w\.\-]+)|'
+                          r'(?P<item>(?P<class>[a-z_]+)(?P<id>\d+)))')
+    def _hyper_repl(self, match):
+        if match.group('url'):
+            s = match.group('url')
+            return '<a href="%s">%s</a>'%(s, s)
+        elif match.group('email'):
+            s = match.group('email')
+            return '<a href="mailto:%s">%s</a>'%(s, s)
+        else:
+            s = match.group('item')
+            s1 = match.group('class')
+            s2 = match.group('id')
+            try:
+                # make sure s1 is a valid tracker classname
+                self._db.getclass(s1)
+                return '<a href="%s">%s %s</a>'%(s, s1, s2)
+            except KeyError:
+                return '%s%s'%(s1, s2)
 
     def plain(self, escape=0, hyperlink=0):
         ''' Render a "plain" representation of the property
@@ -802,9 +810,7 @@ class StringHTMLProperty(HTMLProperty):
         if hyperlink:
             if not escape:
                 s = cgi.escape(s)
-            s = self.url_re.sub(self._url_repl, s)
-            s = self.email_re.sub(self._email_repl, s)
-            s = self.designator_re.sub(self._designator_repl, s)
+            s = self.hyper_re.sub(self._hyper_repl, s)
         return s
 
     def stext(self, escape=0):
@@ -870,9 +876,9 @@ class PasswordHTMLProperty(HTMLProperty):
     def confirm(self, size = 30):
         ''' Render a second form edit field for the property, used for 
             confirmation that the user typed the password correctly. Generates
-            a field with name "name:confirm".
+            a field with name ":confirm:name".
         '''
-        return '<input type="password" name="%s:confirm" size="%s">'%(
+        return '<input type="password" name=":confirm:%s" size="%s">'%(
             self._name, size)
 
 class NumberHTMLProperty(HTMLProperty):
@@ -919,7 +925,16 @@ class DateHTMLProperty(HTMLProperty):
         '''
         if self._value is None:
             return ''
-        return str(self._value)
+        return str(self._value.local(self._db.getUserTimezone()))
+
+    def now(self):
+        ''' Return the current time.
+
+            This is useful for defaulting a new value. Returns a
+            DateHTMLProperty.
+        '''
+        return DateHTMLProperty(self._client, self._nodeid, self._prop,
+            self._name, date.Date('.'))
 
     def field(self, size = 30):
         ''' Render a form edit field for the property
@@ -927,7 +942,7 @@ class DateHTMLProperty(HTMLProperty):
         if self._value is None:
             value = ''
         else:
-            value = cgi.escape(str(self._value))
+            value = cgi.escape(str(self._value.local(self._db.getUserTimezone())))
             value = '&quot;'.join(value.split('"'))
         return '<input name="%s" value="%s" size="%s">'%(self._name, value, size)
 
@@ -959,7 +974,7 @@ class DateHTMLProperty(HTMLProperty):
         ''' Return the date/time as a local (timezone offset) date/time.
         '''
         return DateHTMLProperty(self._client, self._nodeid, self._prop,
-            self._name, self._value.local())
+            self._name, self._value.local(offset))
 
 class IntervalHTMLProperty(HTMLProperty):
     def plain(self):
@@ -1335,6 +1350,9 @@ class HTMLRequest:
         self.classname = client.classname
         self.template = client.template
 
+        # the special char to use for special vars
+        self.special_char = '@'
+
         self._post_init()
 
     def _post_init(self):
@@ -1342,36 +1360,46 @@ class HTMLRequest:
         '''
         # extract the index display information from the form
         self.columns = []
-        if self.form.has_key(':columns'):
-            self.columns = handleListCGIValue(self.form[':columns'])
+        for name in ':columns @columns'.split():
+            if self.form.has_key(name):
+                self.special_char = name[0]
+                self.columns = handleListCGIValue(self.form[name])
+                break
         self.show = ShowDict(self.columns)
 
         # sorting
         self.sort = (None, None)
-        if self.form.has_key(':sort'):
-            sort = self.form[':sort'].value
-            if sort.startswith('-'):
-                self.sort = ('-', sort[1:])
-            else:
-                self.sort = ('+', sort)
-        if self.form.has_key(':sortdir'):
-            self.sort = ('-', self.sort[1])
+        for name in ':sort @sort'.split():
+            if self.form.has_key(name):
+                self.special_char = name[0]
+                sort = self.form[name].value
+                if sort.startswith('-'):
+                    self.sort = ('-', sort[1:])
+                else:
+                    self.sort = ('+', sort)
+                if self.form.has_key(self.special_char+'sortdir'):
+                    self.sort = ('-', self.sort[1])
 
         # grouping
         self.group = (None, None)
-        if self.form.has_key(':group'):
-            group = self.form[':group'].value
-            if group.startswith('-'):
-                self.group = ('-', group[1:])
-            else:
-                self.group = ('+', group)
-        if self.form.has_key(':groupdir'):
-            self.group = ('-', self.group[1])
+        for name in ':group @group'.split():
+            if self.form.has_key(name):
+                self.special_char = name[0]
+                group = self.form[name].value
+                if group.startswith('-'):
+                    self.group = ('-', group[1:])
+                else:
+                    self.group = ('+', group)
+                if self.form.has_key(self.special_char+'groupdir'):
+                    self.group = ('-', self.group[1])
 
         # filtering
         self.filter = []
-        if self.form.has_key(':filter'):
-            self.filter = handleListCGIValue(self.form[':filter'])
+        for name in ':filter @filter'.split():
+            if self.form.has_key(name):
+                self.special_char = name[0]
+                self.filter = handleListCGIValue(self.form[name])
+
         self.filterspec = {}
         db = self.client.db
         if self.classname is not None:
@@ -1389,19 +1417,24 @@ class HTMLRequest:
 
         # full-text search argument
         self.search_text = None
-        if self.form.has_key(':search_text'):
-            self.search_text = self.form[':search_text'].value
+        for name in ':search_text @search_text'.split():
+            if self.form.has_key(name):
+                self.special_char = name[0]
+                self.search_text = self.form[name].value
 
         # pagination - size and start index
         # figure batch args
-        if self.form.has_key(':pagesize'):
-            self.pagesize = int(self.form[':pagesize'].value)
-        else:
-            self.pagesize = 50
-        if self.form.has_key(':startwith'):
-            self.startwith = int(self.form[':startwith'].value)
-        else:
-            self.startwith = 0
+        self.pagesize = 50
+        for name in ':pagesize @pagesize'.split():
+            if self.form.has_key(name):
+                self.special_char = name[0]
+                self.pagesize = int(self.form[name].value)
+
+        self.startwith = 0
+        for name in ':startwith @startwith'.split():
+            if self.form.has_key(name):
+                self.special_char = name[0]
+                self.startwith = int(self.form[name].value)
 
     def updateFromURL(self, url):
         ''' Parse the URL for query args, and update my attributes using the
@@ -1474,23 +1507,24 @@ env: %(env)s
             filterspec=1):
         ''' return the current index args as form elements '''
         l = []
+        sc = self.special_char
         s = '<input type="hidden" name="%s" value="%s">'
         if columns and self.columns:
-            l.append(s%(':columns', ','.join(self.columns)))
+            l.append(s%(sc+'columns', ','.join(self.columns)))
         if sort and self.sort[1] is not None:
             if self.sort[0] == '-':
                 val = '-'+self.sort[1]
             else:
                 val = self.sort[1]
-            l.append(s%(':sort', val))
+            l.append(s%(sc+'sort', val))
         if group and self.group[1] is not None:
             if self.group[0] == '-':
                 val = '-'+self.group[1]
             else:
                 val = self.group[1]
-            l.append(s%(':group', val))
+            l.append(s%(sc+'group', val))
         if filter and self.filter:
-            l.append(s%(':filter', ','.join(self.filter)))
+            l.append(s%(sc+'filter', ','.join(self.filter)))
         if filterspec:
             for k,v in self.filterspec.items():
                 if type(v) == type([]):
@@ -1498,30 +1532,31 @@ env: %(env)s
                 else:
                     l.append(s%(k, v))
         if self.search_text:
-            l.append(s%(':search_text', self.search_text))
-        l.append(s%(':pagesize', self.pagesize))
-        l.append(s%(':startwith', self.startwith))
+            l.append(s%(sc+'search_text', self.search_text))
+        l.append(s%(sc+'pagesize', self.pagesize))
+        l.append(s%(sc+'startwith', self.startwith))
         return '\n'.join(l)
 
     def indexargs_url(self, url, args):
         ''' embed the current index args in a URL '''
+        sc = self.special_char
         l = ['%s=%s'%(k,v) for k,v in args.items()]
         if self.columns and not args.has_key(':columns'):
-            l.append(':columns=%s'%(','.join(self.columns)))
+            l.append(sc+'columns=%s'%(','.join(self.columns)))
         if self.sort[1] is not None and not args.has_key(':sort'):
             if self.sort[0] == '-':
                 val = '-'+self.sort[1]
             else:
                 val = self.sort[1]
-            l.append(':sort=%s'%val)
+            l.append(sc+'sort=%s'%val)
         if self.group[1] is not None and not args.has_key(':group'):
             if self.group[0] == '-':
                 val = '-'+self.group[1]
             else:
                 val = self.group[1]
-            l.append(':group=%s'%val)
-        if self.filter and not args.has_key(':columns'):
-            l.append(':filter=%s'%(','.join(self.filter)))
+            l.append(sc+'group=%s'%val)
+        if self.filter and not args.has_key(':filter'):
+            l.append(sc+'filter=%s'%(','.join(self.filter)))
         for k,v in self.filterspec.items():
             if not args.has_key(k):
                 if type(v) == type([]):
@@ -1529,11 +1564,11 @@ env: %(env)s
                 else:
                     l.append('%s=%s'%(k, v))
         if self.search_text and not args.has_key(':search_text'):
-            l.append(':search_text=%s'%self.search_text)
+            l.append(sc+'search_text=%s'%self.search_text)
         if not args.has_key(':pagesize'):
-            l.append(':pagesize=%s'%self.pagesize)
+            l.append(sc+'pagesize=%s'%self.pagesize)
         if not args.has_key(':startwith'):
-            l.append(':startwith=%s'%self.startwith)
+            l.append(sc+'startwith=%s'%self.startwith)
         return '%s?%s'%(url, '&'.join(l))
     indexargs_href = indexargs_url