Pavan Koli has proposed merging lp:~pskoli93/postorius/Add-a-single-member into
lp:postorius.
Requested reviews:
Mailman Coders (mailman-coders)
Sumana Harihareswara (sumanah)
Related bugs:
Bug #1444699 in Postorius: "I can't add a single member (non-owner,
non-moderator) from the Members page."
https://bugs.launchpad.net/postorius/+bug/1444699
For more details, see:
https://code.launchpad.net/~pskoli93/postorius/Add-a-single-member/+merge/256625
Option to add a single member from the members page has been included in this
branch. Made the changes required to support translations.
--
Your team Mailman Coders is requested to review the proposed merge of
lp:~pskoli93/postorius/Add-a-single-member into lp:postorius.
=== modified file 'src/postorius/forms.py'
--- src/postorius/forms.py 2015-04-16 16:24:11 +0000
+++ src/postorius/forms.py 2015-04-17 08:35:52 +0000
@@ -91,6 +91,14 @@
'required': _('Please enter an email adddress.'),
'invalid': _('Please enter a valid email adddress.')})
+class NewSubscriberForm(forms.Form):
+
+ """Add a subscriber."""
+ subscriber_email = forms.EmailField(
+ label=_('Email Address'),
+ error_messages={
+ 'required': _('Please enter an email adddress.'),
+ 'invalid': _('Please enter a valid email adddress.')})
class ListNew(FieldsetForm):
@@ -250,30 +258,30 @@
choices=autorespond_choices,
widget=forms.RadioSelect,
label=_('Autorespond to list owner'),
- help_text=(
+ help_text=_(
'Should Mailman send an auto-response to emails sent to the '
'-owner address?'))
autoresponse_owner_text = forms.CharField(
label=_('Autoresponse owner text'),
widget=forms.Textarea(),
required=False,
- help_text=('Auto-response text to send to -owner emails.'))
+ help_text=_('Auto-response text to send to -owner emails.'))
autorespond_postings = forms.ChoiceField(
choices=autorespond_choices,
widget=forms.RadioSelect,
label=_('Autorespond postings'),
- help_text=(
+ help_text=_(
'Should Mailman send an auto-response to mailing list posters?'))
autoresponse_postings_text = forms.CharField(
label=_('Autoresponse postings text'),
widget=forms.Textarea(),
required=False,
- help_text=('Auto-response text to send to mailing list posters.'))
+ help_text=_('Auto-response text to send to mailing list posters.'))
autorespond_requests = forms.ChoiceField(
choices=autorespond_choices,
widget=forms.RadioSelect,
label=_('Autorespond requests'),
- help_text=(
+ help_text=_(
'Should Mailman send an auto-response to emails sent to the '
'-request address? If you choose yes, decide whether you want '
'Mailman to discard the original email, or forward it on to the '
@@ -282,10 +290,10 @@
label=_('Autoresponse request text'),
widget=forms.Textarea(),
required=False,
- help_text=('Auto-response text to send to -request emails.'))
+ help_text=_('Auto-response text to send to -request emails.'))
autoresponse_grace_period = forms.CharField(
label=_('Autoresponse grace period'),
- help_text=(
+ help_text=_(
'Number of days between auto-responses to either the mailing list '
'or -request/-owner address from the same poster. Set to zero '
'(or negative) for no grace period (i.e. auto-respond to every '
@@ -299,7 +307,7 @@
choices=((True, _('Yes')), (False, _('No'))),
widget=forms.RadioSelect,
label=_('Advertise the existence of this list?'),
- help_text=(
+ help_text=_(
'Choose whether to include this list on the list of all lists'))
filter_content = forms.TypedChoiceField(
coerce=lambda x: x == 'True',
@@ -307,7 +315,7 @@
widget=forms.RadioSelect,
required=False,
label=_('Filter content'),
- help_text=(
+ help_text=_(
'Should Mailman filter the content of list traffic according to '
'the settings below?'))
collapse_alternatives = forms.TypedChoiceField(
@@ -316,7 +324,7 @@
widget=forms.RadioSelect,
required=False,
label=_('Collapse alternatives'),
- help_text=(
+ help_text=_(
'Should Mailman collapse multipart/alternative to its first part '
'content?'))
convert_html_to_plaintext = forms.TypedChoiceField(
@@ -325,7 +333,7 @@
widget=forms.RadioSelect,
required=False,
label=_('Convert html to plaintext'),
- help_text=(
+ help_text=_(
'Should Mailman convert text/html parts to plain text? This '
'conversion happens after MIME attachments have been stripped.'))
action_choices = (
@@ -341,7 +349,7 @@
'required': _("Please choose a default member action.")},
required=True,
choices=action_choices,
- help_text=(
+ help_text=_(
'Default action to take when a member posts to the list. '
'Hold -- This holds the message for approval by the list '
'moderators.'
@@ -360,14 +368,14 @@
'required': _("Please choose a default non-member action.")},
required=True,
choices=action_choices,
- help_text=(
+ help_text=_(
'When a post from a non-member is received, the message\'s sender '
'is matched against the list of explicitly accepted, held, '
'rejected (bounced), and discarded addresses. '
'If no match is found, then this action is taken.'))
description = forms.CharField(
label=_('Description'),
- help_text=(
+ help_text=_(
'This description is used when the mailing list is listed with '
'other mailing lists, or in headers, and so forth. It should be '
'as succinct as you can get it, while still identifying what the '
@@ -375,7 +383,7 @@
widget=forms.Textarea())
digest_size_threshold = forms.DecimalField(
label=_('Digest size threshold'),
- help_text=('How big in Kb should a digest be before it gets sent out?')
+ help_text=_('How big in Kb should a digest be before it gets sent out?')
)
# Informational
# digest_last_sent_at = forms.IntegerField(
@@ -404,7 +412,7 @@
error_messages={'required': _('Please a domain name'),
'invalid': _('Please enter a valid domain name.')},
required=True,
- help_text=(
+ help_text=_(
"The \"host_name\" is the preferred name for email to "
"'mailman-related addresses on this host, and generally should be "
"the mail host's exchanger address, if any. This setting can be "
@@ -432,7 +440,7 @@
("default-owner-pipeline", _("default-owner-pipeline")),
("default-posting-pipeline", _("default-posting-pipeline")),
("virgin", _("virgin"))),
- help_text=(
+ help_text=_(
'Type of pipeline you want to use for this mailing list')
)
@@ -445,7 +453,7 @@
# )
display_name = forms.CharField(
label=_('Display name'),
- help_text=('Display name is the name shown in the web interface.')
+ help_text=_('Display name is the name shown in the web interface.')
)
subject_prefix = forms.CharField(
label=_('Subject prefix'),
@@ -460,7 +468,7 @@
("no_munging", _("No Munging")),
("point_to_list", _("Reply goes to list")),
("explicit_header", _("Explicit Reply-to header set"))),
- help_text=(
+ help_text=_(
'Where are replies to list messages directed? No Munging is '
'strongly recommended for most mailing lists. \nThis option '
'controls what Mailman does to the Reply-To: header in messages '
@@ -503,7 +511,7 @@
widget=forms.RadioSelect,
required=False,
label=_('Send welcome message'),
- help_text=(
+ help_text=_(
'Send welcome message to newly subscribed members? '
'Turn this off only if you plan on subscribing people manually '
'and don\'t want them to know that you did so. This option is '
@@ -523,7 +531,7 @@
widget=forms.Textarea(),
label=_("Acceptable aliases"),
required=False,
- help_text=(
+ help_text=_(
'Alias names which qualify as explicit to or cc destination names '
'for this list. Alternate addresses that are acceptable when '
'`require_explicit_destination\' is enabled. This option takes a '
@@ -535,7 +543,7 @@
widget=forms.RadioSelect(choices=choices),
required=False,
label=_('Admin immed notify'),
- help_text=(
+ help_text=_(
'Should the list moderators get immediate notice of new requests, '
'as well as daily notices about collected ones? List moderators '
'(and list administrators) are sent daily reminders of requests '
@@ -547,14 +555,14 @@
widget=forms.RadioSelect(choices=choices),
required=False,
label=_('Notify admin of membership changes'),
- help_text=(
+ help_text=_(
'Should administrator get notices of subscribes and unsubscribes?'
))
administrivia = forms.BooleanField(
widget=forms.RadioSelect(choices=choices),
required=False,
label=_('Administrivia'),
- help_text=(
+ help_text=_(
'Administrivia tests will check postings to see whether it\'s '
'really meant as an administrative request (like subscribe, '
'unsubscribe, etc), and will add it to the the administrative '
@@ -566,7 +574,7 @@
widget=forms.RadioSelect,
required=False,
label=_('Anonymous list'),
- help_text=(
+ help_text=_(
'Hide the sender of a message, replacing it with the list address '
'(Removes From, Sender and Reply-To fields)'))
# Informational field, not needed.
@@ -857,7 +865,7 @@
password = cleaned_data.get("password")
password_repeat = cleaned_data.get("password_repeat")
if password != password_repeat:
- raise forms.ValidationError("Passwords must be identical.")
+ raise forms.ValidationError(_("Passwords must be identical."))
return cleaned_data
=== modified file 'src/postorius/templates/postorius/lists/members.html'
--- src/postorius/templates/postorius/lists/members.html 2015-04-16 18:19:33 +0000
+++ src/postorius/templates/postorius/lists/members.html 2015-04-17 08:35:52 +0000
@@ -65,6 +65,17 @@
</table>
<h2>{% trans "Members" %}</h2>
+ <form action="{% url 'list_members' list.fqdn_listname %}" method="POST" class="form-inline">{% csrf_token %}
+ <label for="bla">{% trans 'Email Address' %}</label>
+ {{ subscriber_form.subscriber_email }}
+ <button type="submit" class="btn">{% trans 'Add Member' %}</button>
+ </form>
+ <thead>
+ <tr>
+ <th>{% trans 'Address' %}</th>
+ <th> </th>
+ </tr>
+ </thead>
<table class="table table-bordered table-striped">
<thead>
<tr>
=== modified file 'src/postorius/views/list.py'
--- src/postorius/views/list.py 2015-04-16 18:19:33 +0000
+++ src/postorius/views/list.py 2015-04-17 08:35:52 +0000
@@ -29,7 +29,7 @@
from django.core.validators import validate_email
from django.core.exceptions import ValidationError
from django.utils.decorators import method_decorator
-from django.utils.translation import gettext as _
+from django.utils.translation import ugettext as _
from urllib2 import HTTPError
from postorius import utils
@@ -80,22 +80,38 @@
% request.POST['moderator_email']))
except HTTPError as e:
messages.error(request, _(e.msg))
+ if 'subscriber_email' in request.POST:
+ subscriber_form = NewSubscriberForm(request.POST)
+ if subscriber_form.is_valid():
+ try:
+ self.mailing_list.subscribe(
+ subscriber_form.cleaned_data['subscriber_email'])
+ messages.success(
+ request, _('%s has been subscribed.'
+ % request.POST['subscriber_email']))
+ except HTTPError as e:
+ messages.error(request,_(e.msg))
+ return redirect('list_members', self.mailing_list.list_id)
owner_form = NewOwnerForm()
moderator_form = NewModeratorForm()
+ subscriber_form = NewSubscriberForm()
return render_to_response('postorius/lists/members.html',
{'list': self.mailing_list,
'owner_form': owner_form,
- 'moderator_form': moderator_form},
+ 'moderator_form': moderator_form,
+ 'subscriber_form': subscriber_form},
context_instance=RequestContext(request))
@method_decorator(list_owner_required)
def get(self, request, list_id, page=1):
owner_form = NewOwnerForm()
moderator_form = NewModeratorForm()
+ subscriber_form = NewSubscriberForm()
return render_to_response('postorius/lists/members.html',
{'list': self.mailing_list,
'owner_form': owner_form,
- 'moderator_form': moderator_form},
+ 'moderator_form': moderator_form,
+ 'subscriber_form': subscriber_form},
context_instance=RequestContext(request))
@@ -115,9 +131,9 @@
preferences[key] = preferences_form.cleaned_data[key]
preferences.save()
messages.success(
- request, 'The member\'s preferences have been updated.')
+ request, _('The member\'s preferences have been updated.'))
else:
- messages.error(request, 'Something went wrong.')
+ messages.error(request, _('Something went wrong.'))
# this is a bit silly, since we already have the preferences,
# but I want to be sure we don't show stale data.
@@ -203,11 +219,11 @@
email = request.POST.get('email')
self.mailing_list.subscribe(email)
messages.success(
- request, 'You are subscribed to %s.' %
- self.mailing_list.fqdn_listname)
+ request, _('You are subscribed to %s.' %
+ self.mailing_list.fqdn_listname))
else:
- messages.error(request, 'Something went wrong. '
- 'Please try again.')
+ messages.error(request, _('Something went wrong. '
+ 'Please try again.'))
except MailmanApiError:
return utils.render_api_error(request)
except HTTPError, e:
@@ -225,8 +241,8 @@
try:
self.mailing_list.unsubscribe(email)
messages.success(request,
- '%s has been unsubscribed from this list.' %
- email)
+ _('%s has been unsubscribed from this list.' %
+ email))
except MailmanApiError:
return utils.render_api_error(request)
except ValueError, e:
@@ -247,7 +263,7 @@
def post(self, request, *args, **kwargs):
form = ListMassSubscription(request.POST)
if not form.is_valid():
- messages.error(request, 'Please fill out the form correctly.')
+ messages.error(request, _('Please fill out the form correctly.'))
else:
emails = request.POST["emails"].splitlines()
for email in emails:
@@ -256,16 +272,16 @@
self.mailing_list.subscribe(address=email)
messages.success(
request,
- 'The address %s has been subscribed to %s.' %
- (email, self.mailing_list.fqdn_listname))
+ _('The address %s has been subscribed to %s.' %
+ (email, self.mailing_list.fqdn_listname)))
except MailmanApiError:
return utils.render_api_error(request)
except HTTPError, e:
messages.error(request, e)
except ValidationError:
messages.error(request,
- 'The email address %s is not valid.' %
- email)
+ _('The email address %s is not valid.' %
+ email))
return redirect('mass_subscribe', self.mailing_list.list_id)
@@ -284,7 +300,7 @@
def post(self, request, *args, **kwargs):
form = ListMassRemoval(request.POST)
if not form.is_valid():
- messages.error(request, 'Please fill out the form correctly.')
+ messages.error(request, _('Please fill out the form correctly.'))
else:
emails = request.POST["emails"].splitlines()
for email in emails:
@@ -292,8 +308,8 @@
validate_email(email)
self.mailing_list.unsubscribe(email.lower())
messages.success(request,
- 'The address %s has been unsubscribed from %s.' %
- (email, self.mailing_list.fqdn_listname))
+ _('The address %s has been unsubscribed from %s.' %
+ (email, self.mailing_list.fqdn_listname)))
except MailmanApiError:
return utils.render_api_error(request)
except HTTPError, e:
@@ -302,8 +318,8 @@
messages.error(request, e)
except ValidationError:
messages.error(request,
- 'The email address %s is not valid.' %
- email)
+ _('The email address %s is not valid.' %
+ email))
return redirect('mass_removal', self.mailing_list.list_id)
@@ -561,7 +577,7 @@
except HTTPError, e:
messages.error(request, e.msg)
return redirect('list_held_messages', the_list.list_id)
- messages.success(request, 'The message has been accepted.')
+ messages.success(request, _('The message has been accepted.'))
return redirect('list_held_messages', the_list.list_id)
@@ -577,7 +593,7 @@
except HTTPError, e:
messages.error(request, e.msg)
return redirect('list_held_messages', the_list.list_id)
- messages.success(request, 'The message has been discarded.')
+ messages.success(request, _('The message has been discarded.'))
return redirect('list_held_messages', the_list.list_id)
@@ -593,7 +609,7 @@
except HTTPError, e:
messages.error(request, e.msg)
return redirect('list_held_messages', the_list.list_id)
- messages.success(request, 'The message has been deferred.')
+ messages.success(request, _('The message has been deferred.'))
return redirect('list_held_messages', the_list.list_id)
@@ -609,7 +625,7 @@
except HTTPError, e:
messages.error(request, e.msg)
return redirect('list_held_messages', the_list.list_id)
- messages.success(request, 'The message has been rejected.')
+ messages.success(request, _('The message has been rejected.'))
return redirect('list_held_messages', the_list.list_id)
@@ -767,14 +783,14 @@
try:
mlist = List.objects.get_or_404(fqdn_listname=list_id)
if len(mlist.members) == 0:
- messages.error(request, 'No member is subscribed to the list currently.')
+ messages.error(request, _('No member is subscribed to the list currently.'))
return redirect('mass_removal', mlist.list_id)
if request.method == 'POST':
try:
for names in mlist.members:
mlist.unsubscribe(names.email)
messages.success(request,
- 'All members have been unsubscribed from the list.')
+ _('All members have been unsubscribed from the list.'))
return redirect('list_members', mlist.list_id)
except Exception, e:
messages.error(request, e)
_______________________________________________
Mailman-coders mailing list
[email protected]
https://mail.python.org/mailman/listinfo/mailman-coders