Skip to content

Commit c54e5a1

Browse files
author
Gordon B. McMillan
committed
Pagination of index pages.
New search form.
1 parent 871f14b commit c54e5a1

File tree

2 files changed

+281
-193
lines changed

2 files changed

+281
-193
lines changed

roundup/cgi_client.py

Lines changed: 112 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
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.132 2002-07-08 07:26:14 richard Exp $
18+
# $Id: cgi_client.py,v 1.133 2002-07-08 15:32:05 gmcm Exp $
1919

2020
__doc__ = """
2121
WWW request handler (also used in the stand-alone server).
@@ -133,6 +133,7 @@ def make_index_link(self, name):
133133
d[':group'] = ','.join(map(urllib.quote, spec['GROUP']))
134134
d[':filter'] = ','.join(map(urllib.quote, spec['FILTER']))
135135
d[':columns'] = ','.join(map(urllib.quote, spec['COLUMNS']))
136+
d[':pagesize'] = spec.get('PAGESIZE','50')
136137

137138
# snarf the filterspec
138139
filterspec = spec['FILTERSPEC'].copy()
@@ -257,7 +258,7 @@ def pagehead(self, title, message=None):
257258
<tr class="location-bar">
258259
<td align=left>%(links)s</td>
259260
<td align=right>%(user_info)s</td>
260-
</table>
261+
</table><br>
261262
''')%locals())
262263

263264
def pagefoot(self):
@@ -306,34 +307,67 @@ def index_arg(self, arg):
306307
return arg.value.split(',')
307308
return []
308309

310+
def index_sort(self):
311+
# first try query string
312+
x = self.index_arg(':sort')
313+
if x:
314+
return x
315+
# nope - get the specs out of the form
316+
specs = []
317+
for colnm in self.db.getclass(self.classname).getprops().keys():
318+
desc = ''
319+
try:
320+
spec = self.form[':%s_ss' % colnm]
321+
except KeyError:
322+
continue
323+
spec = spec.value
324+
if spec:
325+
if spec[-1] == '-':
326+
desc='-'
327+
spec = spec[0]
328+
specs.append((int(spec), colnm, desc))
329+
specs.sort()
330+
x = []
331+
for _, colnm, desc in specs:
332+
x.append('%s%s' % (desc, colnm))
333+
return x
334+
309335
def index_filterspec(self, filter):
310336
''' pull the index filter spec from the form
311337
312338
Links and multilinks want to be lists - the rest are straight
313339
strings.
314340
'''
315-
props = self.db.classes[self.classname].getprops()
316-
# all the form args not starting with ':' are filters
317341
filterspec = {}
318-
for key in self.form.keys():
319-
if key[0] == ':': continue
320-
if not props.has_key(key): continue
321-
if key not in filter: continue
322-
prop = props[key]
323-
value = self.form[key]
324-
if (isinstance(prop, hyperdb.Link) or
325-
isinstance(prop, hyperdb.Multilink)):
326-
if type(value) == type([]):
327-
value = [arg.value for arg in value]
342+
props = self.db.classes[self.classname].getprops()
343+
for colnm in filter:
344+
widget = ':%s_fs' % colnm
345+
try:
346+
val = self.form[widget]
347+
except KeyError:
348+
try:
349+
val = self.form[colnm]
350+
except KeyError:
351+
# they checked the filter box but didn't enter a value
352+
continue
353+
propdescr = props.get(colnm, None)
354+
if propdescr is None:
355+
print "huh? %r is in filter & form, but not in Class!" % colnm
356+
raise "butthead programmer"
357+
if (isinstance(propdescr, hyperdb.Link) or
358+
isinstance(propdescr, hyperdb.Multilink)):
359+
if type(val) == type([]):
360+
val = [arg.value for arg in val]
328361
else:
329-
value = value.value.split(',')
330-
l = filterspec.get(key, [])
331-
l = l + value
332-
filterspec[key] = l
362+
val = val.value.split(',')
363+
l = filterspec.get(colnm, [])
364+
l = l + val
365+
filterspec[colnm] = l
333366
else:
334-
filterspec[key] = value.value
367+
filterspec[colnm] = val.value
368+
335369
return filterspec
336-
370+
337371
def customization_widget(self):
338372
''' The customization widget is visible by default. The widget
339373
visibility is remembered by show_customization. Visibility
@@ -355,11 +389,12 @@ def customization_widget(self):
355389
default_index_filter = ['status']
356390
default_index_columns = ['id','activity','title','status','assignedto']
357391
default_index_filterspec = {'status': ['1', '2', '3', '4', '5', '6', '7']}
392+
default_pagesize = '50'
358393

359394
def _get_customisation_info(self):
360395
# see if the web has supplied us with any customisation info
361396
defaults = 1
362-
for key in ':sort', ':group', ':filter', ':columns':
397+
for key in ':sort', ':group', ':filter', ':columns', ':pagesize':
363398
if self.form.has_key(key):
364399
defaults = 0
365400
break
@@ -373,6 +408,7 @@ def _get_customisation_info(self):
373408
filter = d['FILTER']
374409
columns = d['COLUMNS']
375410
filterspec = d['FILTERSPEC']
411+
pagesize = d.get('PAGESIZE', '50')
376412

377413
else:
378414
# nope - fall back on the old way of doing it
@@ -382,43 +418,56 @@ def _get_customisation_info(self):
382418
filter = self.default_index_filter
383419
columns = self.default_index_columns
384420
filterspec = self.default_index_filterspec
421+
pagesize = self.default_pagesize
385422
else:
386423
# make list() extract the info from the CGI environ
387424
self.classname = 'issue'
388-
sort = group = filter = columns = filterspec = None
389-
return columns, filter, group, sort, filterspec
425+
sort = group = filter = columns = filterspec = pagesize = None
426+
return columns, filter, group, sort, filterspec, pagesize
390427

391428
def index(self):
392429
''' put up an index - no class specified
393430
'''
394-
columns, filter, group, sort, filterspec = \
431+
columns, filter, group, sort, filterspec, pagesize = \
395432
self._get_customisation_info()
396433
return self.list(columns=columns, filter=filter, group=group,
397-
sort=sort, filterspec=filterspec)
434+
sort=sort, filterspec=filterspec, pagesize=pagesize)
398435

399436
def searchnode(self):
400-
columns, filter, group, sort, filterspec = \
437+
columns, filter, group, sort, filterspec, pagesize = \
401438
self._get_customisation_info()
402-
show_nodes = 1
403-
if len(self.form.keys()) == 0:
404-
# get the default search filters from instance_config
405-
if hasattr(self.instance, 'SEARCH_FILTERS'):
406-
for f in self.instance.SEARCH_FILTERS:
407-
spec = getattr(self.instance, f)
408-
if spec['CLASS'] == self.classname:
409-
filter = spec['FILTER']
410-
411-
show_nodes = 0
412-
show_customization = 1
413-
return self.list(columns=columns, filter=filter, group=group,
414-
sort=sort, filterspec=filterspec,
415-
show_customization=show_customization, show_nodes=show_nodes)
416-
439+
## show_nodes = 1
440+
## if len(self.form.keys()) == 0:
441+
## # get the default search filters from instance_config
442+
## if hasattr(self.instance, 'SEARCH_FILTERS'):
443+
## for f in self.instance.SEARCH_FILTERS:
444+
## spec = getattr(self.instance, f)
445+
## if spec['CLASS'] == self.classname:
446+
## filter = spec['FILTER']
447+
##
448+
## show_nodes = 0
449+
## show_customization = 1
450+
## return self.list(columns=columns, filter=filter, group=group,
451+
## sort=sort, filterspec=filterspec,
452+
## show_customization=show_customization, show_nodes=show_nodes,
453+
## pagesize=pagesize)
454+
cn = self.classname
455+
self.pagehead(_('%(instancename)s: Index of %(classname)s')%{
456+
'classname': cn, 'instancename': self.instance.INSTANCE_NAME})
457+
index = htmltemplate.IndexTemplate(self, self.instance.TEMPLATES, cn)
458+
self.write('<form onSubmit="return submit_once()" action="%s">\n'%self.classname)
459+
all_columns = self.db.getclass(cn).getprops().keys()
460+
all_columns.sort()
461+
index.filter_section('', filter, columns, group, all_columns, sort,
462+
filterspec, pagesize, 0)
463+
self.pagefoot()
464+
index.db = index.cl = index.properties = None
465+
index.clear()
417466

418467
# XXX deviates from spec - loses the '+' (that's a reserved character
419468
# in URLS
420469
def list(self, sort=None, group=None, filter=None, columns=None,
421-
filterspec=None, show_customization=None, show_nodes=1):
470+
filterspec=None, show_customization=None, show_nodes=1, pagesize=None):
422471
''' call the template index with the args
423472
424473
:sort - sort by prop name, optionally preceeded with '-'
@@ -435,7 +484,7 @@ def list(self, sort=None, group=None, filter=None, columns=None,
435484
cl = self.db.classes[cn]
436485
self.pagehead(_('%(instancename)s: Index of %(classname)s')%{
437486
'classname': cn, 'instancename': self.instance.INSTANCE_NAME})
438-
if sort is None: sort = self.index_arg(':sort')
487+
if sort is None: sort = self.index_sort()
439488
if group is None: group = self.index_arg(':group')
440489
if filter is None: filter = self.index_arg(':filter')
441490
if columns is None: columns = self.index_arg(':columns')
@@ -446,12 +495,22 @@ def list(self, sort=None, group=None, filter=None, columns=None,
446495
search_text = self.form['search_text'].value
447496
else:
448497
search_text = ''
498+
if pagesize is None:
499+
if self.form.has_key(':pagesize'):
500+
pagesize = self.form[':pagesize'].value
501+
else:
502+
pagesize = '50'
503+
pagesize = int(pagesize)
504+
if self.form.has_key(':startwith'):
505+
startwith = int(self.form[':startwith'].value)
506+
else:
507+
startwith = 0
449508

450509
index = htmltemplate.IndexTemplate(self, self.instance.TEMPLATES, cn)
451510
try:
452511
index.render(filterspec, search_text, filter, columns, sort,
453512
group, show_customization=show_customization,
454-
show_nodes=show_nodes)
513+
show_nodes=show_nodes, pagesize=pagesize, startwith=startwith)
455514
except htmltemplate.MissingTemplateError:
456515
self.basicClassEditPage()
457516
self.pagefoot()
@@ -550,13 +609,17 @@ def classhelp(self):
550609
cn = self.form['classname'].value
551610
cl = self.db.classes[cn]
552611
props = self.form['properties'].value.split(',')
612+
if cl.labelprop(1) in props:
613+
sort = [cl.labelprop(1)]
614+
else:
615+
sort = props[0]
553616

554617
w('<table border=1 cellspacing=0 cellpaddin=2>')
555618
w('<tr>')
556619
for name in props:
557620
w('<th align=left>%s</th>'%name)
558621
w('</tr>')
559-
for nodeid in cl.list():
622+
for nodeid in cl.filter(None, {}, sort, []): #cl.list():
560623
w('<tr>')
561624
for name in props:
562625
value = cgi.escape(str(cl.get(nodeid, name)))
@@ -1314,6 +1377,7 @@ class ExtendedClient(Client):
13141377
default_index_filter = ['status']
13151378
default_index_columns = ['activity','status','title','assignedto']
13161379
default_index_filterspec = {'status': ['1', '2', '3', '4', '5', '6', '7']}
1380+
default_pagesize = '50'
13171381

13181382
def parsePropsFromForm(db, cl, form, nodeid=0, num_re=re.compile('^\d+$')):
13191383
'''Pull properties for the given class out of the form.
@@ -1395,6 +1459,9 @@ def parsePropsFromForm(db, cl, form, nodeid=0, num_re=re.compile('^\d+$')):
13951459

13961460
#
13971461
# $Log: not supported by cvs2svn $
1462+
# Revision 1.132 2002/07/08 07:26:14 richard
1463+
# ehem
1464+
#
13981465
# Revision 1.131 2002/07/08 06:53:57 richard
13991466
# Not sure why the cgi_client had an indexer argument.
14001467
#

0 commit comments

Comments
 (0)