summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: c77f1c0)
raw | patch | inline | side by side (parent: c77f1c0)
author | gmcm <gmcm@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Mon, 8 Jul 2002 15:32:06 +0000 (15:32 +0000) | ||
committer | gmcm <gmcm@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Mon, 8 Jul 2002 15:32:06 +0000 (15:32 +0000) |
New search form.
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@835 57a73879-2fb5-44c3-a270-3262357dd7e2
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@835 57a73879-2fb5-44c3-a270-3262357dd7e2
roundup/cgi_client.py | patch | blob | history | |
roundup/htmltemplate.py | patch | blob | history |
diff --git a/roundup/cgi_client.py b/roundup/cgi_client.py
index bc6ff1bf11505fdd77ffa541a97988f78794ec73..83380f6685b580444de4784ad87bca0fe29279d6 100644 (file)
--- a/roundup/cgi_client.py
+++ b/roundup/cgi_client.py
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-# $Id: cgi_client.py,v 1.132 2002-07-08 07:26:14 richard Exp $
+# $Id: cgi_client.py,v 1.133 2002-07-08 15:32:05 gmcm Exp $
__doc__ = """
WWW request handler (also used in the stand-alone server).
d[':group'] = ','.join(map(urllib.quote, spec['GROUP']))
d[':filter'] = ','.join(map(urllib.quote, spec['FILTER']))
d[':columns'] = ','.join(map(urllib.quote, spec['COLUMNS']))
+ d[':pagesize'] = spec.get('PAGESIZE','50')
# snarf the filterspec
filterspec = spec['FILTERSPEC'].copy()
<tr class="location-bar">
<td align=left>%(links)s</td>
<td align=right>%(user_info)s</td>
-</table>
+</table><br>
''')%locals())
def pagefoot(self):
return arg.value.split(',')
return []
+ def index_sort(self):
+ # first try query string
+ x = self.index_arg(':sort')
+ if x:
+ return x
+ # nope - get the specs out of the form
+ specs = []
+ for colnm in self.db.getclass(self.classname).getprops().keys():
+ desc = ''
+ try:
+ spec = self.form[':%s_ss' % colnm]
+ except KeyError:
+ continue
+ spec = spec.value
+ if spec:
+ if spec[-1] == '-':
+ desc='-'
+ spec = spec[0]
+ specs.append((int(spec), colnm, desc))
+ specs.sort()
+ x = []
+ for _, colnm, desc in specs:
+ x.append('%s%s' % (desc, colnm))
+ return x
+
def index_filterspec(self, filter):
''' pull the index filter spec from the form
Links and multilinks want to be lists - the rest are straight
strings.
'''
- props = self.db.classes[self.classname].getprops()
- # all the form args not starting with ':' are filters
filterspec = {}
- for key in self.form.keys():
- if key[0] == ':': continue
- if not props.has_key(key): continue
- if key not in filter: continue
- prop = props[key]
- value = self.form[key]
- if (isinstance(prop, hyperdb.Link) or
- isinstance(prop, hyperdb.Multilink)):
- if type(value) == type([]):
- value = [arg.value for arg in value]
+ props = self.db.classes[self.classname].getprops()
+ for colnm in filter:
+ widget = ':%s_fs' % colnm
+ try:
+ val = self.form[widget]
+ except KeyError:
+ try:
+ val = self.form[colnm]
+ except KeyError:
+ # they checked the filter box but didn't enter a value
+ continue
+ propdescr = props.get(colnm, None)
+ if propdescr is None:
+ print "huh? %r is in filter & form, but not in Class!" % colnm
+ raise "butthead programmer"
+ if (isinstance(propdescr, hyperdb.Link) or
+ isinstance(propdescr, hyperdb.Multilink)):
+ if type(val) == type([]):
+ val = [arg.value for arg in val]
else:
- value = value.value.split(',')
- l = filterspec.get(key, [])
- l = l + value
- filterspec[key] = l
+ val = val.value.split(',')
+ l = filterspec.get(colnm, [])
+ l = l + val
+ filterspec[colnm] = l
else:
- filterspec[key] = value.value
+ filterspec[colnm] = val.value
+
return filterspec
-
+
def customization_widget(self):
''' The customization widget is visible by default. The widget
visibility is remembered by show_customization. Visibility
default_index_filter = ['status']
default_index_columns = ['id','activity','title','status','assignedto']
default_index_filterspec = {'status': ['1', '2', '3', '4', '5', '6', '7']}
+ default_pagesize = '50'
def _get_customisation_info(self):
# see if the web has supplied us with any customisation info
defaults = 1
- for key in ':sort', ':group', ':filter', ':columns':
+ for key in ':sort', ':group', ':filter', ':columns', ':pagesize':
if self.form.has_key(key):
defaults = 0
break
filter = d['FILTER']
columns = d['COLUMNS']
filterspec = d['FILTERSPEC']
+ pagesize = d.get('PAGESIZE', '50')
else:
# nope - fall back on the old way of doing it
filter = self.default_index_filter
columns = self.default_index_columns
filterspec = self.default_index_filterspec
+ pagesize = self.default_pagesize
else:
# make list() extract the info from the CGI environ
self.classname = 'issue'
- sort = group = filter = columns = filterspec = None
- return columns, filter, group, sort, filterspec
+ sort = group = filter = columns = filterspec = pagesize = None
+ return columns, filter, group, sort, filterspec, pagesize
def index(self):
''' put up an index - no class specified
'''
- columns, filter, group, sort, filterspec = \
+ columns, filter, group, sort, filterspec, pagesize = \
self._get_customisation_info()
return self.list(columns=columns, filter=filter, group=group,
- sort=sort, filterspec=filterspec)
+ sort=sort, filterspec=filterspec, pagesize=pagesize)
def searchnode(self):
- columns, filter, group, sort, filterspec = \
+ columns, filter, group, sort, filterspec, pagesize = \
self._get_customisation_info()
- show_nodes = 1
- if len(self.form.keys()) == 0:
- # get the default search filters from instance_config
- if hasattr(self.instance, 'SEARCH_FILTERS'):
- for f in self.instance.SEARCH_FILTERS:
- spec = getattr(self.instance, f)
- if spec['CLASS'] == self.classname:
- filter = spec['FILTER']
-
- show_nodes = 0
- show_customization = 1
- return self.list(columns=columns, filter=filter, group=group,
- sort=sort, filterspec=filterspec,
- show_customization=show_customization, show_nodes=show_nodes)
-
+## show_nodes = 1
+## if len(self.form.keys()) == 0:
+## # get the default search filters from instance_config
+## if hasattr(self.instance, 'SEARCH_FILTERS'):
+## for f in self.instance.SEARCH_FILTERS:
+## spec = getattr(self.instance, f)
+## if spec['CLASS'] == self.classname:
+## filter = spec['FILTER']
+##
+## show_nodes = 0
+## show_customization = 1
+## return self.list(columns=columns, filter=filter, group=group,
+## sort=sort, filterspec=filterspec,
+## show_customization=show_customization, show_nodes=show_nodes,
+## pagesize=pagesize)
+ cn = self.classname
+ self.pagehead(_('%(instancename)s: Index of %(classname)s')%{
+ 'classname': cn, 'instancename': self.instance.INSTANCE_NAME})
+ index = htmltemplate.IndexTemplate(self, self.instance.TEMPLATES, cn)
+ self.write('<form onSubmit="return submit_once()" action="%s">\n'%self.classname)
+ all_columns = self.db.getclass(cn).getprops().keys()
+ all_columns.sort()
+ index.filter_section('', filter, columns, group, all_columns, sort,
+ filterspec, pagesize, 0)
+ self.pagefoot()
+ index.db = index.cl = index.properties = None
+ index.clear()
# XXX deviates from spec - loses the '+' (that's a reserved character
# in URLS
def list(self, sort=None, group=None, filter=None, columns=None,
- filterspec=None, show_customization=None, show_nodes=1):
+ filterspec=None, show_customization=None, show_nodes=1, pagesize=None):
''' call the template index with the args
:sort - sort by prop name, optionally preceeded with '-'
cl = self.db.classes[cn]
self.pagehead(_('%(instancename)s: Index of %(classname)s')%{
'classname': cn, 'instancename': self.instance.INSTANCE_NAME})
- if sort is None: sort = self.index_arg(':sort')
+ if sort is None: sort = self.index_sort()
if group is None: group = self.index_arg(':group')
if filter is None: filter = self.index_arg(':filter')
if columns is None: columns = self.index_arg(':columns')
search_text = self.form['search_text'].value
else:
search_text = ''
+ if pagesize is None:
+ if self.form.has_key(':pagesize'):
+ pagesize = self.form[':pagesize'].value
+ else:
+ pagesize = '50'
+ pagesize = int(pagesize)
+ if self.form.has_key(':startwith'):
+ startwith = int(self.form[':startwith'].value)
+ else:
+ startwith = 0
index = htmltemplate.IndexTemplate(self, self.instance.TEMPLATES, cn)
try:
index.render(filterspec, search_text, filter, columns, sort,
group, show_customization=show_customization,
- show_nodes=show_nodes)
+ show_nodes=show_nodes, pagesize=pagesize, startwith=startwith)
except htmltemplate.MissingTemplateError:
self.basicClassEditPage()
self.pagefoot()
cn = self.form['classname'].value
cl = self.db.classes[cn]
props = self.form['properties'].value.split(',')
+ if cl.labelprop(1) in props:
+ sort = [cl.labelprop(1)]
+ else:
+ sort = props[0]
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():
+ for nodeid in cl.filter(None, {}, sort, []): #cl.list():
w('<tr>')
for name in props:
value = cgi.escape(str(cl.get(nodeid, name)))
default_index_filter = ['status']
default_index_columns = ['activity','status','title','assignedto']
default_index_filterspec = {'status': ['1', '2', '3', '4', '5', '6', '7']}
+ default_pagesize = '50'
def parsePropsFromForm(db, cl, form, nodeid=0, num_re=re.compile('^\d+$')):
'''Pull properties for the given class out of the form.
#
# $Log: not supported by cvs2svn $
+# Revision 1.132 2002/07/08 07:26:14 richard
+# ehem
+#
# Revision 1.131 2002/07/08 06:53:57 richard
# Not sure why the cgi_client had an indexer argument.
#
index e245597fef39718571228c0c14f54736ce0b2ec0..2541ee348dc0bf0a8318f2b95e582859476765c4 100644 (file)
--- a/roundup/htmltemplate.py
+++ b/roundup/htmltemplate.py
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-# $Id: htmltemplate.py,v 1.94 2002-06-27 15:38:53 gmcm Exp $
+# $Id: htmltemplate.py,v 1.95 2002-07-08 15:32:06 gmcm Exp $
__doc__ = """
Template engine.
"""
import os, re, StringIO, urllib, cgi, errno, types, urllib
+
import hyperdb, date
from i18n import _
return _('<input type="submit" name="submit" value="Submit New Entry">')
else:
return _('[Submit: not called from item]')
-
+
def do_classhelp(self, classname, properties, label='?', width='400',
height='400'):
'''pop up a javascript window with class help
return '<a href="javascript:help_window(\'classhelp?classname=%s&' \
'properties=%s\', \'%s\', \'%s\')"><b>(%s)</b></a>'%(classname,
properties, width, height, label)
+ #return '<a href="classhelp?classname=%s&properties=%s" target="classhelp"><b>(%s)</b></a>'%(classname,
+ # properties, label)
#
# INDEX TEMPLATES
#
return ''
if m.group('display'):
command = m.group('command')
- return eval(command, self.globals, self.locals)
+ return eval(command, self.globals, self.locals)
return '*** unhandled match: %s'%str(m.groupdict())
class IndexTemplate(TemplateFunctions):
self.cl = self.db.classes[self.classname]
self.properties = self.cl.getprops()
+ def clear(self):
+ self.db = self.cl = self.properties = None
+ TemplateFunctions.clear(self)
+
+ def buildurl(self, filterspec, search_text, filter, columns, sort, group, pagesize):
+ d = {'pagesize':pagesize, 'pagesize':pagesize, 'classname':self.classname}
+ d['filter'] = ','.join(map(urllib.quote,filter))
+ d['columns'] = ','.join(map(urllib.quote,columns))
+ d['sort'] = ','.join(map(urllib.quote,sort))
+ d['group'] = ','.join(map(urllib.quote,group))
+ tmp = []
+ for col, vals in filterspec.items():
+ vals = ','.join(map(urllib.quote,vals))
+ tmp.append('%s=%s' % (col, vals))
+ d['filters'] = '&'.join(tmp)
+ return '%(classname)s?%(filters)s&:sort=%(sort)s&:filter=%(filter)s&:group=%(group)s&:columns=%(columns)s&:pagesize=%(pagesize)s' % d
+
col_re=re.compile(r'<property\s+name="([^>]+)">')
def render(self, filterspec={}, search_text='', filter=[], columns=[],
sort=[], group=[], show_display_form=1, nodeids=None,
- show_customization=1, show_nodes=1):
+ show_customization=1, show_nodes=1, pagesize=50, startwith=0):
self.filterspec = filterspec
w = self.client.write
- # get the filter template
- try:
- filter_template = open(os.path.join(self.templates,
- self.classname+'.filter')).read()
- all_filters = self.col_re.findall(filter_template)
- except IOError, error:
- if error.errno not in (errno.ENOENT, errno.ESRCH): raise
- filter_template = None
- all_filters = []
# XXX deviate from spec here ...
# load the index section template and figure the default columns from it
if (show_display_form and
self.instance.FILTER_POSITION in ('top and bottom', 'top')):
w('<form onSubmit="return submit_once()" action="%s">\n'%self.classname)
- self.filter_section(filter_template, search_text, filter,
- columns, group, all_filters, all_columns, show_customization)
- # make sure that the sorting doesn't get lost either
- if sort:
- w('<input type="hidden" name=":sort" value="%s">'%
- ','.join(sort))
- w('</form>\n')
-
+ self.filter_section(search_text, filter, columns, group, all_columns, sort, filterspec,
+ pagesize, startwith)
# now display the index section
w('<table width=100% border=0 cellspacing=0 cellpadding=2>\n')
for name in columns:
cname = name.capitalize()
if show_display_form:
- sb = self.sortby(name, filterspec, columns, filter, group, sort)
+ sb = self.sortby(name, filterspec, columns, filter, group, sort, pagesize, startwith)
anchor = "%s?%s"%(self.classname, sb)
w('<td><span class="list-header"><a href="%s">%s</a></span></td>\n'%(
anchor, cname))
matches = self.client.indexer.search(
search_text.split(' '), self.cl)
nodeids = self.cl.filter(matches, filterspec, sort, group)
- for nodeid in nodeids:
+ for nodeid in nodeids[startwith:startwith+pagesize]:
# check for a group heading
if group_names:
this_group = [self.cl.get(nodeid, name, _('[no value]'))
if isinstance(prop, hyperdb.Link):
group_cl = self.db.classes[prop.classname]
key = group_cl.getkey()
+ if key is None:
+ key = group_cl.labelprop()
value = self.cl.get(nodeid, name)
if value is None:
l.append(_('[unselected %(classname)s]')%{
'classname': prop.classname})
else:
- l.append(group_cl.get(self.cl.get(nodeid,
- name), key))
+ l.append(group_cl.get(value, key))
elif isinstance(prop, hyperdb.Multilink):
group_cl = self.db.classes[prop.classname]
key = group_cl.getkey()
self.nodeid = None
w('</table>')
+ # the previous and next links
+ if nodeids:
+ baseurl = self.buildurl(filterspec, search_text, filter, columns, sort, group, pagesize)
+ if startwith > 0:
+ prevurl = '<a href="%s&:startwith=%s"><< Previous page</a>' % \
+ (baseurl, max(0, startwith-pagesize))
+ else:
+ prevurl = ""
+ if startwith + pagesize < len(nodeids):
+ nexturl = '<a href="%s&:startwith=%s">Next page >></a>' % (baseurl, startwith+pagesize)
+ else:
+ nexturl = ""
+ if prevurl or nexturl:
+ w('<table width="100%%"><tr><td width="50%%" align="center">%s</td><td width="50%%" align="center">%s</td></tr></table>' % (prevurl, nexturl))
# display the filter section
if (show_display_form and hasattr(self.instance, 'FILTER_POSITION') and
self.instance.FILTER_POSITION in ('top and bottom', 'bottom')):
w('<form onSubmit="return submit_once()" action="%s">\n'%self.classname)
- self.filter_section(filter_template, search_text, filter,
- columns, group, all_filters, all_columns, show_customization)
- # make sure that the sorting doesn't get lost either
- if sort:
- w('<input type="hidden" name=":sort" value="%s">'%
- ','.join(sort))
- w('</form>\n')
+ self.filter_section(search_text, filter, columns, group, all_columns, sort, filterspec,
+ pagesize, startwith)
- self.db = self.cl = self.properties = None
self.clear()
def node_matches(self, match, colspan):
colspan, ', '.join(file_links)))
- def filter_section(self, template, search_text, filter, columns, group,
- all_filters, all_columns, show_customization):
- w = self.client.write
+ def filter_section(self, search_text, filter, columns, group, all_columns, sort, filterspec,
+ pagesize, startwith):
- # wrap the template in a single table to ensure the whole widget
- # is displayed at once
- w('<table><tr><td>')
-
- if template and filter:
- # display the filter section
- w('<table width=100% border=0 cellspacing=0 cellpadding=2>')
- w('<tr class="location-bar">')
- w(_(' <th align="left" colspan="2">Filter specification...</th>'))
- w('</tr>')
- w('<tr>')
- w('<th class="location-bar">Search terms</th>')
- w('<td><input name="search_text" value="%s" size="50"></td>'%(
- search_text))
- w('</tr>')
- replace = IndexTemplateReplace(self.globals, locals(), filter)
- w(replace.go(template))
- w('<tr class="location-bar"><td width="1%%"> </td>')
- w(_('<td><input type="submit" name="action" value="Redisplay"></td></tr>'))
- w('</table>')
-
- # now add in the filter/columns/group/etc config table form
- w('<input type="hidden" name="show_customization" value="%s">' %
- show_customization )
- w('<table width=100% border=0 cellspacing=0 cellpadding=2>\n')
- names = []
- seen = {}
- for name in all_filters + all_columns:
- if self.properties.has_key(name) and not seen.has_key(name):
- names.append(name)
- seen[name] = 1
- if show_customization:
- action = '-'
- else:
- action = '+'
- # hide the values for filters, columns and grouping in the form
- # if the customization widget is not visible
- for name in names:
- if all_filters and name in filter:
- w('<input type="hidden" name=":filter" value="%s">' % name)
- if all_columns and name in columns:
- w('<input type="hidden" name=":columns" value="%s">' % name)
- if all_columns and name in group:
- w('<input type="hidden" name=":group" value="%s">' % name)
-
- # TODO: The widget style can go into the stylesheet
- w(_('<th align="left" colspan=%s>'
- '<input style="height : 1em; width : 1em; font-size: 12pt" type="submit" name="action" value="%s"> View '
- 'customisation...</th></tr>\n')%(len(names)+1, action))
-
- if not show_customization:
- w('</table>\n')
- return
-
- w('<tr class="location-bar"><th> </th>')
- for name in names:
- w('<th>%s</th>'%name.capitalize())
- w('</tr>\n')
+ sortspec = {}
+ for i in range(len(sort)):
+ mod = ''
+ colnm = sort[i]
+ if colnm[0] == '-':
+ mod = '-'
+ colnm = colnm[1:]
+ sortspec[colnm] = '%d%s' % (i+1, mod)
+
+ startwith = 0
+ w = self.client.write
- # Filter
- if all_filters:
- w(_('<tr><th width="1%" align=right class="location-bar">Filters</th>\n'))
- for name in names:
- if name not in all_filters:
- w('<td> </td>')
- continue
- if name in filter: checked=' checked'
- else: checked=''
- w('<td align=middle>\n')
- w(' <input type="checkbox" name=":filter" value="%s" '
- '%s></td>\n'%(name, checked))
- w('</tr>\n')
-
- # Columns
- if all_columns:
- w(_('<tr><th width="1%" align=right class="location-bar">Columns</th>\n'))
- for name in names:
- if name not in all_columns:
- w('<td> </td>')
- continue
- if name in columns: checked=' checked'
- else: checked=''
- w('<td align=middle>\n')
- w(' <input type="checkbox" name=":columns" value="%s"'
- '%s></td>\n'%(name, checked))
- w('</tr>\n')
-
- # Grouping
- w(_('<tr><th width="1%" align=right class="location-bar">Grouping</th>\n'))
- for name in names:
- if name not in all_columns:
- w('<td> </td>')
- continue
- if name in group: checked=' checked'
- else: checked=''
- w('<td align=middle>\n')
- w(' <input type="checkbox" name=":group" value="%s"'
- '%s></td>\n'%(name, checked))
- w('</tr>\n')
-
- w('<tr class="location-bar"><td width="1%"> </td>')
- w('<td colspan="%s">'%len(names))
- w(_('<input type="submit" name="action" value="Redisplay"></td>'))
- w('</tr>\n')
+ # display the filter section
+ w( '<br>\n')
+ w( '<table border=0 cellspacing=0 cellpadding=0>\n')
+ w( '<tr class="list-header">\n')
+ w(_(' <th align="left" colspan="7">Filter specification...</th>\n'))
+ w( '</tr>\n')
+ # see if we have any indexed properties
+ if self.classname in self.db.config.HEADER_SEARCH_LINKS:
+ #if self.properties.has_key('messages') or self.properties.has_key('files'):
+ w( '<tr class="location-bar">\n')
+ w( ' <td align="right" class="form-label"><b>Search Terms</b></td>\n')
+ w( ' <td> </td>\n')
+ w( ' <td colspan=5 class="form-text"><input type="text" name="search_text" value="%s" size="50"></td>\n' % search_text)
+ w( '</tr>\n')
+ w( '<tr class="location-bar">\n')
+ w( ' <th align="center" width="20%"> </th>\n')
+ w(_(' <th align="center" width="10%">Show</th>\n'))
+ w(_(' <th align="center" width="10%">Group</th>\n'))
+ w(_(' <th align="center" width="10%">Sort</th>\n'))
+ w(_(' <th colspan="3" align="center">Condition</th>\n'))
+ w( '</tr>\n')
+
+ for nm in all_columns:
+ propdescr = self.properties.get(nm, None)
+ if not propdescr:
+ print "hey sysadmin - %s is not a property of %r" % (nm, self.classname)
+ continue
+ w( '<tr class="location-bar">\n')
+ w(_(' <td align="right" class="form-label"><b>%s</b></td>\n' % nm.capitalize()))
+ # show column - can't show multilinks
+ if isinstance(propdescr, hyperdb.Multilink):
+ w(' <td></td>\n')
+ else:
+ checked = columns and nm in columns or 0
+ checked = ('', 'checked')[checked]
+ w(' <td align="center" class="form-text"><input type="checkbox" name=":columns" value="%s" %s></td>\n' % (nm, checked) )
+ # can only group on Link
+ if isinstance(propdescr, hyperdb.Link):
+ checked = group and nm in group or 0
+ checked = ('', 'checked')[checked]
+ w(' <td align="center" class="form-text"><input type="checkbox" name=":group" value="%s" %s></td>\n' % (nm, checked) )
+ else:
+ w(' <td></td>\n')
+ # sort - no sort on Multilinks
+ if isinstance(propdescr, hyperdb.Multilink):
+ w('<td></td>\n')
+ else:
+ val = sortspec.get(nm, '')
+ w('<td align="center" class="form-text"><input type="text" name=":%s_ss" size="3" value="%s"></td>\n' % (nm,val))
+ # condition
+ val = ''
+ if isinstance(propdescr, hyperdb.Link):
+ op = "is in "
+ xtra = '<a href="javascript:help_window(\'classhelp?classname=%s&properties=id,%s\', \'200\', \'400\')"><b>(list)</b></a>'\
+ % (propdescr.classname, self.db.getclass(propdescr.classname).labelprop())
+ val = ','.join(filterspec.get(nm, ''))
+ elif isinstance(propdescr, hyperdb.Multilink):
+ op = "contains "
+ xtra = '<a href="javascript:help_window(\'classhelp?classname=%s&properties=id,%s\', \'200\', \'400\')"><b>(list)</b></a>'\
+ % (propdescr.classname, self.db.getclass(propdescr.classname).labelprop())
+ val = ','.join(filterspec.get(nm, ''))
+ elif isinstance(propdescr, hyperdb.String) and nm != 'id':
+ op = "equals "
+ xtra = ""
+ val = filterspec.get(nm, '')
+ else:
+ w('<td></td><td></td><td></td></tr>\n')
+ continue
+ checked = filter and nm in filter or 0
+ checked = ('', 'checked')[checked]
+ w( ' <td class="form-text"><input type="checkbox" name=":filter" value="%s" %s></td>\n' % (nm, checked))
+ w(_(' <td class="form-label" nowrap>%s</td><td class="form-text" nowrap><input type="text" name=":%s_fs" value="%s" size=50>%s</td>\n' % (op, nm, val, xtra)))
+ w( '</tr>\n')
+ w('<tr class="location-bar">\n')
+ w(' <td colspan=7><hr></td>\n')
+ w('</tr>\n')
+ w('<tr class="location-bar">\n')
+ w(_(' <td align="right" class="form-label">Pagesize</td>\n'))
+ w(' <td colspan=2 align="center" class="form-text"><input type="text" name=":pagesize" size="3" value="%s"></td>\n' % pagesize)
+ w(' <td colspan=4></td>\n')
+ w('</tr>\n')
+ w('<tr class="location-bar">\n')
+ w(_(' <td align="right" class="form-label">Start With</td>\n'))
+ w(' <td colspan=2 align="center" class="form-text"><input type="text" name=":startwith" size="3" value="%s"></td>\n' % startwith)
+ w(' <td colspan=3 align="center" valign="center"><input type="submit" name="Query" value="Redisplay"></td>\n')
+ w(' <td></td>\n')
+ w('</tr>\n')
w('</table>\n')
- # and the outer table
- w('</td></tr></table>')
-
-
- def sortby(self, sort_name, filterspec, columns, filter, group, sort):
+ def sortby(self, sort_name, filterspec, columns, filter, group, sort, pagesize, startwith):
l = []
w = l.append
for k, v in filterspec.items():
w(':filter=%s'%','.join(map(urllib.quote, filter)))
if group:
w(':group=%s'%','.join(map(urllib.quote, group)))
+ w(':pagesize=%s' % pagesize)
+ w(':startwith=%s' % startwith)
m = []
s_dir = ''
for name in sort:
w(':sort=%s'%','.join(m[:2]))
return '&'.join(l)
-
-#
+#
# ITEM TEMPLATES
#
class ItemTemplateReplace:
self.cl = self.db.classes[self.classname]
self.properties = self.cl.getprops()
+ def clear(self):
+ self.db = self.cl = self.properties = None
+ TemplateFunctions.clear(self)
+
def render(self, nodeid):
self.nodeid = nodeid
replace = ItemTemplateReplace(self.globals, locals(), self.cl, nodeid)
w(replace.go(s))
w('</form>')
- self.cl = self.db = self.properties = None
+
self.clear()
self.cl = self.db.classes[self.classname]
self.properties = self.cl.getprops()
+ def clear(self):
+ self.db = self.cl = None
+ TemplateFunctions.clear(self)
+
def render(self, form):
self.form = form
w = self.client.write
replace = ItemTemplateReplace(self.globals, locals(), None, None)
w(replace.go(s))
w('</form>')
- self.cl = self.db = None
+
self.clear()
#
# $Log: not supported by cvs2svn $
+# Revision 1.94 2002/06/27 15:38:53 gmcm
+# Fix the cycles (a clear method, called after render, that removes
+# the bound methods from the globals dict).
+# Use cl.filter instead of cl.list followed by sortfunc. For some
+# backends (Metakit), filter can sort at C speeds, cutting >10 secs
+# off of filling in the <select...> box for assigned_to when you
+# have 600+ users.
+#
# Revision 1.93 2002/06/27 12:05:25 gmcm
# Default labelprops to id.
# In history, make sure there's a .item before making a link / multilink into an href.