--- Mailman/Cgi/admin.py 2005-02-12 21:22:55.000000000 +0100
+++ /var/local/mailman/Mailman/Cgi/admin.py 2005-10-31 00:57:05.000000000 +0100
@@ -28,6 +28,7 @@ import urllib
import signal
from types import *
from string import lowercase, digits
+from urllib import urlencode
from email.Utils import unquote, parseaddr, formataddr
@@ -47,7 +48,6 @@ _ = i18n._
i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
NL = '\n'
-OPTCOLUMNS = 11
try:
True, False
@@ -876,93 +876,97 @@ def membership_options(mlist, subcat, cg
doc.addError(_('Bad regular expression: ') + regexp)
else:
# BAW: There's got to be a more efficient way of doing this!
+ # yes please... this doesn't scale at all
names = [mlist.getMemberName(s) or '' for s in all]
all = [a for n, a in zip(names, all)
if cre.search(n) or cre.search(a)]
- chunkindex = None
- bucket = None
- actionurl = None
+
+ # Do we want to display the language menu?
+ langs = mlist.GetAvailableLanguages()
+ if len(langs) > 1:
+ langdescs = [_(Utils.GetLanguageDescr(lang)) for lang in langs]
+ OPTCOLUMNS = 11
+ else:
+ langs = None
+ OPTCOLUMNS = 10
+ options = [_('unsub'), _('member address
member name'),
+ _('mod'), _('hide'), _('nomail
[reason]'), _('ack'),
+ _('not metoo'), _('nodupes'), _('digest'), _('plain')]
+ if langs:
+ options.append(_('language'))
+
+ starters = []
+
+ # List all members that we want to display
+ # maybe everyone if they are not too many
if len(all) < chunksz:
members = all
else:
- # Split them up alphabetically, and then split the alphabetical
- # listing by chunks
- buckets = {}
- for addr in all:
- members = buckets.setdefault(addr[0].lower(), [])
- members.append(addr)
- # Now figure out which bucket we want
- bucket = None
- qs = {}
- # POST methods, even if their actions have a query string, don't get
- # put into FieldStorage's keys :-(
+ # Retrieve the start address
+ # BAW: POST methods, even if their actions have a query string, don't
+ # get put into FieldStorage's keys :-(
+ start = ''
qsenviron = os.environ.get('QUERY_STRING')
if qsenviron:
qs = cgi.parse_qs(qsenviron)
- bucket = qs.get('letter', 'a')[0].lower()
- if bucket not in digits + lowercase:
- bucket = None
- if not bucket or not buckets.has_key(bucket):
- keys = buckets.keys()
- keys.sort()
- bucket = keys[0]
- members = buckets[bucket]
- action = adminurl + '/members?letter=%s' % bucket
- if len(members) <= chunksz:
- form.set_action(action)
- else:
- i, r = divmod(len(members), chunksz)
- numchunks = i + (not not r * 1)
- # Now chunk them up
- chunkindex = 0
- if qs.has_key('chunk'):
- try:
- chunkindex = int(qs['chunk'][0])
- except ValueError:
- chunkindex = 0
- if chunkindex < 0 or chunkindex > numchunks:
- chunkindex = 0
- members = members[chunkindex*chunksz:(chunkindex+1)*chunksz]
- # And set the action URL
- form.set_action(action + '&chunk=%s' % chunkindex)
- # So now members holds all the addresses we're going to display
- allcnt = len(all)
- if bucket:
- membercnt = len(members)
- usertable.AddRow([Center(Italic(_(
- '%(allcnt)s members total, %(membercnt)s shown')))])
- else:
- usertable.AddRow([Center(Italic(_('%(allcnt)s members total')))])
- usertable.AddCellInfo(usertable.GetCurrentRowIndex(),
+ if qs.has_key('start'):
+ start = qs.get('start')[0].lower()
+
+ # Show start links for every address that is either starting a bucket
+ # or, inside the current bucket, starting a chunk
+ num = 0
+ numtaken = 0
+ members = []
+ if all:
+ bucket = all[0][0].upper() # first bucket, ignore
+ try:
+ currentbucket = start[0].upper()
+ except:
+ currentbucket = ''
+
+ for addr in all:
+ # If the address changes of bucket, or is in the same bucket
+ # as the start parameter, and a multiple of chunksize addresses
+ # write a link to it
+ reason = ''
+ if addr[0].upper() != bucket:
+ bucket = addr[0].upper()
+ reason = '' + bucket + ''
+ num = 0
+ elif num % chunksz == 0 and bucket == currentbucket:
+ reason = '' + str(num/chunksz) + ''
+ if reason:
+ if start == addr:
+ link = reason
+ else:
+ url = adminurl + '/members?' + urlencode({'start':addr})
+ link = Link(url, reason).Format()
+ starters.append(link)
+ num += 1
+
+ # If the address is after the START value, take it for display
+ # but don't take more than the max chunksize
+ if addr.lower() >= start and numtaken < chunksz:
+ numtaken += 1
+ members.append(addr)
+
+
+ # Add the start links
+ if starters:
+ joiner = ' ' + '\n'
+ usertable.AddRow([Center(joiner.join(starters))])
+ usertable.AddCellInfo(usertable.GetCurrentRowIndex(),
usertable.GetCurrentCellIndex(),
colspan=OPTCOLUMNS,
bgcolor=mm_cfg.WEB_ADMINITEM_COLOR)
- # Add the alphabetical links
- if bucket:
- cells = []
- for letter in digits + lowercase:
- if not buckets.get(letter):
- continue
- url = adminurl + '/members?letter=%s' % letter
- if letter == bucket:
- show = Bold('[%s]' % letter.upper()).Format()
- else:
- show = letter.upper()
- cells.append(Link(url, show).Format())
- joiner = ' '*2 + '\n'
- usertable.AddRow([Center(joiner.join(cells))])
+
+ # So now members holds all the addresses we're going to display
+ usertable.AddRow('')
usertable.AddCellInfo(usertable.GetCurrentRowIndex(),
usertable.GetCurrentCellIndex(),
colspan=OPTCOLUMNS,
bgcolor=mm_cfg.WEB_ADMINITEM_COLOR)
- usertable.AddRow([Center(h) for h in (_('unsub'),
- _('member address
member name'),
- _('mod'), _('hide'),
- _('nomail
[reason]'),
- _('ack'), _('not metoo'),
- _('nodupes'),
- _('digest'), _('plain'),
- _('language'))])
+ usertable.AddRow([Center(h) for h in options])
rowindex = usertable.GetCurrentRowIndex()
for i in range(OPTCOLUMNS):
usertable.AddCellInfo(rowindex, i, bgcolor=mm_cfg.WEB_ADMINITEM_COLOR)
@@ -978,6 +982,8 @@ def membership_options(mlist, subcat, cg
MemberAdaptor.BYADMIN : _('A'),
MemberAdaptor.BYBOUNCE: _('B'),
}
+ # memorize the regular-or-digest list
+ regular_or_digest = mlist.getRegularMemberKeys()
# Now populate the rows
for addr in members:
link = Link(mlist.GetOptionsURL(addr, obscure=1),
@@ -1021,8 +1027,9 @@ def membership_options(mlist, subcat, cg
# This code is less efficient than the original which did a has_key on
# the underlying dictionary attribute. This version is slower and
# less memory efficient. It points to a new MemberAdaptor interface
- # method.
- if addr in mlist.getRegularMemberKeys():
+ # method. (Modified by Fil to "cache" the result - useful for
+ # MySQLMemberAdaptor)
+ if addr in regular_or_digest:
cells.append(Center(CheckBox(addr + '_digest', 'off', 0).Format()))
else:
cells.append(Center(CheckBox(addr + '_digest', 'on', 1).Format()))
@@ -1035,13 +1042,12 @@ def membership_options(mlist, subcat, cg
cells.append(Center(CheckBox('%s_plain' % addr, value, checked)))
# User's preferred language
langpref = mlist.getMemberLanguage(addr)
- langs = mlist.GetAvailableLanguages()
- langdescs = [_(Utils.GetLanguageDescr(lang)) for lang in langs]
- try:
- selected = langs.index(langpref)
- except ValueError:
- selected = 0
- cells.append(Center(SelectOptions(addr + '_language', langs,
+ if langs:
+ try:
+ selected = langs.index(langpref)
+ except ValueError:
+ selected = 0
+ cells.append(Center(SelectOptions(addr + '_language', langs,
langdescs, selected)).Format())
usertable.AddRow(cells)
# Add the usertable and a legend
@@ -1105,23 +1111,6 @@ def membership_options(mlist, subcat, cg
_('Click here to include the legend for this table.')))
container.AddItem(Center(usertable))
- # There may be additional chunks
- if chunkindex is not None:
- buttons = []
- url = adminurl + '/members?%sletter=%s&' % (addlegend, bucket)
- footer = _('''
To view more members, click on the appropriate - range listed below:''') - chunkmembers = buckets[bucket] - last = len(chunkmembers) - for i in range(numchunks): - if i == chunkindex: - continue - start = chunkmembers[i*chunksz] - end = chunkmembers[min((i+1)*chunksz, last)-1] - link = Link(url + 'chunk=%d' % i, _('from %(start)s to %(end)s')) - buttons.append(link) - buttons = UnorderedList(*buttons) - container.AddItem(footer + buttons.Format() + '
') return container