← Back to team overview

launchpad-reviewers team mailing list archive

Re: [Merge] lp:~thomir/launchpad/devel-fix-editemails-link into lp:launchpad

 

Review: Needs Fixing code

Just a few super-trivial niggles!

Diff comments:

> === modified file 'lib/lp/registry/browser/configure.zcml'
> --- lib/lp/registry/browser/configure.zcml	2015-02-06 13:37:58 +0000
> +++ lib/lp/registry/browser/configure.zcml	2015-02-26 21:41:09 +0000
> @@ -1009,6 +1009,14 @@
>                  name="+editemails"
>                  template="../templates/person-editemails.pt"/>
>          </browser:pages>
> +        <browser:pages
> +            for="lp.registry.interfaces.person.IPerson"
> +            permission="launchpad.Edit"
> +            class="lp.registry.browser.person.PersonEditMailingListsView">
> +            <browser:page
> +                name="+editmailinglists"
> +                template="../templates/person-editmailinglists.pt"/>
> +        </browser:pages>

There's only one page using this class, so you can just specify for/permission/class in the <browser:page> directly. No need for the <browser:pages> wrapper.

>          <browser:page
>              name="+oauth-tokens"
>              for="lp.registry.interfaces.person.IPerson"
> 
> === modified file 'lib/lp/registry/browser/person.py'
> --- lib/lp/registry/browser/person.py	2015-02-06 13:37:58 +0000
> +++ lib/lp/registry/browser/person.py	2015-02-26 21:41:09 +0000
> @@ -723,6 +723,7 @@
>          'branding',
>          'editemailaddresses',
>          'editlanguages',
> +        'editmailinglists',
>          'editircnicknames',
>          'editjabberids',
>          'editsshkeys',
> @@ -782,6 +783,12 @@
>          return Link(target, text, icon='edit')
>  
>      @enabled_with_permission('launchpad.Edit')
> +    def editmailinglists(self):
> +        target = '+editmailinglists'
> +        text = 'Manage mailing list subscriptions'
> +        return Link(target, text, icon='edit')
> +
> +    @enabled_with_permission('launchpad.Edit')
>      def editircnicknames(self):
>          target = '+editircnicknames'
>          text = 'Update IRC nicknames'
> @@ -2722,8 +2729,6 @@
>                    orientation='vertical')
>      custom_widget('UNVALIDATED_SELECTED', LaunchpadRadioWidget,
>                    orientation='vertical')
> -    custom_widget('mailing_list_auto_subscribe_policy',
> -                  LaunchpadRadioWidgetWithDescription)
>  
>      label = 'Change your e-mail settings'
>  
> @@ -2746,9 +2751,7 @@
>          self.form_fields = (self._validated_emails_field() +
>                              self._unvalidated_emails_field() +
>                              FormFields(TextLine(__name__='newemail',
> -                                                title=u'Add a new address'))
> -                            + self._mailing_list_fields()
> -                            + self._autosubscribe_policy_fields())
> +                                                title=u'Add a new address')))
>  
>      @property
>      def initial_values(self):
> @@ -2769,20 +2772,8 @@
>          unvalidated = self.unvalidated_addresses
>          if len(unvalidated) > 0:
>              unvalidated = unvalidated.pop()
> -        initial = dict(VALIDATED_SELECTED=validated,
> -                       UNVALIDATED_SELECTED=unvalidated)
> -
> -        # Defaults for the mailing list autosubscribe buttons.
> -        policy = self.context.mailing_list_auto_subscribe_policy
> -        initial.update(mailing_list_auto_subscribe_policy=policy)
> -
> -        return initial
> -
> -    def setUpWidgets(self, context=None):
> -        """See `LaunchpadFormView`."""
> -        super(PersonEditEmailsView, self).setUpWidgets(context)
> -        widget = self.widgets['mailing_list_auto_subscribe_policy']
> -        widget.display_label = False
> +        return dict(VALIDATED_SELECTED=validated,
> +                    UNVALIDATED_SELECTED=unvalidated)
>  
>      def _validated_emails_field(self):
>          """Create a field with a vocabulary of validated emails.
> @@ -2824,75 +2815,6 @@
>                     source=SimpleVocabulary(terms)),
>              custom_widget=self.custom_widgets['UNVALIDATED_SELECTED'])
>  
> -    def _mailing_list_subscription_type(self, mailing_list):
> -        """Return the context user's subscription type for the given list.
> -
> -        This is 'Preferred address' if the user is subscribed using her
> -        preferred address and 'Don't subscribe' if the user is not
> -        subscribed at all. Otherwise it's the EmailAddress under
> -        which the user is subscribed to this mailing list.
> -        """
> -        subscription = mailing_list.getSubscription(self.context)
> -        if subscription is None:
> -            return "Don't subscribe"
> -        elif subscription.email_address is None:
> -            return 'Preferred address'
> -        else:
> -            return subscription.email_address
> -
> -    def _mailing_list_fields(self):
> -        """Creates a field for each mailing list the user can subscribe to.
> -
> -        If a team doesn't have a mailing list, or the mailing list
> -        isn't usable, it's not included.
> -        """
> -        mailing_list_set = getUtility(IMailingListSet)
> -        fields = []
> -        terms = [
> -            SimpleTerm("Preferred address"),
> -            SimpleTerm("Don't subscribe"),
> -            ]
> -        for email in self.validated_addresses:
> -            terms.append(SimpleTerm(email, email.email))
> -        for team in self.context.teams_participated_in:
> -            mailing_list = mailing_list_set.get(team.name)
> -            if mailing_list is not None and mailing_list.is_usable:
> -                name = 'subscription.%s' % team.name
> -                value = self._mailing_list_subscription_type(mailing_list)
> -                field = Choice(__name__=name,
> -                               title=team.name,
> -                               source=SimpleVocabulary(terms), default=value)
> -                fields.append(field)
> -        return FormFields(*fields)
> -
> -    def _autosubscribe_policy_fields(self):
> -        """Create a field for each mailing list auto-subscription option."""
> -        return FormFields(
> -            Choice(__name__='mailing_list_auto_subscribe_policy',
> -                   title=_('When should Launchpad automatically subscribe '
> -                           'you to a team&#x2019;s mailing list?'),
> -                   source=MailingListAutoSubscribePolicy))
> -
> -    @property
> -    def mailing_list_widgets(self):
> -        """Return all the mailing list subscription widgets."""
> -        mailing_list_set = getUtility(IMailingListSet)
> -        widgets = []
> -        for widget in self.widgets:
> -            if widget.name.startswith('field.subscription.'):
> -                team_name = widget.label
> -                mailing_list = mailing_list_set.get(team_name)
> -                assert mailing_list is not None, 'Missing mailing list'
> -                widget_dict = dict(
> -                    team=mailing_list.team,
> -                    widget=widget,
> -                    )
> -                widgets.append(widget_dict)
> -                # We'll put the label in the first column, so don't include it
> -                # in the second column.
> -                widget.display_label = False
> -        return widgets
> -
>      def _validate_selected_address(self, data, field='VALIDATED_SELECTED'):
>          """A generic validator for this view's actions.
>  
> @@ -3125,6 +3047,139 @@
>                  "message for up to an hour or two.)" % newemail)
>          self.next_url = self.action_url
>  
> +
> +class PersonEditMailingListsView(LaunchpadFormView):
> +    """A view for editing a person's mailing list subscriptions."""
> +
> +    implements(IPersonEditMenu)
> +
> +    schema = IEmailAddress
> +
> +    custom_widget('mailing_list_auto_subscribe_policy',
> +                  LaunchpadRadioWidgetWithDescription)
> +
> +    label = 'Change your mailing list subscriptions'
> +
> +    def initialize(self):
> +        if self.context.is_team:
> +            # +editmailinglists is not available on teams.
> +            name = self.request['PATH_INFO'].split('/')[-1]
> +            raise NotFound(self, name, request=self.request)
> +        super(PersonEditMailingListsView, self).initialize()
> +
> +    def setUpFields(self):
> +        """Set up fields for this view.
> +
> +        The main fields of interest are the selection fields with custom
> +        vocabularies for the lists of validated and unvalidated email
> +        addresses.
> +        """
> +        super(PersonEditMailingListsView, self).setUpFields()
> +        self.form_fields = (self._mailing_list_fields()
> +                            + self._autosubscribe_policy_fields())
> +
> +    @property
> +    def initial_values(self):
> +        """Set up default values for the radio widgets.
> +
> +        A radio widget must have a selected value, so we select the
> +        first unvalidated and validated email addresses in the lists
> +        to be the default for the corresponding widgets.
> +
> +        The only exception is if the user has a preferred email
> +        address: then, that address is used as the default validated
> +        email address.
> +        """
> +        # Defaults for the mailing list autosubscribe buttons.
> +        return dict(mailing_list_auto_subscribe_policy=
> +                    self.context.mailing_list_auto_subscribe_policy)

That formatting is a bit weird. I'd do something like this:

return dict(
    mailing_list_auto_subscribe_policy=
        self.context.mailing_list_auto_subscribe_policy)

> +
> +    def setUpWidgets(self, context=None):
> +        """See `LaunchpadFormView`."""
> +        super(PersonEditMailingListsView, self).setUpWidgets(context)
> +        widget = self.widgets['mailing_list_auto_subscribe_policy']
> +        widget.display_label = False
> +
> +    def _mailing_list_subscription_type(self, mailing_list):
> +        """Return the context user's subscription type for the given list.
> +
> +        This is 'Preferred address' if the user is subscribed using her
> +        preferred address and 'Don't subscribe' if the user is not
> +        subscribed at all. Otherwise it's the EmailAddress under
> +        which the user is subscribed to this mailing list.
> +        """
> +        subscription = mailing_list.getSubscription(self.context)
> +        if subscription is None:
> +            return "Don't subscribe"
> +        elif subscription.email_address is None:
> +            return 'Preferred address'
> +        else:
> +            return subscription.email_address
> +
> +    def _mailing_list_fields(self):
> +        """Creates a field for each mailing list the user can subscribe to.
> +
> +        If a team doesn't have a mailing list, or the mailing list
> +        isn't usable, it's not included.
> +        """
> +        mailing_list_set = getUtility(IMailingListSet)
> +        fields = []
> +        terms = [
> +            SimpleTerm("Preferred address"),
> +            SimpleTerm("Don't subscribe"),
> +            ]
> +        for email in self.validated_addresses:
> +            terms.append(SimpleTerm(email, email.email))
> +        for team in self.context.teams_participated_in:
> +            mailing_list = mailing_list_set.get(team.name)
> +            if mailing_list is not None and mailing_list.is_usable:
> +                name = 'subscription.%s' % team.name
> +                value = self._mailing_list_subscription_type(mailing_list)
> +                field = Choice(__name__=name,
> +                               title=team.name,
> +                               source=SimpleVocabulary(terms), default=value)
> +                fields.append(field)
> +        return FormFields(*fields)
> +
> +    def _autosubscribe_policy_fields(self):
> +        """Create a field for each mailing list auto-subscription option."""
> +        return FormFields(
> +            Choice(__name__='mailing_list_auto_subscribe_policy',
> +                   title=_('When should Launchpad automatically subscribe '
> +                           'you to a team&#x2019;s mailing list?'),
> +                   source=MailingListAutoSubscribePolicy))
> +
> +    @property
> +    def mailing_list_widgets(self):
> +        """Return all the mailing list subscription widgets."""
> +        mailing_list_set = getUtility(IMailingListSet)
> +        widgets = []
> +        for widget in self.widgets:
> +            if widget.name.startswith('field.subscription.'):
> +                team_name = widget.label
> +                mailing_list = mailing_list_set.get(team_name)
> +                assert mailing_list is not None, 'Missing mailing list'
> +                widget_dict = dict(
> +                    team=mailing_list.team,
> +                    widget=widget,
> +                    )
> +                widgets.append(widget_dict)
> +                # We'll put the label in the first column, so don't include it
> +                # in the second column.
> +                widget.display_label = False
> +        return widgets
> +
> +    @property
> +    def validated_addresses(self):
> +        """All of this person's validated email addresses, including
> +        their preferred address (if any).
> +        """
> +        addresses = []
> +        if self.context.preferredemail:
> +            addresses.append(self.context.preferredemail)
> +        addresses += [email for email in self.context.validatedemails]

This could just be "addresses += list(self.context.validatedemails)".

> +        return addresses
> +
>      def validate_action_update_subscriptions(self, action, data):
>          """Make sure the user is subscribing using a valid address.
>  
> 
> === modified file 'lib/lp/registry/browser/tests/test_person.py'
> --- lib/lp/registry/browser/tests/test_person.py	2014-11-29 00:21:14 +0000
> +++ lib/lp/registry/browser/tests/test_person.py	2015-02-26 21:41:09 +0000
> @@ -683,6 +683,13 @@
>          browser = setupBrowserForUser(user=self.person)
>          self.assertRaises(NotFound, browser.open, url)
>  
> +    def test_team_editmailinglists_not_found(self):
> +        """Teams should not have a +editmailinglists page."""
> +        team = self.factory.makeTeam(owner=self.person, members=[self.person])
> +        url = '%s/+editmailinglists' % canonical_url(team)
> +        browser = setupBrowserForUser(user=self.person)
> +        self.assertRaises(NotFound, browser.open, url)
> +
>      def test_email_string_validation_no_email_prodvided(self):
>          """+editemails should warn if no email is provided."""
>          no_email = ''
> 
> === modified file 'lib/lp/registry/doc/teammembership-email-notification.txt'
> --- lib/lp/registry/doc/teammembership-email-notification.txt	2012-08-13 19:34:10 +0000
> +++ lib/lp/registry/doc/teammembership-email-notification.txt	2015-02-26 21:41:09 +0000
> @@ -818,7 +818,7 @@
>      <BLANKLINE>
>      If you would like to subscribe to the team list, use the link below
>      to update your Mailing List Subscription preferences.
> -      <http://launchpad.dev/people/+me/+editemails>
> +      <http://launchpad.dev/people/+me/+editmailinglists>
>      <BLANKLINE>
>      -- =
>      <BLANKLINE>
> @@ -843,7 +843,7 @@
>      <BLANKLINE>
>      If you would like to subscribe to the team list, use the link below
>      to update your Mailing List Subscription preferences.
> -      <http://launchpad.dev/people/+me/+editemails>
> +      <http://launchpad.dev/people/+me/+editmailinglists>
>      <BLANKLINE>
>      -- =
>      <BLANKLINE>
> 
> === modified file 'lib/lp/registry/mail/notification.py'
> --- lib/lp/registry/mail/notification.py	2012-11-26 18:50:14 +0000
> +++ lib/lp/registry/mail/notification.py	2015-02-26 21:41:09 +0000
> @@ -148,7 +148,7 @@
>                  'team-list-subscribe-block.txt', app='registry')
>              editemails_url = urlappend(
>                  canonical_url(getUtility(ILaunchpadRoot)),
> -                'people/+me/+editemails')
> +                'people/+me/+editmailinglists')
>              list_instructions = template % dict(editemails_url=editemails_url)
>          else:
>              list_instructions = ''
> @@ -257,7 +257,7 @@
>      headers = {}
>      subject = "New Mailing List for %s" % team.displayname
>      template = get_email_template('new-mailing-list.txt', app='registry')
> -    editemails_url = '%s/+editemails'
> +    editemails_url = '%s/+editmailinglists'
>  
>      for person in team.allmembers:
>          if person.is_team or person.preferredemail is None:
> 
> === modified file 'lib/lp/registry/stories/mailinglists/subscriptions.txt'
> --- lib/lp/registry/stories/mailinglists/subscriptions.txt	2014-01-30 15:04:06 +0000
> +++ lib/lp/registry/stories/mailinglists/subscriptions.txt	2015-02-26 21:41:09 +0000
> @@ -69,7 +69,7 @@
>      >>> logout()
>      >>> no_team_browser = setupBrowserFreshLogin(person)
>  
> -    >>> no_team_browser.open('http://launchpad.dev/people/+me/+editemails')
> +    >>> no_team_browser.open('http://launchpad.dev/people/+me/+editmailinglists')
>      >>> rosetta_admins = no_team_browser.getControl(
>      ...     name='field.subscription.rosetta-admins')
>      >>> rosetta_admins.displayOptions
> @@ -89,11 +89,11 @@
>      >>> logout()
>      >>> carlos_browser = setupBrowserFreshLogin(carlos)
>      >>> carlos_browser.open('http://launchpad.dev/~carlos')
> -    >>> carlos_browser.getLink(url="+editemails").click()
> +    >>> carlos_browser.getLink(url="+editmailinglists").click()
>  
>      >>> from lp.services.helpers import backslashreplace
>      >>> print backslashreplace(carlos_browser.title)
> -    Change your e-mail settings...
> +    Change your mailing list subscriptions...
>  
>      >>> admins = carlos_browser.getControl(name='field.subscription.admins')
>      >>> rosetta_admins = carlos_browser.getControl(
> @@ -198,9 +198,9 @@
>  Admins team, and he should know if the list is available.
>  
>      >>> carlos_browser.open('http://launchpad.dev/~carlos')
> -    >>> carlos_browser.getLink(url="+editemails").click()
> +    >>> carlos_browser.getLink(url="+editmailinglists").click()
>      >>> print backslashreplace(carlos_browser.title)
> -    Change your e-mail settings...
> +    Change your mailing list subscriptions...
>  
>      >>> rosetta_admins = carlos_browser.getControl(
>      ...     name='field.subscription.rosetta-admins')
> @@ -236,9 +236,9 @@
>      >>> logout()
>      >>> jdub_browser = setupBrowserFreshLogin(jdub)
>      >>> jdub_browser.open('http://launchpad.dev/~jdub')
> -    >>> jdub_browser.getLink(url="+editemails").click()
> +    >>> jdub_browser.getLink(url="+editmailinglists").click()
>      >>> print jdub_browser.title
> -    Change your e-mail settings...
> +    Change your mailing list subscriptions...
>  
>      >>> jdub_browser.getControl(
>      ...     name='field.subscription.rosetta-admins')
> @@ -260,9 +260,9 @@
>  His mailing list subscription is now available to be managed.
>  
>      >>> jdub_browser.open('http://launchpad.dev/~jdub')
> -    >>> jdub_browser.getLink(url="+editemails").click()
> +    >>> jdub_browser.getLink(url="+editmailinglists").click()
>      >>> print jdub_browser.title
> -    Change your e-mail settings...
> +    Change your mailing list subscriptions...
>  
>      >>> rosetta_team = jdub_browser.getControl(
>      ...     name='field.subscription.rosetta-admins')
> @@ -327,14 +327,14 @@
>      >>> carlos_browser.open('http://launchpad.dev/~admins')
>      >>> carlos_browser.getLink('Subscribe to mailing list').click()
>      >>> print carlos_browser.url
> -    http://launchpad.dev/~carlos/+editemails
> +    http://launchpad.dev/~carlos/+editmailinglists
>  
>  The unsubscribe link is visible for the rosetta admins team, which
>  has an active mailing list.
>  
>      # Subscribe to the list using the normal technique.
>      >>> carlos_browser.open('http://launchpad.dev/~carlos')
> -    >>> carlos_browser.getLink(url="+editemails").click()
> +    >>> carlos_browser.getLink(url="+editmailinglists").click()
>      >>> rosetta_admins = carlos_browser.getControl(
>      ...     name='field.subscription.rosetta-admins')
>      >>> rosetta_admins.value = ['Preferred address']
> @@ -469,9 +469,9 @@
>  list based on a setting in the person's Email preferences page.
>  
>      >>> carlos_browser.open('http://launchpad.dev/~carlos')
> -    >>> carlos_browser.getLink(url="+editemails").click()
> +    >>> carlos_browser.getLink(url="+editmailinglists").click()
>      >>> print backslashreplace(carlos_browser.title)
> -    Change your e-mail settings...
> +    Change your mailing list subscriptions...
>  
>  Carlos's default setting, 'Ask me when I join a team', is still in place.
>  
> @@ -549,7 +549,7 @@
>      >>> logout()
>      >>> browser = setupBrowserFreshLogin(james)
>      >>> browser.open('http://launchpad.dev/~jblack')
> -    >>> browser.getLink(url="+editemails").click()
> +    >>> browser.getLink(url="+editmailinglists").click()
>      >>> print_radio_button_field(browser.contents,
>      ...     'mailing_list_auto_subscribe_policy')
>      ( ) Never subscribe to mailing lists
> @@ -566,7 +566,7 @@
>  
>      # Change James' setting
>      >>> browser.open('http://launchpad.dev/~jblack')
> -    >>> browser.getLink(url="+editemails").click()
> +    >>> browser.getLink(url="+editmailinglists").click()
>      >>> set_autosubscribe_policy_and_submit('ALWAYS', browser)
>      ( ) Never subscribe to mailing lists
>      ( ) Ask me when I join a team
> @@ -582,7 +582,7 @@
>  
>      # Change James' setting
>      >>> browser.open('http://launchpad.dev/~jblack')
> -    >>> browser.getLink(url="+editemails").click()
> +    >>> browser.getLink(url="+editmailinglists").click()
>      >>> set_autosubscribe_policy_and_submit('NEVER', browser)
>      (*) Never subscribe to mailing lists
>      ( ) Ask me when I join a team
> 
> === modified file 'lib/lp/registry/stories/team/xx-team-membership.txt'
> --- lib/lp/registry/stories/team/xx-team-membership.txt	2012-01-15 11:06:57 +0000
> +++ lib/lp/registry/stories/team/xx-team-membership.txt	2015-02-26 21:41:09 +0000
> @@ -247,7 +247,7 @@
>      >>> user_browser.getLink('Register a team')
>      <Link ... url='http://.../people/+newteam'>
>      >>> user_browser.getLink('Change mailing list subscriptions')
> -    <Link ... url='http://.../~no-priv/+editemails'>
> +    <Link ... url='http://.../~no-priv/+editmailinglists'>
>  
>  Teams also have a participation page, but it does not include a mailing
>  list column.
> 
> === modified file 'lib/lp/registry/templates/person-editemails.pt'
> --- lib/lp/registry/templates/person-editemails.pt	2012-06-28 01:47:35 +0000
> +++ lib/lp/registry/templates/person-editemails.pt	2015-02-26 21:41:09 +0000
> @@ -19,6 +19,10 @@
>           id="no-contact-address">
>            Currently you don't have a contact address in Launchpad.
>        </p>
> +      <p>Looking to <a
> +        tal:define="link context/menu:overview/editmailinglists"
> +        tal:attributes="href link/target" 
> +        >configure your mailing list subscriptions?</a></p>

The question mark shouldn't be part of the link.

>      </metal:extra-info>
>  
>      <metal:widgets fill-slot="widgets">
> @@ -70,79 +74,6 @@
>      </metal:widgets>
>      <metal:widgets fill-slot="buttons" />
>    </div>
> -
> -
> -  <form action=""
> -        method="post" enctype="multipart/form-data"
> -        accept-charset="UTF-8" tal:condition="view/mailing_list_widgets">
> -
> -    <h2>Mailing list subscriptions</h2>
> -
> -    <p>You're a member of one or more teams with active mailing
> -      lists. You can subscribe to a team's mailing list using any of
> -      your verified email addresses.</p>
> -
> -    <table class="listing" style="width: 45em;">
> -      <thead>
> -        <th style="white-space:nowrap;">For mailing list</th>
> -        <th>Subscribe with</th>
> -      </thead>
> -      <tbody>
> -        <tr tal:repeat="widget view/mailing_list_widgets">
> -          <td tal:content="structure widget/team/fmt:link">Team</td>
> -          <td tal:content="structure widget/widget">Widget</td>
> -        </tr>
> -      </tbody>
> -    </table>
> -    <div style="padding-top: 1em; padding-bottom: 1em;">
> -      <input tal:replace="structure view/action_update_subscriptions/render" />
> -    </div>
> -  </form>
> -
> -  <form action=""
> -        method="post" enctype="multipart/form-data"
> -        accept-charset="UTF-8">
> -
> -    <h2>Automatic subscription to mailing lists</h2>
> -
> -    <div id="notification-info">When a team you are a member of creates a new
> -        mailing list, you will receive an email notification offering you the
> -        opportunity to join the new mailing list.  Launchpad can also
> -        automatically subscribe you to a team's mailing list whenever you
> -        join a team.</div>
> -
> -    <tal:widget
> -       define="widget nocall:view/widgets/mailing_list_auto_subscribe_policy">
> -      <table class="form">
> -
> -        <thead>
> -          <tr>
> -            <th style="white-space:nowrap; text-align:left;">
> -              <div style="margin-bottom: 1em;">
> -                <label tal:attributes="for widget/name"
> -                       tal:content="structure widget/label" />
> -              </div>
> -            </th>
> -            <td></td>
> -          </tr>
> -        </thead>
> -
> -        <tbody>
> -          <metal:block use-macro="context/@@launchpad_form/widget_row" />
> -          <tr>
> -            <td>
> -              <input
> -                 tal:replace="structure
> -                              view/action_update_autosubscribe_policy/render" />
> -            </td>
> -            <td></td>
> -          </tr>
> -        </tbody>
> -
> -      </table>
> -    </tal:widget>
> -  </form>
> -
>  </div>
>  </body>
>  </html>
> 
> === added file 'lib/lp/registry/templates/person-editmailinglists.pt'
> --- lib/lp/registry/templates/person-editmailinglists.pt	1970-01-01 00:00:00 +0000
> +++ lib/lp/registry/templates/person-editmailinglists.pt	2015-02-26 21:41:09 +0000
> @@ -0,0 +1,88 @@
> +<html
> +  xmlns="http://www.w3.org/1999/xhtml";
> +  xmlns:tal="http://xml.zope.org/namespaces/tal";
> +  xmlns:metal="http://xml.zope.org/namespaces/metal";
> +  xmlns:i18n="http://xml.zope.org/namespaces/i18n";
> +  metal:use-macro="view/macro:page/main_only"
> +  i18n:domain="launchpad"
> +>
> +  <body>
> +<div metal:fill-slot="main">
> +  <form action=""
> +        method="post" enctype="multipart/form-data"
> +        accept-charset="UTF-8" tal:condition="view/mailing_list_widgets">
> +
> +    <h2>Mailing list subscriptions</h2>

This heading can probably be dropped, as it is immediately preceded by "Change your mailing list subscriptions".

> +
> +    <p>You're a member of one or more teams with active mailing
> +      lists. You can subscribe to a team's mailing list using any of
> +      your verified email addresses. You can <a
> +        tal:define="link context/menu:overview/editemailaddresses"
> +        tal:attributes="href link/target" 
> +        >configure your verified email addresses here</a>.

"here" in a link is an antipattern. Perhaps just linkify "your verified email addresses" in the previous sentence?

> +    </p>
> +
> +    <table class="listing" style="width: 45em;">
> +      <thead>
> +        <th style="white-space:nowrap;">For mailing list</th>
> +        <th>Subscribe with</th>
> +      </thead>
> +      <tbody>
> +        <tr tal:repeat="widget view/mailing_list_widgets">
> +          <td tal:content="structure widget/team/fmt:link">Team</td>
> +          <td tal:content="structure widget/widget">Widget</td>
> +        </tr>
> +      </tbody>
> +    </table>
> +    <div style="padding-top: 1em; padding-bottom: 1em;">
> +      <input tal:replace="structure view/action_update_subscriptions/render" />
> +    </div>
> +  </form>
> +
> +  <form action=""
> +        method="post" enctype="multipart/form-data"
> +        accept-charset="UTF-8">
> +
> +    <h2>Automatic subscription to mailing lists</h2>

I'd drop the "to mailing lists".

> +
> +    <div id="notification-info">When a team you are a member of creates a new
> +        mailing list, you will receive an email notification offering you the
> +        opportunity to join the new mailing list.  Launchpad can also
> +        automatically subscribe you to a team's mailing list whenever you
> +        join a team.</div>
> +
> +    <tal:widget
> +       define="widget nocall:view/widgets/mailing_list_auto_subscribe_policy">
> +      <table class="form">
> +
> +        <thead>
> +          <tr>
> +            <th style="white-space:nowrap; text-align:left;">
> +              <div style="margin-bottom: 1em;">
> +                <label tal:attributes="for widget/name"
> +                       tal:content="structure widget/label" />
> +              </div>
> +            </th>
> +            <td></td>
> +          </tr>
> +        </thead>
> +
> +        <tbody>
> +          <metal:block use-macro="context/@@launchpad_form/widget_row" />
> +          <tr>
> +            <td>
> +              <input
> +                 tal:replace="structure
> +                              view/action_update_autosubscribe_policy/render" />
> +            </td>
> +            <td></td>
> +          </tr>
> +        </tbody>
> +
> +      </table>
> +    </tal:widget>
> +  </form>
> +
> +</div>
> +</body>
> +</html>
> 
> === modified file 'lib/lp/registry/templates/person-portlet-contact-details.pt'
> --- lib/lp/registry/templates/person-portlet-contact-details.pt	2012-06-15 16:23:50 +0000
> +++ lib/lp/registry/templates/person-portlet-contact-details.pt	2015-02-26 21:41:09 +0000
> @@ -15,9 +15,7 @@
>          <dd tal:content="context/name"/>
>      </dl>
>      <dl id="email-addresses">
> -      <dt>Email:
> -        <a tal:replace="structure overview_menu/editemailaddresses/fmt:icon" />
> -      </dt>
> +      <dt>Email:</dt>
>        <dd
>          tal:attributes="title view/visible_email_address_description">
>          <tal:not_logged_in
> @@ -49,6 +47,16 @@
>            </span>
>          </tal:emails>
>        </dd>
> +      <dd>
> +        <a
> +        tal:define="link context/menu:overview/editemailaddresses"
> +        tal:condition="link/enabled"
> +        tal:content="structure link/fmt:link" /><br />
> +        <a
> +        tal:define="link context/menu:overview/editmailinglists"
> +        tal:condition="link/enabled"
> +        tal:content="structure link/fmt:link" />

The attributes of those <a>s should be indented.

> +      </dd>
>      </dl>
>  
>  
> 
> === modified file 'lib/lp/registry/templates/team-portlet-mailinglist.pt'
> --- lib/lp/registry/templates/team-portlet-mailinglist.pt	2012-07-06 06:02:33 +0000
> +++ lib/lp/registry/templates/team-portlet-mailinglist.pt	2015-02-26 21:41:09 +0000
> @@ -22,7 +22,7 @@
>          <tal:can-subscribe-to-list
>              condition="view/user_can_subscribe_to_list">
>            <a id="link-list-subscribe" class="sprite add"
> -              href="/people/+me/+editemails">Subscribe to mailing list</a>
> +              href="/people/+me/+editmailinglists">Subscribe to mailing list</a>
>            <br />
>          </tal:can-subscribe-to-list>
>          <tal:subscribed-to-list
> 
> === modified file 'lib/lp/registry/tests/test_mailinglist.py'
> --- lib/lp/registry/tests/test_mailinglist.py	2013-01-11 01:05:14 +0000
> +++ lib/lp/registry/tests/test_mailinglist.py	2015-02-26 21:41:09 +0000
> @@ -169,7 +169,7 @@
>          self.assertEqual(
>              'New Mailing List for Team', notifications[0]['subject'])
>          self.assertTextMatchesExpressionIgnoreWhitespace(
> -            '.*To subscribe:.*http://launchpad.dev/~.*/\+editemails.*',
> +            '.*To subscribe:.*http://launchpad.dev/~.*/\+editmailinglists.*',
>              notifications[0].get_payload())
>  
>      def test_startConstructing_from_APPROVED(self):
> 


-- 
https://code.launchpad.net/~thomir/launchpad/devel-fix-editemails-link/+merge/251176
Your team Launchpad code reviewers is subscribed to branch lp:launchpad.


References