index f3789f0e13e946bcd53c28d068f87f70a7ec2f88..324e75f47ac5114833fbdeeb51b05fb6139f2706 100644 (file)
"""Implements the API used in the HTML templating for the web interface.
"""
+
+todo = '''
+- Most methods should have a "default" arg to supply a value
+ when none appears in the hyperdb or request.
+- Multilink property additions: change_note and new_upload
+- Add class.find() too
+- NumberHTMLProperty should support numeric operations
+- HTMLProperty should have an isset() method
+'''
+
__docformat__ = 'restructuredtext'
from __future__ import nested_scopes
raise
if self.templates.has_key(src) and \
- stime < self.templates[src].mtime:
+ stime <= self.templates[src].mtime:
# compiled template is up to date
return self.templates[src]
content_type = mimetypes.guess_type(filename)[0] or 'text/html'
pt.pt_edit(open(src).read(), content_type)
pt.id = filename
- pt.mtime = time.time()
+ pt.mtime = stime
return pt
def __getitem__(self, name):
'tracker': client.instance,
'utils': utils(client),
'templates': Templates(client.instance.config.TEMPLATES),
+ 'template': self,
}
# add in the item if there is one
if client.nodeid:
# check to see if we're actually accessing an item
m = desre.match(item)
if m:
- self._client.db.getclass(m.group('cl'))
- return HTMLItem(self._client, m.group('cl'), m.group('id'))
+ cl = m.group('cl')
+ self._client.db.getclass(cl)
+ if cl == 'user':
+ klass = HTMLUser
+ else:
+ klass = HTMLItem
+ return klass(self._client, cl, m.group('id'))
else:
self._client.db.getclass(item)
if item == 'user':
def classes(self):
l = self._client.db.classes.keys()
l.sort()
- r = []
+ m = []
for item in l:
if item == 'user':
m.append(HTMLUserClass(self._client, item))
m.append(HTMLClass(self._client, item))
- return r
+ return m
-def lookupIds(db, prop, ids, fail_ok=False, num_re=re.compile('-?\d+')):
+def lookupIds(db, prop, ids, fail_ok=0, num_re=re.compile('-?\d+')):
''' "fail_ok" should be specified if we wish to pass through bad values
(most likely form values that we wish to represent back to the user)
'''
l = []
for entry in ids:
if num_re.match(entry):
- l.append(cl.get(entry, key))
+ l.append(linkcl.get(entry, key))
else:
l.append(entry)
return l
if form.has_key(item):
if isinstance(prop, hyperdb.Multilink):
value = lookupIds(self._db, prop,
- handleListCGIValue(form[item]), fail_ok=True)
+ handleListCGIValue(form[item]), fail_ok=1)
elif isinstance(prop, hyperdb.Link):
value = form[item].value.strip()
if value:
value = lookupIds(self._db, prop, [value],
- fail_ok=True)[0]
+ fail_ok=1)[0]
else:
value = None
else:
def designator(self):
"""Return this item's designator (classname + id)."""
return '%s%s'%(self._classname, self._nodeid)
+
+ def is_retired(self):
+ """Is this item retired?"""
+ return self._klass.is_retired(self._nodeid)
def submit(self, label="Submit Changes"):
"""Generate a submit button.
timezone = self._db.getUserTimezone()
if direction == 'descending':
history.reverse()
+ # pre-load the history with the current state
for prop_n in self._props.keys():
prop = self[prop_n]
- if isinstance(prop, HTMLProperty):
- current[prop_n] = prop.plain()
- # make link if hrefable
- if (self._props.has_key(prop_n) and
- isinstance(self._props[prop_n], hyperdb.Link)):
- classname = self._props[prop_n].classname
- try:
- template = find_template(self._db.config.TEMPLATES,
- classname, 'item')
- if template[1].startswith('_generic'):
- raise NoTemplate, 'not really...'
- except NoTemplate:
- pass
- else:
- id = self._klass.get(self._nodeid, prop_n, None)
- current[prop_n] = '<a href="%s%s">%s</a>'%(
- classname, id, current[prop_n])
+ if not isinstance(prop, HTMLProperty):
+ continue
+ current[prop_n] = prop.plain()
+ # make link if hrefable
+ if (self._props.has_key(prop_n) and
+ isinstance(self._props[prop_n], hyperdb.Link)):
+ classname = self._props[prop_n].classname
+ try:
+ template = find_template(self._db.config.TEMPLATES,
+ classname, 'item')
+ if template[1].startswith('_generic'):
+ raise NoTemplate, 'not really...'
+ except NoTemplate:
+ pass
+ else:
+ id = self._klass.get(self._nodeid, prop_n, None)
+ current[prop_n] = '<a href="%s%s">%s</a>'%(
+ classname, id, current[prop_n])
for id, evt_date, user, action, args in history:
date_s = str(evt_date.local(timezone)).replace("."," ")
current[k] = str(d)
elif isinstance(prop, hyperdb.Interval) and args[k]:
- d = date.Interval(args[k])
- cell.append('%s: %s'%(k, str(d)))
+ val = str(date.Interval(args[k]))
+ cell.append('%s: %s'%(k, val))
if current.has_key(k):
cell[-1] += ' -> %s'%current[k]
- current[k] = str(d)
+ current[k] = val
elif isinstance(prop, hyperdb.String) and args[k]:
- cell.append('%s: %s'%(k, cgi.escape(args[k])))
+ val = cgi.escape(args[k])
+ cell.append('%s: %s'%(k, val))
if current.has_key(k):
cell[-1] += ' -> %s'%current[k]
- current[k] = cgi.escape(args[k])
+ current[k] = val
+
+ elif isinstance(prop, hyperdb.Boolean) and args[k] is not None:
+ val = args[k] and 'Yes' or 'No'
+ cell.append('%s: %s'%(k, val))
+ if current.has_key(k):
+ cell[-1] += ' -> %s'%current[k]
+ current[k] = val
elif not args[k]:
if current.has_key(k):
# use our fabricated request
return pt.render(self._client, req.classname, req)
+ def download_url(self):
+ ''' Assume that this item is a FileClass and that it has a name
+ and content. Construct a URL for the download of the content.
+ '''
+ name = self._klass.get(self._nodeid, 'name')
+ url = '%s%s/%s'%(self._classname, self._nodeid, name)
+ return urllib.quote(url)
+
+
class HTMLUserPermission:
def is_edit_ok(self):
return cmp(self._value, other._value)
return cmp(self._value, other)
+ def isset(self):
+ '''Is my _value None?'''
+ return self._value is None
+
def is_edit_ok(self):
''' Is the user allowed to Edit the current class?
'''
'''
self.view_check()
- if not is_edit_ok():
+ if not self.is_edit_ok():
return self.plain()
checked = self._value and "checked" or ""
tz = self._db.getUserTimezone()
value = cgi.escape(str(self._value.local(tz)))
- if is_edit_ok():
+ if self.is_edit_ok():
value = '"'.join(value.split('"'))
return self.input(name=self._formname,value=value,size=size)
else:
k = linkcl.getkey()
if k:
- label = linkcl.get(self._value, k)
+ value = linkcl.get(self._value, k)
else:
- label = self._value
- value = cgi.escape(str(self._value))
+ value = self._value
+ value = cgi.escape(str(value))
value = '"'.join(value.split('"'))
return '<input name="%s" value="%s" size="%s">'%(self._formname,
- label, size)
+ value, size)
def menu(self, size=None, height=None, showid=0, additional=[],
sort_on=None, **conditions):
'''
return str(value) in self._value
+ def isset(self):
+ '''Is my _value []?'''
+ return self._value == []
+
def reverse(self):
''' return the list in reverse order
'''
return Batch(self.client, sequence, size, start, end, orphan,
overlap)
+ def url_quote(self, url):
+ '''URL-quote the supplied text.'''
+ return urllib.quote(url)
+
+ def html_quote(self, html):
+ '''HTML-quote the supplied text.'''
+ return cgi.escape(url)
+