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>&nbsp;</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

Reply via email to