I know of page_title and label, which are used for this purpose, did you mean
one of them or am I not aware of this third one?
> + """Required for default headings in templates."""
> + return self.displayname
> +
> +
> +class PersonalArchiveSubscriptionNavigation(Navigation):
> + """Navigation for `IPersonalArchiveSubscription`.
> +
> + Without this, a breadcrumb will not be created for personal
> + archive subscription objects.
This is no longer needed, actually -- a fix for the bug (423898) is included
in my breadcrumbs branch that is on PQM now.
> + """
> + usedfor = IPersonalArchiveSubscription
> +
> def traverse_archive_subscription_for_subscriber(subscriber, archive_id):
> """Return the subscription for a subscriber to an archive."""
> subscription = None
> @@ -79,6 +96,14 @@
> return PersonalArchiveSubscription(subscriber, archive)
>
>
> +class PersonalArchiveSubscriptionBreadcrumb(Breadcrumb):
> + """Builds a breadcrumb for `PersonalArchiveSubscription`."""
> +
> + @property
> + def text(self):
> + return self.context.displayname
You can use webapp.breadcrumbs.DisplaynameBreadcrumb in the zcml and get rid
of this adapter altogether. It'd be great if you could do a quick check for
other places where that generic adapter could replace other specific ones. :)
(Note I haven't done any JS hacking since the epic, so I may have
misunderstood what the code is doing)
And btw, it'd be nice if you could get a second pair of eyes to have a look at
this, as I don't feel comfortable reviewing something I wouldn't know how to
write.
> +
> + // Unfortunately we can't use the lazr slider, as it uses display:block
> + // which breaks table rows (they use display:table-row).
> + function show_add_subscriber(e) {
> + e.preventDefault();
> + subscribers.setStyle('display', 'block');
> + add_subscriber_row.setStyle('display', 'table-row');
> + }
> +
> + Y.on('click', show_add_subscriber,
> + '#add-subscriber-placeholder a');
> +
> +});
> + </script>
> +
>
> </div>
> </body>
>
Hi Michael,
Your changes look good. I have a few suggestions and I'd like somebody
else to review the JS changes, as I don't feel comfortable doing so.
review approve
> === modified file 'lib/lp/ soyuz/browser/ archivesubscrip tion.py' soyuz/browser/ archivesubscrip tion.py 2009-08-12 08:40:41 +0000 soyuz/browser/ archivesubscrip tion.py 2009-09-14 08:08:51 +0000 bersView' , eSubscriptionBr eadcrumb' , ubscriptionView ', ubscriptionsVie w', archive_ subscription_ for_subscriber' enSet) interfaces. archivesubscrib er import ( berSet, IPersonalArchiv eSubscription) launchpad. webapp. breadcrumb import Breadcrumb launchpad. webapp. launchpadform import ( rmView) launchpad. webapp. publisher import ( widgets. popup import PersonPickerWidget veSubscription` .""" displayname
> --- lib/lp/
> +++ lib/lp/
> @@ -9,6 +9,8 @@
>
> __all__ = [
> 'ArchiveSubscri
> + 'PersonalArchiv
> + 'PersonArchiveS
> 'PersonArchiveS
> 'traverse_
> ]
> @@ -34,10 +36,11 @@
> IArchiveAuthTok
> from lp.soyuz.
> IArchiveSubscri
> +from canonical.
> from canonical.
> action, custom_widget, LaunchpadFormView, LaunchpadEditFo
> from canonical.
> - canonical_url, LaunchpadView)
> + canonical_url, LaunchpadView, Navigation)
> from canonical.widgets import DateWidget
> from canonical.
>
> @@ -65,6 +68,20 @@
> """See `IPersonalArchi
> return "Access to %s" % self.archive.
>
> + @property
> + def title(self):
I know of page_title and label, which are used for this purpose, did you mean
one of them or am I not aware of this third one?
> + """Required for default headings in templates.""" SubscriptionNav igation( Navigation) : veSubscription` .
> + return self.displayname
> +
> +
> +class PersonalArchive
> + """Navigation for `IPersonalArchi
> +
> + Without this, a breadcrumb will not be created for personal
> + archive subscription objects.
This is no longer needed, actually -- a fix for the bug (423898) is included
in my breadcrumbs branch that is on PQM now.
> + """ eSubscription archive_ subscription_ for_subscriber( subscriber, archive_id): Subscription( subscriber, archive) SubscriptionBre adcrumb( Breadcrumb) : eSubscription` .""" displayname
> + usedfor = IPersonalArchiv
> +
> def traverse_
> """Return the subscription for a subscriber to an archive."""
> subscription = None
> @@ -79,6 +96,14 @@
> return PersonalArchive
>
>
> +class PersonalArchive
> + """Builds a breadcrumb for `PersonalArchiv
> +
> + @property
> + def text(self):
> + return self.context.
You can use webapp. breadcrumbs. DisplaynameBrea dcrumb in the zcml and get rid
of this adapter altogether. It'd be great if you could do a quick check for
other places where that generic adapter could replace other specific ones. :)
> + berUI(Interface ): soyuz/browser/ tests/test_ breadcrumbs. py' soyuz/browser/ tests/test_ breadcrumbs. py 2009-09-02 16:32:06 +0000 soyuz/browser/ tests/test_ breadcrumbs. py 2009-09-11 10:52:54 +0000 launchpad. webapp. tests.breadcrum bs import ( estCase) interfaces. distribution import IDistributionSet browser. archivesubscrip tion import PersonalArchive Subscription eriesBreadcrumb (BaseBreadcrumb TestCase) : ls(texts[ -1], "0.1-1") criptionBreadcr umb(BaseBreadcr umbTestCase) : veSubscriptionB readcrumb, self).setUp() makeArchive( ) buildd_ secret = 'secret' subscription = self.ppa. newSubscription (owner, owner) newAuthToken( owner) archive_ subscription = PersonalArchive Subscription( archive_ subscription( self):
> +
> class IArchiveSubscri
> """A custom interface for user interaction with archive subscriptions.
>
> === modified file 'lib/lp/
> --- lib/lp/
> +++ lib/lp/
> @@ -11,6 +11,8 @@
> from canonical.
> BaseBreadcrumbT
> from lp.registry.
> +from lp.soyuz.
> +from lp.testing import login, login_person
>
>
> class TestDistroArchS
> @@ -55,5 +57,38 @@
> self.assertEqua
>
>
> +class TestArchiveSubs
> +
> + def setUp(self):
> + super(TestArchi
> +
> + # Create a private ppa
> + self.ppa = self.factory.
> + login('<email address hidden>')
> + self.ppa.private = True
> + self.ppa.
> +
> + owner = self.ppa.owner
> + login_person(owner)
> + self.ppa_
> + self.ppa_token = self.ppa.
> + self.personal_
> + owner, self.ppa)
> +
> + def test_personal_
> +
I find it weird to have a blank line here, although I do that for class
definitions.
> + self.traversed_ objects = [ archive_ subscription] url(self. personal_ archive_ subscription) rumbsURLs( objects) rumbsTexts( objects) ls(subscription _url, urls[-1]) displayname, texts[-1]) TestLoader( ).loadTestsFrom Name(__ name__) soyuz/templates /archive- subscribers. pt' soyuz/templates /archive- subscribers. pt 2009-08-05 10:02:22 +0000 soyuz/templates /archive- subscribers. pt 2009-09-18 08:09:23 +0000 "context/ @@launchpad_ widget_ macros/ yui2calendar- dependencies" /> slot="heading" > "CONTEXTS/ fmt:pagetitle" > slot="main" > top-portlet" > subscribers" > subscriptions" id="no- subscribers" > subscriptions" id="no- subscribers" > subscriber- placeholder" ></div> "view/errors" "view/error_ count" /> subscribers" class="listing"> archive_ subscriber_ row"> width:30% ">Name< /th> "2">Comment< /th> add-subscriber" style=" background- color:# eeeeff; "> row-form define="widgets widgets| view/widgets" javascript" > lib/yui/ current/ build/' , isNull( Y.get(' p.error. message' ))) { subscribers .add-subscriber'); row.setStyle( 'display' , 'none'); #subscribers' ); isObject( Y.get(' #no-subscribers '))) { setStyle( 'display' , 'none'); #add-subscriber -placeholder' ); #add-subscriber -placeholder a"); node.set( 'innerHTML' , 'Add access');
> + self.root, self.ppa.owner, self.personal_
> + subscription_url = canonical_
> +
> + urls = self._getBreadc
> + subscription_url, self.traversed_
> + texts = self._getBreadc
> + subscription_url, self.traversed_
> +
> + self.assertEqua
> + self.assertEquals(
> + "Access to %s" % self.ppa.
> +
> def test_suite():
> return unittest.
>
> === modified file 'lib/lp/
> --- lib/lp/
> +++ lib/lp/
> @@ -12,22 +12,19 @@
> use-macro=
> </metal:block>
>
> - <div metal:fill-
> - <h1 tal:content=
> - Manage access to Blah PPA
> - </h1>
> - </div>
> <div metal:fill-
> <div class="
> <p>You can grant access to people or teams to install software
> from your PPA.
> </p>
>
> - <div class="
> - <p tal:condition="not: view/has_
> - No one has access to install software from this PPA.
> - </p>
> -
> + <p tal:condition="not: view/has_
> + No one has access to install software from this PPA.
> + </p>
> +
> + <div id="add-
> +
> + <div id="subscribers">
> <p class="error message" tal:condition=
> tal:content=
>
> @@ -44,13 +41,13 @@
> id="archive-
> <thead>
> <tr class="
> - <th>Name</th>
> + <th style="
> <th>Expires</th>
> <th colspan=
> </tr>
> </thead>
> <tbody>
> - <tr>
> + <tr class="
> <tal:single-
> repeat="widget widgets">
>
> @@ -96,6 +93,49 @@
> </form>
> </div><!-- class="portlet" -->
> </div>
> + <script type="text/
> +YUI({
> + base: '../../
> + filter: 'raw'
> + }).use('node', 'event', 'lazr.effects', function(Y) {
> +
> + // If there are no errors then we hide the add-subscriber row and
> + // potentially the whole table if there are no subscribers.
> + if (Y.Lang.
> +
> + // Hide the add-subscriber row.
> + var add_subscriber_row = Y.get(
> + '#archive-
> + add_subscriber_
> +
> + // If there are no subscribers, then hide the complete section.
> + var subscribers = Y.get('
> + if (Y.Lang.
> + subscribers.
> + }
> + }
> +
> + // Add a link to open the add-subscriber row.
> + var placeholder = Y.get('
> + placeholder.set(
> + 'innerHTML', '<a class="js-action sprite add" href="#" />');
> + var add_subscriber_node = Y.get("
> + add_subscriber_
Do you really need to use JS to set the innerHTML of the <a> tag? Can't you
do something like
placeholder .set('innerHTML ', '<a class="...">Add access</a>');
?
(Note I haven't done any JS hacking since the epic, so I may have
misunderstood what the code is doing)
And btw, it'd be nice if you could get a second pair of eyes to have a look at
this, as I don't feel comfortable reviewing something I wouldn't know how to
write.
> + subscriber( e) { setStyle( 'display' , 'block'); row.setStyle( 'display' , 'table-row'); subscriber, r-placeholder a');
> + // Unfortunately we can't use the lazr slider, as it uses display:block
> + // which breaks table rows (they use display:table-row).
> + function show_add_
> + e.preventDefault();
> + subscribers.
> + add_subscriber_
> + }
> +
> + Y.on('click', show_add_
> + '#add-subscribe
> +
> +});
> + </script>
> +
>
> </div>
> </body>
>