Merge lp:~edwin-grubbs/launchpad/bug-490593-configure-involvement-portlet into lp:launchpad

Proposed by Edwin Grubbs
Status: Merged
Approved by: Curtis Hovey
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~edwin-grubbs/launchpad/bug-490593-configure-involvement-portlet
Merge into: lp:launchpad
Diff against target: 1459 lines (+524/-182)
34 files modified
Makefile (+3/-0)
lib/canonical/launchpad/icing/style-3-0.css.in (+26/-5)
lib/canonical/launchpad/pagetests/standalone/xx-form-layout.txt (+2/-1)
lib/lp/blueprints/browser/specificationtarget.py (+1/-1)
lib/lp/bugs/stories/bug-also-affects/xx-upstream-bugtracker-links.txt (+4/-2)
lib/lp/bugs/stories/bugs/xx-front-page-info.txt (+1/-1)
lib/lp/bugs/stories/bugtracker/bugtrackers-index.txt (+2/-1)
lib/lp/bugs/stories/bugtracker/xx-bugtracker.txt (+2/-1)
lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt (+11/-11)
lib/lp/bugs/stories/guided-filebug/xx-no-launchpadder.txt (+2/-1)
lib/lp/bugs/stories/guided-filebug/xx-project-guided-filebug.txt (+1/-1)
lib/lp/bugs/stories/initial-bug-contacts/10-set-upstream-bugcontact.txt (+2/-2)
lib/lp/bugs/templates/bugtarget-bugs.pt (+8/-3)
lib/lp/bugs/templates/bugtarget-macros-filebug.pt (+1/-1)
lib/lp/code/stories/branches/xx-branch-tag-cloud.txt (+7/-5)
lib/lp/code/stories/branches/xx-product-branches.txt (+12/-8)
lib/lp/registry/browser/configure.zcml (+42/-0)
lib/lp/registry/browser/pillar.py (+72/-4)
lib/lp/registry/browser/product.py (+101/-23)
lib/lp/registry/browser/productseries.py (+24/-20)
lib/lp/registry/browser/tests/pillar-views.txt (+46/-14)
lib/lp/registry/doc/product.txt (+6/-3)
lib/lp/registry/model/product.py (+6/-2)
lib/lp/registry/stories/product/xx-product-development-focus.txt (+32/-16)
lib/lp/registry/stories/product/xx-product-edit.txt (+4/-2)
lib/lp/registry/stories/product/xx-product-launchpad-usage.txt (+40/-17)
lib/lp/registry/templates/pillar-involvement-portlet.pt (+30/-3)
lib/lp/registry/templates/product-index.pt (+0/-4)
lib/lp/translations/stories/productseries/xx-productseries-translations.txt (+10/-10)
lib/lp/translations/stories/standalone/xx-product-translations.txt (+8/-7)
lib/lp/translations/stories/translationgroups/15-product-translation-group.txt (+3/-2)
lib/lp/translations/stories/translationgroups/46-test-distro-structured-permissions.txt (+1/-1)
lib/lp/translations/stories/translations/55-rosetta-potemplates.txt (+2/-1)
lib/lp/translations/templates/product-portlet-not-using-launchpad.pt (+12/-9)
To merge this branch: bzr merge lp:~edwin-grubbs/launchpad/bug-490593-configure-involvement-portlet
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code ui Approve
Review via email: mp+21524@code.launchpad.net

Description of the change

Summary
-------

This branch uses the "Get Involved" portlet to encourage users to link
projects to the upstream bug tracker. In a later branch, we may open
up permissions to more than the project owner.

Implementation details
----------------------

Drive-by cleanups.
    Makefile
    lib/lp/blueprints/browser/specificationtarget.py

Split out form elements for configuring Launchpad services into seperate
forms. The visible_disabled_links attributes displays disabled links for
projects that don't have Bugs or Branches configured.
    lib/lp/registry/browser/configure.zcml
    lib/lp/registry/browser/pillar.py
    lib/lp/registry/browser/product.py
    lib/lp/registry/stories/product/xx-product-launchpad-usage.txt
    lib/lp/registry/browser/tests/pillar-views.txt
    lib/lp/registry/templates/pillar-involvement-portlet.pt

Added styles for a disabled version of the Get Involved links.
    lib/canonical/launchpad/icing/style-3-0.css.in

Fixed links that were pointing to +edit.
    lib/lp/bugs/templates/bugtarget-bugs.pt
    lib/lp/bugs/templates/bugtarget-macros-filebug.pt
    lib/lp/translations/templates/product-portlet-not-using-launchpad.pt

Fixed tests that were expecting to use +edit.
    lib/canonical/launchpad/pagetests/standalone/xx-form-layout.txt
    lib/lp/bugs/stories/bug-also-affects/xx-upstream-bugtracker-links.txt
    lib/lp/bugs/stories/bugtracker/bugtrackers-index.txt
    lib/lp/bugs/stories/bugtracker/xx-bugtracker.txt
    lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt
    lib/lp/bugs/stories/guided-filebug/xx-no-launchpadder.txt
    lib/lp/bugs/stories/guided-filebug/xx-project-guided-filebug.txt
    lib/lp/bugs/stories/initial-bug-contacts/10-set-upstream-bugcontact.txt
    lib/lp/code/stories/branches/xx-branch-tag-cloud.txt
    lib/lp/code/stories/branches/xx-product-branches.txt
    lib/lp/registry/stories/product/xx-product-edit.txt
    lib/lp/translations/stories/productseries/xx-productseries-translations.txt
    lib/lp/translations/stories/standalone/xx-product-translations.txt
    lib/lp/translations/stories/translationgroups/15-product-translation-group.txt
    lib/lp/translations/stories/translationgroups/46-test-distro-structured-permissions.txt
    lib/lp/translations/stories/translations/55-rosetta-potemplates.txt

Tests
-----

./bin/test -vv -t whatever '/xx-product-launchpad-usage.txt|/pillar-views.txt|/xx-form-layout.txt|/xx-upstream-bugtracker-links.txt|/bugtrackers-index.txt|/xx-bugtracker.txt|/xx-bug-reporting-guidelines.txt|/xx-no-launchpadder.txt|/xx-project-guided-filebug.txt|/xx-branch-tag-cloud.txt|/xx-product-branches.txt|/xx-product-edit.txt|/xx-productseries-translations.txt|/xx-product-translations.txt|stories/initial-bug-contacts|stories/translationgroups|stories/translations'

Demo and Q/A
------------

* Open http://launchpad.dev/firefox
  * Test the new forms and links for:
    * Configure Launchpad Answers
    * Configure Launchpad Branches
    * Configure Launchpad Bugs
    * Configure Launchpad Translations
* Open http://blueprints.launchpad.dev/firefox
    * There should be a "Configure Launchpad Blueprints" link.
* Open http://translations.launchpad.dev/firefox
    * If translations is disabled, there should be a
      "Configure Launchpad Translations" link.
* Open http://bugs.launchpad.dev/firefox
    * If the project is not using launchpad for bug tracking,
      there should be a "Configure Launchpad Bugs" link.

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :
Download full text (10.4 KiB)

Hi Edwin.

I really appreciate your effort to solve this usability issue.

UI/Usability
------------

! As the owner of thunderbird, I saw that the "Report a bug" was disabled. I
  used "Configure Launchpad bugs" and choose The Mozilla.org bug tracker and
  provided the remove project.
  * I still see "Report a bug" (This service needs configuration). This is
    wrong. I provided the real information that should satisfy other
    contributors. I expect to see the warning disappear.

! As the owner of Firefox and thunderbird, I expect to see a warning that
  "Development focus branch has not been specified" which I can see in the
  Project information portlet.
  * I think this is a case where official_codehosting is a bogus attribute.
    We know if the project officially uses code if the branch is neither a
    mirror or import. I expect the Involvement portlet to tell me that this
    is a problem.
  * As an anonymous user I should see a warning that the development focus is
    missing a branch in the Involvement portlet.
  * May be call for action should also be repeated on the series page since
    that is the object that is being edited.

! As the user of evolution, a project that has a link to a package with
  I expect to see a warning that translation syncing should be setup.
  The owner certainly can set official/unofficial usage, but any user
  can enable series sync, and should if Ubuntu has translations for it.
  * This is a unique case were any user can set this. This information
    must be shown on the series overview for any user to act on.
  * We may want alternate configuration link or tool tips about the
    problem.
  * This is case is harder than the others because the official_translations
    attribute is legitimate.

! I think the message for all these services is wrong. We want the user
  to tell Launchpad where the service is and maybe configure it if the
  service is Launchpad's. In the bug tracker example. we need to know the
  bug tracker, and the owner wants to tell every one about the official
  tracker; no one is asking users to enable Launchpad Bugs.

* I noticed that as an anonymous user or no-priv that the Involvement portlet
  has about 1em extra padding in the bottom. Oh. The markup has an empty
  <ul>; this is invalid HTML.

* I Think the "Uses Launchpad for" item in the Project information portlet
  may be redundant. We can discuss removing it after we are certain that this
  change is all the information needed. I suspect we need to disable answers
  and blueprints first since they are effectively on and it is not clear
  that the involvement portlet is 100% related to official uses. Of course,
  the involvement portlet is not just about official uses anymore either.

* Think the "Development focus branch has not been specified" link in
  the Project information portlet may be removable if we solve the Involvement
  portlet issues.

* Note to self, we may want to remove official_translations from distros.
  Only Ubuntu can use translations. I recall there was a complaint from a
  user that we cannot set a distro bug tracker.

I see your configuration for the bug tracker is similar to my branch and I
...

review: Needs Fixing (code ui)
Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :
Download full text (23.5 KiB)

> Hi Edwin.
>
> I really appreciate your effort to solve this usability issue.
>
> UI/Usability
> ------------
>
> ! As the owner of thunderbird, I saw that the "Report a bug" was disabled. I
> used "Configure Launchpad bugs" and choose The Mozilla.org bug tracker and
> provided the remove project.
> * I still see "Report a bug" (This service needs configuration). This is
> wrong. I provided the real information that should satisfy other
> contributors. I expect to see the warning disappear.

Hi Curtis,

Thanks for the review.

As we discussed on Skype, I will focus on code hosting now and fix the logic for displaying the bug tracker warning in another branch.

I have not fixed any of the unit tests for these recent changes, since I want to get your input on the UI changes first. You will notice that "Configure code hosting" switches between a plus-icon and an edit-icon, since I'm re-using the original menu item for +linkbranch. The plus-icon doesn't really make sense with the "configure" verb, but I think it is worth contemplating the use of a different icon to indicate unconfigured services.

> ! As the owner of Firefox and thunderbird, I expect to see a warning that
> "Development focus branch has not been specified" which I can see in the
> Project information portlet.
> * I think this is a case where official_codehosting is a bogus attribute.
> We know if the project officially uses code if the branch is neither a
> mirror or import. I expect the Involvement portlet to tell me that this
> is a problem.
> * As an anonymous user I should see a warning that the development focus is
> missing a branch in the Involvement portlet.
> * May be call for action should also be repeated on the series page since
> that is the object that is being edited.

I'm confused here, since a little further down you comment that the warning could be removed from the Project information portlet. Do you want a more noticeable warning message in the involvement portlet than a tooltip?

> ! As the user of evolution, a project that has a link to a package with
> I expect to see a warning that translation syncing should be setup.
> The owner certainly can set official/unofficial usage, but any user
> can enable series sync, and should if Ubuntu has translations for it.
> * This is a unique case were any user can set this. This information
> must be shown on the series overview for any user to act on.
> * We may want alternate configuration link or tool tips about the
> problem.
> * This is case is harder than the others because the official_translations
> attribute is legitimate.

We agreed to handle translations later.

> ! I think the message for all these services is wrong. We want the user
> to tell Launchpad where the service is and maybe configure it if the
> service is Launchpad's. In the bug tracker example. we need to know the
> bug tracker, and the owner wants to tell every one about the official
> tracker; no one is asking users to enable Launchpad Bugs.

I tried improving the tooltip for the warnings.

> * I noticed that as an anonymous user or no-priv that the Involve...

Revision history for this message
Curtis Hovey (sinzui) wrote :
Download full text (7.5 KiB)

Hi Edwin.

I have a couple suggestion and questions that I think will take a few minutes
to resolve.

Using the UI:

    * "bug tracker" is two words.
    * Maybe "Configure support tracking" for answers.
    * We are asking users to Configure project development branch? I guess
      length is the issue here.

Code:

I see these warnings:

    == Pyflakes notices ==

    lib/lp/registry/browser/pillar.py
        28: 'IProductSeries' imported but unused

    lib/lp/registry/browser/product.py
        9: undefined name 'ProductInvolvementView' in __all__

> === modified file 'lib/lp/bugs/templates/bugtarget-bugs.pt'
> --- lib/lp/bugs/templates/bugtarget-bugs.pt 2010-03-04 15:09:10 +0000
> +++ lib/lp/bugs/templates/bugtarget-bugs.pt 2010-03-19 16:20:16 +0000
> @@ -169,9 +169,14 @@
> bug tracking.</strong></p>
>
> <p tal:condition="context/required:launchpad.Edit"
> - id="no-malone-edit">
> - <a tal:attributes="href string:${context/fmt:url/+edit}">Enable
> - bug tracking.</a>
> + id="no-malone-edit"
> + tal:define ="configure_bugtracker context/menu:overview/configure_bugtracker | nothing"
> + >
> + <a tal:condition="configure_bugtracker"
> + tal:replace="structure configure_bugtracker/fmt:link"/>
> + <a tal:condition="not: configure_bugtracker"
> + tal:attributes="href string:${context/fmt:url/+edit}">
> + Enable bug tracking.</a>

Why isn't this using the context's overview menu edit link that has
permission checking for rendering.

    context/menu:overview/edit:fmt:url

The language looks wrong. We are interested in Configuring, not enabling.
I think this is for the bugs root page which may be fine in this case.

> === modified file 'lib/lp/code/stories/branches/xx-product-branches.txt'
> --- lib/lp/code/stories/branches/xx-product-branches.txt 2010-01-08 14:22:42 +0000
> +++ lib/lp/code/stories/branches/xx-product-branches.txt 2010-03-19 16:20:16 +0000
> @@ -170,7 +170,7 @@
> the 'Import your project' button is not shown.
>
> >>> admin_browser.open('http://launchpad.dev/gnome-terminal')
> - >>> admin_browser.getLink('Change details').click()
> + >>> admin_browser.getLink('Configure Launchpad Branches').click()
> >>> admin_browser.getControl(
> ... 'Code for this project is published in Bazaar branches '
> ... 'on Launchpad').click()

I do not like the use of "Launchpad" in these links. They imply the project
is setting up hosting when we are really interested in gathering project info.

I have dealt with several angry, confused users who see Launchpad masquerading
or is forking project. I think taking "Launchpad" out of the link will make
it clear we want the know where the upstream branch is.

> === modified file 'lib/lp/registry/browser/pillar.py'
> --- lib/lp/registry/browser/pillar.py 2010-02-17 11:19:42 +0000
> +++ lib/lp/registry/browser/pillar.py 2010-03-19 16:20:16 +0000

> @@ -128,6 +130,78 @@
> link for link in menuapi.navigation.values() if link.enabled],
> key=attrgetter('sort_key'))
>
> + @cachedproperty
> + def visible_d...

Read more...

review: Needs Information (code ui)
Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :
Download full text (20.2 KiB)

Hi Curtis,

Thanks for the review. I have merged in Brad's branch and pointed
the "Configure product branch" links at +setbranch instead of
+linkbranch, and I have responded to your comments below.

-Edwin

> Hi Edwin.
>
> I have a couple suggestion and questions that I think will take a few minutes
> to resolve.
>
> Using the UI:
>
> * "bug tracker" is two words.
> * Maybe "Configure support tracking" for answers.
> * We are asking users to Configure project development branch? I guess
> length is the issue here.

Fixed.

>
> Code:
>
> I see these warnings:
>
> == Pyflakes notices ==
>
> lib/lp/registry/browser/pillar.py
> 28: 'IProductSeries' imported but unused
>
> lib/lp/registry/browser/product.py
> 9: undefined name 'ProductInvolvementView' in __all__
>

TODO: lint

>
> > === modified file 'lib/lp/bugs/templates/bugtarget-bugs.pt'
> > --- lib/lp/bugs/templates/bugtarget-bugs.pt 2010-03-04 15:09:10 +0000
> > +++ lib/lp/bugs/templates/bugtarget-bugs.pt 2010-03-19 16:20:16 +0000
> > @@ -169,9 +169,14 @@
> > bug tracking.</strong></p>
> >
> > <p tal:condition="context/required:launchpad.Edit"
> > - id="no-malone-edit">
> > - <a tal:attributes="href string:${context/fmt:url/+edit}">Enable
> > - bug tracking.</a>
> > + id="no-malone-edit"
> > + tal:define ="configure_bugtracker
> context/menu:overview/configure_bugtracker | nothing"
> > + >
> > + <a tal:condition="configure_bugtracker"
> > + tal:replace="structure configure_bugtracker/fmt:link"/>
> > + <a tal:condition="not: configure_bugtracker"
> > + tal:attributes="href string:${context/fmt:url/+edit}">
> > + Enable bug tracking.</a>
>
> Why isn't this using the context's overview menu edit link that has
> permission checking for rendering.
>
> context/menu:overview/edit:fmt:url
>
> The language looks wrong. We are interested in Configuring, not enabling.
> I think this is for the bugs root page which may be fine in this case.

I was afraid of breaking a bunch more tests if I changed the name of
the link from "Enable bug tracking", not to mention that there may be
push back on the "Configure bug tracker" link later on.

> > === modified file 'lib/lp/code/stories/branches/xx-product-branches.txt'
> > --- lib/lp/code/stories/branches/xx-product-branches.txt 2010-01-08
> 14:22:42 +0000
> > +++ lib/lp/code/stories/branches/xx-product-branches.txt 2010-03-19
> 16:20:16 +0000
> > @@ -170,7 +170,7 @@
> > the 'Import your project' button is not shown.
> >
> > >>> admin_browser.open('http://launchpad.dev/gnome-terminal')
> > - >>> admin_browser.getLink('Change details').click()
> > + >>> admin_browser.getLink('Configure Launchpad Branches').click()
> > >>> admin_browser.getControl(
> > ... 'Code for this project is published in Bazaar branches '
> > ... 'on Launchpad').click()
>
> I do not like the use of "Launchpad" in these links. They imply the project
> is setting up hosting when we are really interested in gathering project info.
>
> I have dealt with severa...

Revision history for this message
Curtis Hovey (sinzui) wrote :

Thanks for these revisions Edwin.

I am very aware of the ProductInvolvementView problem. I am working on a fix for it. It tangentially related to the ProductSeriesBranchTarget adapter I am trying to remove. Your branch is good to land. If I solve the provideAdapter() problem, will move your class in my branch.

review: Approve (code ui)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Makefile'
--- Makefile 2010-04-06 21:43:23 +0000
+++ Makefile 2010-04-09 18:48:33 +0000
@@ -182,7 +182,10 @@
182 --download-base=download-cache/dist --eggs=eggs182 --download-base=download-cache/dist --eggs=eggs
183183
184# This builds bin/py and all the other bin files except bin/buildout.184# This builds bin/py and all the other bin files except bin/buildout.
185# Remove the target before calling buildout to ensure that buildout
186# updates the timestamp.
185$(BUILDOUT_BIN): bin/buildout versions.cfg $(BUILDOUT_CFG) setup.py187$(BUILDOUT_BIN): bin/buildout versions.cfg $(BUILDOUT_CFG) setup.py
188 $(RM) $@
186 $(SHHH) PYTHONPATH= ./bin/buildout \189 $(SHHH) PYTHONPATH= ./bin/buildout \
187 configuration:instance_name=${LPCONFIG} -c $(BUILDOUT_CFG)190 configuration:instance_name=${LPCONFIG} -c $(BUILDOUT_CFG)
188191
189192
=== modified file 'lib/canonical/launchpad/icing/style-3-0.css.in'
--- lib/canonical/launchpad/icing/style-3-0.css.in 2010-04-06 17:12:49 +0000
+++ lib/canonical/launchpad/icing/style-3-0.css.in 2010-04-09 18:48:33 +0000
@@ -525,6 +525,19 @@
525 display: block;525 display: block;
526 padding: 0.3em;526 padding: 0.3em;
527 }527 }
528.involvement li.disabled {
529 color: #cccccc;
530 }
531.involvement-service-links li.disabled img {
532 margin-bottom: 0;
533 }
534.involvement-service-links li.disabled span {
535 margin-bottom: 0;
536 }
537.involvement-service-links li.disabled table {
538 padding-top: 0.3em;
539 padding-bottom: 0.3em;
540 }
528.involvement a.bugs {541.involvement a.bugs {
529 color: #b9413e;542 color: #b9413e;
530 background: url(/@@/bugs-arrow-right.png) right center no-repeat;543 background: url(/@@/bugs-arrow-right.png) right center no-repeat;
@@ -812,15 +825,23 @@
812 padding: 2px 0 5px 18px;825 padding: 2px 0 5px 18px;
813 line-height: 18px;826 line-height: 18px;
814}827}
828.icon-only {
829 border: 0;
830 padding: 0;
831 width: 14px;
832}
833div.icon-only {
834 height: 14px;
835}
815input[type="submit"].icon-only {836input[type="submit"].icon-only {
816 vertical-align: middle;837 height: 14px;
817 border: 0;
818 padding: 0;
819 height: 16px;
820 width: 16px;
821 background-color: inherit;838 background-color: inherit;
822 cursor: pointer;839 cursor: pointer;
823}840}
841span.icon-only {
842 padding-right: 14px;
843 line-height: 14px;
844}
824.vertical .sprite {845.vertical .sprite {
825 /* XXX: EdwinGrubbs 2009-10-29 bug=463032846 /* XXX: EdwinGrubbs 2009-10-29 bug=463032
826 The reduced padding is only necessary to prevent parts of the847 The reduced padding is only necessary to prevent parts of the
827848
=== added file 'lib/canonical/launchpad/images/gray-arrow-right.png'
828Binary files lib/canonical/launchpad/images/gray-arrow-right.png 1970-01-01 00:00:00 +0000 and lib/canonical/launchpad/images/gray-arrow-right.png 2010-04-09 18:48:33 +0000 differ849Binary files lib/canonical/launchpad/images/gray-arrow-right.png 1970-01-01 00:00:00 +0000 and lib/canonical/launchpad/images/gray-arrow-right.png 2010-04-09 18:48:33 +0000 differ
=== modified file 'lib/canonical/launchpad/pagetests/standalone/xx-form-layout.txt'
--- lib/canonical/launchpad/pagetests/standalone/xx-form-layout.txt 2010-03-26 13:26:12 +0000
+++ lib/canonical/launchpad/pagetests/standalone/xx-form-layout.txt 2010-04-09 18:48:33 +0000
@@ -91,7 +91,8 @@
91Checkboxes have their label to the right. One example is the checkbox for91Checkboxes have their label to the right. One example is the checkbox for
92specifying whether your project uses Launchpad Translations.92specifying whether your project uses Launchpad Translations.
9393
94 >>> admin_browser.open('http://launchpad.dev/evolution/+edit')94 >>> admin_browser.open(
95 ... 'http://launchpad.dev/evolution/+configure-translations')
95 >>> content = find_main_content(admin_browser.contents)96 >>> content = find_main_content(admin_browser.contents)
9697
97 >>> print content98 >>> print content
9899
=== modified file 'lib/lp/blueprints/browser/specificationtarget.py'
--- lib/lp/blueprints/browser/specificationtarget.py 2010-02-19 11:55:02 +0000
+++ lib/lp/blueprints/browser/specificationtarget.py 2010-04-09 18:48:33 +0000
@@ -42,7 +42,7 @@
42from canonical.lazr.utils import smartquote42from canonical.lazr.utils import smartquote
4343
4444
45class HasSpecificationsMenuMixin(object):45class HasSpecificationsMenuMixin:
4646
47 def listall(self):47 def listall(self):
48 """Return a link to show all blueprints."""48 """Return a link to show all blueprints."""
4949
=== modified file 'lib/lp/bugs/stories/bug-also-affects/xx-upstream-bugtracker-links.txt'
--- lib/lp/bugs/stories/bug-also-affects/xx-upstream-bugtracker-links.txt 2009-07-01 13:16:44 +0000
+++ lib/lp/bugs/stories/bug-also-affects/xx-upstream-bugtracker-links.txt 2010-04-09 18:48:33 +0000
@@ -28,7 +28,8 @@
28If we link Thunderbird to an upstream bug tracker, the text will change28If we link Thunderbird to an upstream bug tracker, the text will change
29to reflect this.29to reflect this.
3030
31 >>> admin_browser.open('http://launchpad.dev/thunderbird/+edit')31 >>> admin_browser.open(
32 ... 'http://launchpad.dev/thunderbird/+configure-bugtracker')
32 >>> admin_browser.getControl(33 >>> admin_browser.getControl(
33 ... name='field.bugtracker').value = ['external']34 ... name='field.bugtracker').value = ['external']
34 >>> admin_browser.getControl(35 >>> admin_browser.getControl(
@@ -89,7 +90,8 @@
89If the remote bug tracker is one for which Launchpad doesn't offer a bug90If the remote bug tracker is one for which Launchpad doesn't offer a bug
90filing link, such as Debbugs, only a search link will be displayed.91filing link, such as Debbugs, only a search link will be displayed.
9192
92 >>> admin_browser.open('http://launchpad.dev/gnome-terminal/+edit')93 >>> admin_browser.open(
94 ... 'http://launchpad.dev/gnome-terminal/+configure-bugtracker')
93 >>> admin_browser.getControl(95 >>> admin_browser.getControl(
94 ... 'In a registered bug tracker:').selected = True96 ... 'In a registered bug tracker:').selected = True
95 >>> admin_browser.getControl(97 >>> admin_browser.getControl(
9698
=== modified file 'lib/lp/bugs/stories/bugs/xx-front-page-info.txt'
--- lib/lp/bugs/stories/bugs/xx-front-page-info.txt 2010-03-12 14:26:46 +0000
+++ lib/lp/bugs/stories/bugs/xx-front-page-info.txt 2010-04-09 18:48:33 +0000
@@ -31,7 +31,7 @@
31 >>> enable_tracker = find_tag_by_id(31 >>> enable_tracker = find_tag_by_id(
32 ... admin_browser.contents, 'no-malone-edit')32 ... admin_browser.contents, 'no-malone-edit')
33 >>> print extract_text(enable_tracker)33 >>> print extract_text(enable_tracker)
34 Enable bug tracking.34 Configure bug tracker
3535
36The bugs home page for a project using Launchpad for bug tracking36The bugs home page for a project using Launchpad for bug tracking
37shows controls for setting bug supervisor and states that no37shows controls for setting bug supervisor and states that no
3838
=== modified file 'lib/lp/bugs/stories/bugtracker/bugtrackers-index.txt'
--- lib/lp/bugs/stories/bugtracker/bugtrackers-index.txt 2009-09-23 11:10:00 +0000
+++ lib/lp/bugs/stories/bugtracker/bugtrackers-index.txt 2010-04-09 18:48:33 +0000
@@ -88,7 +88,8 @@
88Let's link a pair to debbugs:88Let's link a pair to debbugs:
8989
90 >>> def link_to_debbugs(name):90 >>> def link_to_debbugs(name):
91 ... admin_browser.open("http://launchpad.dev/%s/+edit" % name)91 ... admin_browser.open(
92 ... "http://launchpad.dev/%s/+configure-bugtracker" % name)
92 ... admin_browser.getControl("In a registered bug tracker").click()93 ... admin_browser.getControl("In a registered bug tracker").click()
93 ... bt = admin_browser.getControl(name="field.bugtracker.bugtracker")94 ... bt = admin_browser.getControl(name="field.bugtracker.bugtracker")
94 ... bt.value = ["3"]95 ... bt.value = ["3"]
9596
=== modified file 'lib/lp/bugs/stories/bugtracker/xx-bugtracker.txt'
--- lib/lp/bugs/stories/bugtracker/xx-bugtracker.txt 2010-04-09 12:00:54 +0000
+++ lib/lp/bugs/stories/bugtracker/xx-bugtracker.txt 2010-04-09 18:48:33 +0000
@@ -672,7 +672,8 @@
672 ... 'A test Bugzilla Tracker']672 ... 'A test Bugzilla Tracker']
673 >>> admin_browser.getControl('Change Details').click()673 >>> admin_browser.getControl('Change Details').click()
674674
675 >>> admin_browser.open('http://launchpad.dev/jokosher/+edit')675 >>> admin_browser.open(
676 ... 'http://launchpad.dev/jokosher/+configure-bugtracker')
676 >>> admin_browser.getControl(name='field.bugtracker'677 >>> admin_browser.getControl(name='field.bugtracker'
677 ... ).displayValue = ['In a registered bug tracker:']678 ... ).displayValue = ['In a registered bug tracker:']
678 >>> admin_browser.getControl(name='field.bugtracker.bugtracker'679 >>> admin_browser.getControl(name='field.bugtracker.bugtracker'
679680
=== modified file 'lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt'
--- lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt 2009-10-30 12:17:48 +0000
+++ lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt 2010-04-09 18:48:33 +0000
@@ -4,14 +4,14 @@
4distributions, product groups, products, and source packages.4distributions, product groups, products, and source packages.
55
6 >>> contexts = [6 >>> contexts = [
7 ... ('Ubuntu', 'ubuntu'),7 ... ('Ubuntu', 'ubuntu', '+edit'),
8 ... ('Mozilla', 'mozilla'),8 ... ('Mozilla', 'mozilla', '+edit'),
9 ... ('Firefox', 'firefox'),9 ... ('Firefox', 'firefox', '+configure-bugtracker'),
10 ... ('alsa-utils in Ubuntu', 'ubuntu/+source/alsa-utils'),10 ... ('alsa-utils in Ubuntu', 'ubuntu/+source/alsa-utils', '+edit'),
11 ... ]11 ... ]
1212
13 >>> for context_name, context_path in contexts:13 >>> for context_name, context_path, view in contexts:
14 ... edit_url = 'http://launchpad.dev/%s/+edit' % (context_path,)14 ... edit_url = 'http://launchpad.dev/%s/%s' % (context_path, view)
15 ... admin_browser.open(edit_url)15 ... admin_browser.open(edit_url)
16 ... admin_browser.getControl(16 ... admin_browser.getControl(
17 ... name='field.bug_reporting_guidelines').value = (17 ... name='field.bug_reporting_guidelines').value = (
@@ -31,7 +31,7 @@
31 ... print extract_text(find_tag_by_id(31 ... print extract_text(find_tag_by_id(
32 ... user_browser.contents, 'bug-reporting-guidelines'))32 ... user_browser.contents, 'bug-reporting-guidelines'))
3333
34 >>> for context_name, context_path in contexts:34 >>> for context_name, context_path, view in contexts:
35 ... filebug_url = (35 ... filebug_url = (
36 ... 'http://launchpad.dev/%s/+filebug' % (context_path,))36 ... 'http://launchpad.dev/%s/+filebug' % (context_path,))
37 ... user_browser.open(filebug_url)37 ... user_browser.open(filebug_url)
@@ -43,7 +43,7 @@
43But they are displayed once you've got to the step of entering a bug43But they are displayed once you've got to the step of entering a bug
44description.44description.
4545
46 >>> for context_name, context_path in contexts:46 >>> for context_name, context_path, view in contexts:
47 ... filebug_url = (47 ... filebug_url = (
48 ... 'http://launchpad.dev/%s/+filebug' % (context_path,))48 ... 'http://launchpad.dev/%s/+filebug' % (context_path,))
49 ... user_browser.open(filebug_url)49 ... user_browser.open(filebug_url)
@@ -143,7 +143,7 @@
143 ... pass143 ... pass
144144
145 >>> edit_url_re = re.compile('/[+]edit$')145 >>> edit_url_re = re.compile('/[+]edit$')
146 >>> for context_name, context_path in contexts:146 >>> for context_name, context_path, view in contexts:
147 ... overview_url = 'http://launchpad.dev/%s' % (context_path,)147 ... overview_url = 'http://launchpad.dev/%s' % (context_path,)
148 ... print '* ' + context_name148 ... print '* ' + context_name
149 ... print ' - User:',149 ... print ' - User:',
@@ -173,8 +173,8 @@
173Unprivileged cannot access the page for changing bug reporting173Unprivileged cannot access the page for changing bug reporting
174guidelines.174guidelines.
175175
176 >>> for context_name, context_path in contexts:176 >>> for context_name, context_path, view in contexts:
177 ... edit_url = 'http://launchpad.dev/%s/+edit' % (context_path,)177 ... edit_url = 'http://launchpad.dev/%s/%s' % (context_path, view)
178 ... print '* ' + context_name178 ... print '* ' + context_name
179 ... try:179 ... try:
180 ... user_browser.open(edit_url)180 ... user_browser.open(edit_url)
181181
=== modified file 'lib/lp/bugs/stories/guided-filebug/xx-no-launchpadder.txt'
--- lib/lp/bugs/stories/guided-filebug/xx-no-launchpadder.txt 2009-07-27 12:39:34 +0000
+++ lib/lp/bugs/stories/guided-filebug/xx-no-launchpadder.txt 2010-04-09 18:48:33 +0000
@@ -52,7 +52,8 @@
52The advice is slightly different if the upstream bug tracker is52The advice is slightly different if the upstream bug tracker is
53actually an email address.53actually an email address.
5454
55 >>> admin_browser.open('http://launchpad.dev/jokosher/+edit')55 >>> admin_browser.open(
56 ... 'http://launchpad.dev/jokosher/+configure-bugtracker')
56 >>> admin_browser.getControl(57 >>> admin_browser.getControl(
57 ... 'By emailing an upstream bug contact').selected = True58 ... 'By emailing an upstream bug contact').selected = True
58 >>> admin_browser.getControl(59 >>> admin_browser.getControl(
5960
=== modified file 'lib/lp/bugs/stories/guided-filebug/xx-project-guided-filebug.txt'
--- lib/lp/bugs/stories/guided-filebug/xx-project-guided-filebug.txt 2010-01-13 15:08:30 +0000
+++ lib/lp/bugs/stories/guided-filebug/xx-project-guided-filebug.txt 2010-04-09 18:48:33 +0000
@@ -217,7 +217,7 @@
217 ... sourcepackagename=thunderbird_spn, distroseries=hoary)217 ... sourcepackagename=thunderbird_spn, distroseries=hoary)
218 >>> logout()218 >>> logout()
219219
220 >>> admin_browser.open('http://launchpad.dev/testy/+edit')220 >>> admin_browser.open('http://launchpad.dev/testy/+configure-bugtracker')
221 >>> admin_browser.getControl(name='field.bugtracker').value = ['external']221 >>> admin_browser.getControl(name='field.bugtracker').value = ['external']
222 >>> admin_browser.getControl(222 >>> admin_browser.getControl(
223 ... name='field.bugtracker.bugtracker').value = ['3']223 ... name='field.bugtracker.bugtracker').value = ['3']
224224
=== modified file 'lib/lp/bugs/stories/initial-bug-contacts/10-set-upstream-bugcontact.txt'
--- lib/lp/bugs/stories/initial-bug-contacts/10-set-upstream-bugcontact.txt 2010-01-19 16:37:15 +0000
+++ lib/lp/bugs/stories/initial-bug-contacts/10-set-upstream-bugcontact.txt 2010-04-09 18:48:33 +0000
@@ -122,9 +122,9 @@
122We can change the settings to use Launchpad for bug tracking.122We can change the settings to use Launchpad for bug tracking.
123123
124 >>> sample_browser.getLink(124 >>> sample_browser.getLink(
125 ... 'Enable bug tracking.').click()125 ... 'Configure bug tracker').click()
126 >>> print sample_browser.title126 >>> print sample_browser.title
127 Change A product for testing things's details : Bugs : Test Product127 Configure bug tracker : Bugs : Test Product
128 >>> sample_browser.getControl('In Launchpad').click()128 >>> sample_browser.getControl('In Launchpad').click()
129 >>> sample_browser.getControl('Change').click()129 >>> sample_browser.getControl('Change').click()
130130
131131
=== modified file 'lib/lp/bugs/templates/bugtarget-bugs.pt'
--- lib/lp/bugs/templates/bugtarget-bugs.pt 2010-03-04 15:09:10 +0000
+++ lib/lp/bugs/templates/bugtarget-bugs.pt 2010-04-09 18:48:33 +0000
@@ -169,9 +169,14 @@
169 bug tracking.</strong></p>169 bug tracking.</strong></p>
170170
171 <p tal:condition="context/required:launchpad.Edit"171 <p tal:condition="context/required:launchpad.Edit"
172 id="no-malone-edit">172 id="no-malone-edit"
173 <a tal:attributes="href string:${context/fmt:url/+edit}">Enable173 tal:define ="configure_bugtracker context/menu:overview/configure_bugtracker | nothing"
174 bug tracking.</a>174 >
175 <a tal:condition="configure_bugtracker"
176 tal:replace="structure configure_bugtracker/fmt:link"/>
177 <a tal:condition="not: configure_bugtracker"
178 tal:attributes="href string:${context/fmt:url/+edit}">
179 Enable bug tracking.</a>
175 </p>180 </p>
176 </tal:not_uses_malone>181 </tal:not_uses_malone>
177182
178183
=== modified file 'lib/lp/bugs/templates/bugtarget-macros-filebug.pt'
--- lib/lp/bugs/templates/bugtarget-macros-filebug.pt 2009-12-04 12:12:35 +0000
+++ lib/lp/bugs/templates/bugtarget-macros-filebug.pt 2010-04-09 18:48:33 +0000
@@ -143,7 +143,7 @@
143 <div class="highlight-message">143 <div class="highlight-message">
144 <a tal:replace="structure product_or_distro/fmt:link">Alsa Utils</a>144 <a tal:replace="structure product_or_distro/fmt:link">Alsa Utils</a>
145 <strong>does not use</strong> Launchpad as its bug tracker.145 <strong>does not use</strong> Launchpad as its bug tracker.
146 <a tal:attributes="href context/menu:overview/edit/fmt:url"146 <a tal:attributes="href context/menu:overview/configure_bugtracker/fmt:url"
147 tal:condition="context/required:launchpad.Edit">147 tal:condition="context/required:launchpad.Edit">
148 Change this&nbsp;<span class="sprite edit"></span>148 Change this&nbsp;<span class="sprite edit"></span>
149 </a>149 </a>
150150
=== modified file 'lib/lp/code/stories/branches/xx-branch-tag-cloud.txt'
--- lib/lp/code/stories/branches/xx-branch-tag-cloud.txt 2009-08-28 05:57:37 +0000
+++ lib/lp/code/stories/branches/xx-branch-tag-cloud.txt 2010-04-09 18:48:33 +0000
@@ -22,11 +22,13 @@
2222
23Update firefox to officially use codehosting:23Update firefox to officially use codehosting:
2424
25 >>> admin_browser.open('http://launchpad.dev/firefox/+edit')25 >>> from lp.registry.interfaces.product import IProductSet
26 >>> admin_browser.getControl(26 >>> from zope.component import getUtility
27 ... 'Code for this project is published in Bazaar branches on '27 >>> login('admin@canonical.com')
28 ... 'Launchpad').click()28 >>> firefox = getUtility(IProductSet).getByName('firefox')
29 >>> admin_browser.getControl('Change').click()29 >>> firefox.development_focus.branch = factory.makeBranch(
30 ... product=firefox)
31 >>> logout()
3032
31The class for firefox in the project tag cloud will now show 'highlight' rather33The class for firefox in the project tag cloud will now show 'highlight' rather
32than shade.34than shade.
3335
=== modified file 'lib/lp/code/stories/branches/xx-product-branches.txt'
--- lib/lp/code/stories/branches/xx-product-branches.txt 2010-01-08 14:22:42 +0000
+++ lib/lp/code/stories/branches/xx-product-branches.txt 2010-04-09 18:48:33 +0000
@@ -158,10 +158,18 @@
158There are two buttons that show on the right hand side of the screen158There are two buttons that show on the right hand side of the screen
159for project branch listings. 'Register a branch' and 'Import your project'.159for project branch listings. 'Register a branch' and 'Import your project'.
160160
161 >>> from zope.component import getUtility
162 >>> from lp.registry.interfaces.product import IProductSet
163 >>> login('admin@canonical.com')
164 >>> product = getUtility(IProductSet).getByName('firefox')
165 >>> old_branch = product.development_focus.branch
166 >>> product.development_focus.branch = None
167 >>> logout()
161 >>> def print_links(browser):168 >>> def print_links(browser):
162 ... links = find_tag_by_id(browser.contents, 'floating-links')169 ... links = find_tag_by_id(browser.contents, 'floating-links')
163 ... for link in links.findAll('a'):170 ... for link in links.findAll('a'):
164 ... print extract_text(link)171 ... print extract_text(link)
172 >>> browser.open('http://code.launchpad.dev/firefox')
165 >>> print_links(browser)173 >>> print_links(browser)
166 Register a branch174 Register a branch
167 Import your project175 Import your project
@@ -169,14 +177,10 @@
169If the product specifies that it officially uses Launchpad code, then177If the product specifies that it officially uses Launchpad code, then
170the 'Import your project' button is not shown.178the 'Import your project' button is not shown.
171179
172 >>> admin_browser.open('http://launchpad.dev/gnome-terminal')180 >>> login('admin@canonical.com')
173 >>> admin_browser.getLink('Change details').click()181 >>> product.development_focus.branch = old_branch
174 >>> admin_browser.getControl(182 >>> logout()
175 ... 'Code for this project is published in Bazaar branches '183 >>> browser.open('http://code.launchpad.dev/firefox')
176 ... 'on Launchpad').click()
177 >>> admin_browser.getControl('Change').click()
178
179 >>> browser.open('http://code.launchpad.dev/gnome-terminal')
180 >>> print_links(browser)184 >>> print_links(browser)
181 Register a branch185 Register a branch
182186
183187
=== modified file 'lib/lp/registry/browser/configure.zcml'
--- lib/lp/registry/browser/configure.zcml 2010-04-06 18:49:52 +0000
+++ lib/lp/registry/browser/configure.zcml 2010-04-09 18:48:33 +0000
@@ -495,6 +495,20 @@
495 facet="overview"495 facet="overview"
496 permission="zope.Public"496 permission="zope.Public"
497 template="../templates/pillar-involvement-portlet.pt"/>497 template="../templates/pillar-involvement-portlet.pt"/>
498 <browser:page
499 name="+get-involved"
500 for="lp.registry.interfaces.product.IProduct"
501 class="lp.registry.browser.pillar.ProductInvolvementView"
502 facet="overview"
503 permission="zope.Public"
504 template="../templates/pillar-involvement-portlet.pt"/>
505 <browser:page
506 name="+get-involved"
507 for="lp.registry.interfaces.product.IProductSeries"
508 class="lp.registry.browser.pillar.ProductSeriesInvolvementView"
509 facet="overview"
510 permission="zope.Public"
511 template="../templates/pillar-involvement-portlet.pt"/>
498 <facet512 <facet
499 facet="overview">513 facet="overview">
500 <browser:url514 <browser:url
@@ -1458,6 +1472,34 @@
1458 permission="launchpad.Edit"1472 permission="launchpad.Edit"
1459 template="../../app/templates/generic-edit.pt"/>1473 template="../../app/templates/generic-edit.pt"/>
1460 <browser:page1474 <browser:page
1475 for="lp.registry.interfaces.product.IProduct"
1476 facet="overview"
1477 permission="launchpad.Edit"
1478 name="+configure-answers"
1479 template="../../app/templates/generic-edit.pt"
1480 class="lp.registry.browser.product.ProductConfigureAnswersView"/>
1481 <browser:page
1482 for="lp.registry.interfaces.product.IProduct"
1483 facet="overview"
1484 permission="launchpad.Edit"
1485 name="+configure-blueprints"
1486 template="../../app/templates/generic-edit.pt"
1487 class="lp.registry.browser.product.ProductConfigureBlueprintsView"/>
1488 <browser:page
1489 for="lp.registry.interfaces.product.IProduct"
1490 facet="overview"
1491 permission="launchpad.Edit"
1492 name="+configure-bugtracker"
1493 template="../../app/templates/generic-edit.pt"
1494 class="lp.registry.browser.product.ProductConfigureBugTrackerView"/>
1495 <browser:page
1496 for="lp.registry.interfaces.product.IProduct"
1497 facet="overview"
1498 permission="launchpad.Edit"
1499 name="+configure-translations"
1500 template="../../app/templates/generic-edit.pt"
1501 class="lp.registry.browser.product.ProductConfigureTranslationsView"/>
1502 <browser:page
1461 name="+branding"1503 name="+branding"
1462 for="lp.registry.interfaces.product.IProduct"1504 for="lp.registry.interfaces.product.IProduct"
1463 facet="overview"1505 facet="overview"
14641506
=== modified file 'lib/lp/registry/browser/pillar.py'
--- lib/lp/registry/browser/pillar.py 2010-02-17 11:19:42 +0000
+++ lib/lp/registry/browser/pillar.py 2010-04-09 18:48:33 +0000
@@ -15,6 +15,7 @@
15from zope.component.globalregistry import provideAdapter15from zope.component.globalregistry import provideAdapter
16from zope.interface import implements, Interface16from zope.interface import implements, Interface
1717
18from canonical.cachedproperty import cachedproperty
18from canonical.launchpad.webapp.interfaces import INavigationMenu19from canonical.launchpad.webapp.interfaces import INavigationMenu
19from canonical.launchpad.webapp.menu import Link, NavigationMenu20from canonical.launchpad.webapp.menu import Link, NavigationMenu
20from canonical.launchpad.webapp.publisher import LaunchpadView, nearest21from canonical.launchpad.webapp.publisher import LaunchpadView, nearest
@@ -24,7 +25,6 @@
24from lp.registry.interfaces.distributionsourcepackage import (25from lp.registry.interfaces.distributionsourcepackage import (
25 IDistributionSourcePackage)26 IDistributionSourcePackage)
26from lp.registry.interfaces.pillar import IPillar27from lp.registry.interfaces.pillar import IPillar
27from lp.registry.interfaces.productseries import IProductSeries
28from lp.registry.interfaces.projectgroup import IProjectGroup28from lp.registry.interfaces.projectgroup import IProjectGroup
2929
3030
@@ -69,6 +69,9 @@
69 """A view for any `IPillar`."""69 """A view for any `IPillar`."""
70 implements(IInvolved)70 implements(IInvolved)
7171
72 configuration_links = []
73 visible_disabled_link_names = []
74
72 def __init__(self, context, request):75 def __init__(self, context, request):
73 super(PillarView, self).__init__(context, request)76 super(PillarView, self).__init__(context, request)
74 self.official_malone = False77 self.official_malone = False
@@ -85,9 +88,7 @@
85 self.official_codehosting = False88 self.official_codehosting = False
86 else:89 else:
87 self._set_official_launchpad(pillar)90 self._set_official_launchpad(pillar)
88 if IProductSeries.providedBy(self.context):91 if IDistroSeries.providedBy(self.context):
89 self.official_answers = False
90 elif IDistroSeries.providedBy(self.context):
91 self.official_answers = False92 self.official_answers = False
92 self.official_codehosting = False93 self.official_codehosting = False
93 elif IDistributionSourcePackage.providedBy(self.context):94 elif IDistributionSourcePackage.providedBy(self.context):
@@ -128,6 +129,73 @@
128 link for link in menuapi.navigation.values() if link.enabled],129 link for link in menuapi.navigation.values() if link.enabled],
129 key=attrgetter('sort_key'))130 key=attrgetter('sort_key'))
130131
132 @cachedproperty
133 def visible_disabled_links(self):
134 """Important disabled links.
135
136 These are displayed to notify the user to provide configuration
137 info to enable the links.
138
139 Override the visible_disabled_link_names attribute to change
140 the results.
141 """
142 involved_menu = MenuAPI(self).navigation
143 important_links = [
144 involved_menu[name]
145 for name in self.visible_disabled_link_names]
146 return sorted([
147 link for link in important_links if not link.enabled],
148 key=attrgetter('sort_key'))
149
131150
132provideAdapter(151provideAdapter(
133 InvolvedMenu, [IInvolved], INavigationMenu, name="overview")152 InvolvedMenu, [IInvolved], INavigationMenu, name="overview")
153
154
155# This class can't be moved into the browser/product.py file, since
156# the pillar-views.txt test will fail due to the MenuAPI adapter
157# for PillarView.enabled_links not working.
158class ProductInvolvementView(PillarView):
159 """Encourage configuration of involvement links for projects."""
160
161 has_involvement = True
162 visible_disabled_link_names = ['submit_code']
163
164 @property
165 def configuration_links(self):
166 """The enabled involvement links."""
167 overview_menu = MenuAPI(self.context).overview
168 series_menu = MenuAPI(self.context.development_focus).overview
169 configuration_names = [
170 'configure_answers',
171 'configure_bugtracker',
172 'configure_translations',
173 ]
174 configuration_links = [
175 overview_menu[name] for name in configuration_names]
176 set_branch = series_menu['set_branch']
177 set_branch.text = 'Configure project branch'
178 configuration_links.append(set_branch)
179 return sorted([
180 link for link in configuration_links if link.enabled],
181 key=attrgetter('sort_key'))
182
183
184class ProductSeriesInvolvementView(PillarView):
185 """Encourage configuration of involvement links for project series."""
186
187 has_involvement = True
188 visible_disabled_link_names = ['submit_code']
189
190 def __init__(self, context, request):
191 super(ProductSeriesInvolvementView, self).__init__(context, request)
192 self.official_codehosting = self.context.branch is not None
193 self.official_answers = False
194
195 @property
196 def configuration_links(self):
197 """The enabled involvement links."""
198 series_menu = MenuAPI(self.context).overview
199 set_branch = series_menu['set_branch']
200 set_branch.text = 'Configure series branch'
201 return [set_branch]
134202
=== modified file 'lib/lp/registry/browser/product.py'
--- lib/lp/registry/browser/product.py 2010-04-06 20:25:12 +0000
+++ lib/lp/registry/browser/product.py 2010-04-09 18:48:33 +0000
@@ -12,11 +12,17 @@
12 'ProductAdminView',12 'ProductAdminView',
13 'ProductBrandingView',13 'ProductBrandingView',
14 'ProductBugsMenu',14 'ProductBugsMenu',
15 'ProductConfigureAnswersView',
16 'ProductConfigureBlueprintsView',
17 'ProductConfigureBranchesView',
18 'ProductConfigureBugTrackerView',
19 'ProductConfigureTranslationsView',
15 'ProductDownloadFileMixin',20 'ProductDownloadFileMixin',
16 'ProductDownloadFilesView',21 'ProductDownloadFilesView',
17 'ProductEditPeopleView',22 'ProductEditPeopleView',
18 'ProductEditView',23 'ProductEditView',
19 'ProductFacets',24 'ProductFacets',
25 'ProductInvolvementView',
20 'ProductNavigation',26 'ProductNavigation',
21 'ProductNavigationMenu',27 'ProductNavigationMenu',
22 'ProductOverviewMenu',28 'ProductOverviewMenu',
@@ -331,6 +337,30 @@
331 return Link('+edit', text, icon='edit')337 return Link('+edit', text, icon='edit')
332338
333 @enabled_with_permission('launchpad.Edit')339 @enabled_with_permission('launchpad.Edit')
340 def configure_bugtracker(self):
341 text = 'Configure bug tracker'
342 summary = 'Specify where bugs are tracked for this project'
343 return Link('+configure-bugtracker', text, summary, icon='edit')
344
345 @enabled_with_permission('launchpad.Edit')
346 def configure_translations(self):
347 text = 'Configure translations'
348 summary = 'Allow users to submit translations for this project'
349 return Link('+configure-translations', text, summary, icon='edit')
350
351 @enabled_with_permission('launchpad.Edit')
352 def configure_answers(self):
353 text = 'Configure support tracker'
354 summary = 'Allow users to ask questions on this project'
355 return Link('+configure-answers', text, summary, icon='edit')
356
357 @enabled_with_permission('launchpad.Edit')
358 def configure_blueprints(self):
359 text = 'Configure blueprints'
360 summary = 'Enable tracking of specifications and meetings'
361 return Link('+configure-blueprints', text, summary, icon='edit')
362
363 @enabled_with_permission('launchpad.Edit')
334 def branding(self):364 def branding(self):
335 text = 'Change branding'365 text = 'Change branding'
336 return Link('+branding', text, icon='edit')366 return Link('+branding', text, icon='edit')
@@ -374,6 +404,10 @@
374 facet = 'overview'404 facet = 'overview'
375 links = [405 links = [
376 'edit',406 'edit',
407 'configure_answers',
408 'configure_blueprints',
409 'configure_bugtracker',
410 'configure_translations',
377 'reassign',411 'reassign',
378 'top_contributors',412 'top_contributors',
379 'distributions',413 'distributions',
@@ -473,11 +507,12 @@
473 return Link('+securitycontact', text, icon='edit')507 return Link('+securitycontact', text, icon='edit')
474508
475509
476class ProductSpecificationsMenu(NavigationMenu,510class ProductSpecificationsMenu(NavigationMenu, ProductEditLinksMixin,
477 HasSpecificationsMenuMixin):511 HasSpecificationsMenuMixin):
478 usedfor = IProduct512 usedfor = IProduct
479 facet = 'specifications'513 facet = 'specifications'
480 links = ['listall', 'doc', 'assignments', 'new', 'register_sprint']514 links = ['configure_blueprints', 'listall', 'doc', 'assignments', 'new',
515 'register_sprint']
481516
482517
483def _cmp_distros(a, b):518def _cmp_distros(a, b):
@@ -1145,6 +1180,70 @@
1145 return canonical_url(self.context)1180 return canonical_url(self.context)
11461181
11471182
1183class ProductConfigureBase(ReturnToReferrerMixin, LaunchpadEditFormView):
1184 implements(IProductEditMenu)
1185 schema = IProduct
1186
1187 @property
1188 def page_title(self):
1189 return self.label
1190
1191 @action("Change", name='change')
1192 def change_action(self, action, data):
1193 self.updateContextFromData(data)
1194
1195
1196class ProductConfigureBugTrackerView(ProductConfigureBase):
1197 """View class to configure the bug tracker for a project."""
1198
1199 label = "Configure bug tracker"
1200 field_names = [
1201 "bugtracker",
1202 "enable_bug_expiration",
1203 "remote_product",
1204 "bug_reporting_guidelines",
1205 ]
1206 custom_widget('bugtracker', ProductBugTrackerWidget)
1207
1208 def validate(self, data):
1209 """Constrain bug expiration to Launchpad Bugs tracker."""
1210 # enable_bug_expiration is disabled by JavaScript when bugtracker
1211 # is not 'In Launchpad'. The constraint is enforced here in case the
1212 # JavaScript fails to activate or run. Note that the bugtracker
1213 # name : values are {'In Launchpad' : object, 'Somewhere else' : None
1214 # 'In a registered bug tracker' : IBugTracker}.
1215 bugtracker = data.get('bugtracker', None)
1216 if bugtracker is None or IBugTracker.providedBy(bugtracker):
1217 data['enable_bug_expiration'] = False
1218
1219
1220class ProductConfigureBlueprintsView(ProductConfigureBase):
1221 """View class to configure the Launchpad Blueprints for a project."""
1222
1223 label = "Configure Blueprints"
1224 field_names = [
1225 "official_blueprints",
1226 ]
1227
1228
1229class ProductConfigureTranslationsView(ProductConfigureBase):
1230 """View class to configure the Launchpad Translations for a project."""
1231
1232 label = "Configure Translations"
1233 field_names = [
1234 "official_rosetta",
1235 ]
1236
1237
1238class ProductConfigureAnswersView(ProductConfigureBase):
1239 """View class to configure the Launchpad Answers for a project."""
1240
1241 label = "Configure Answers"
1242 field_names = [
1243 "official_answers",
1244 ]
1245
1246
1148class ProductEditView(ProductLicenseMixin, LaunchpadEditFormView):1247class ProductEditView(ProductLicenseMixin, LaunchpadEditFormView):
1149 """View class that lets you edit a Product object."""1248 """View class that lets you edit a Product object."""
11501249
@@ -1157,15 +1256,7 @@
1157 "title",1256 "title",
1158 "summary",1257 "summary",
1159 "description",1258 "description",
1160 "bug_reporting_guidelines",
1161 "project",1259 "project",
1162 "official_codehosting",
1163 "bugtracker",
1164 "enable_bug_expiration",
1165 "official_blueprints",
1166 "official_rosetta",
1167 "official_answers",
1168 "remote_product",
1169 "homepageurl",1260 "homepageurl",
1170 "sourceforgeproject",1261 "sourceforgeproject",
1171 "freshmeatproject",1262 "freshmeatproject",
@@ -1178,7 +1269,6 @@
1178 "license_info",1269 "license_info",
1179 ]1270 ]
1180 custom_widget('licenses', LicenseWidget)1271 custom_widget('licenses', LicenseWidget)
1181 custom_widget('bugtracker', ProductBugTrackerWidget)
1182 custom_widget('license_info', GhostWidget)1272 custom_widget('license_info', GhostWidget)
11831273
1184 @property1274 @property
@@ -1206,18 +1296,6 @@
1206 return False1296 return False
1207 return super(ProductEditView, self).showOptionalMarker(field_name)1297 return super(ProductEditView, self).showOptionalMarker(field_name)
12081298
1209 def validate(self, data):
1210 """Constrain bug expiration to Launchpad Bugs tracker."""
1211 # enable_bug_expiration is disabled by JavaScript when bugtracker
1212 # is not 'In Launchpad'. The contraint is enforced here in case the
1213 # JavaScript fails to activate or run. Note that the bugtracker
1214 # name : values are {'In Launchpad' : object, 'Somewhere else' : None
1215 # 'In a registered bug tracker' : IBugTracker}.
1216 bugtracker = data.get('bugtracker', None)
1217 if bugtracker is None or IBugTracker.providedBy(bugtracker):
1218 data['enable_bug_expiration'] = False
1219 ProductLicenseMixin.validate(self, data)
1220
1221 @action("Change", name='change')1299 @action("Change", name='change')
1222 def change_action(self, action, data):1300 def change_action(self, action, data):
1223 previous_licenses = self.context.licenses1301 previous_licenses = self.context.licenses
12241302
=== modified file 'lib/lp/registry/browser/productseries.py'
--- lib/lp/registry/browser/productseries.py 2010-04-08 19:04:48 +0000
+++ lib/lp/registry/browser/productseries.py 2010-04-09 18:48:33 +0000
@@ -81,7 +81,8 @@
81from canonical.launchpad.webapp.interfaces import (81from canonical.launchpad.webapp.interfaces import (
82 NotFoundError, UnexpectedFormData)82 NotFoundError, UnexpectedFormData)
83from canonical.launchpad.webapp.launchpadform import (83from canonical.launchpad.webapp.launchpadform import (
84 action, custom_widget, LaunchpadEditFormView, LaunchpadFormView)84 action, custom_widget, LaunchpadEditFormView, LaunchpadFormView,
85 ReturnToReferrerMixin)
85from canonical.launchpad.webapp.menu import structured86from canonical.launchpad.webapp.menu import structured
86from canonical.widgets.itemswidgets import LaunchpadRadioWidget87from canonical.widgets.itemswidgets import LaunchpadRadioWidget
87from canonical.widgets.textwidgets import StrippedTextWidget88from canonical.widgets.textwidgets import StrippedTextWidget
@@ -175,6 +176,7 @@
175 links = [176 links = [
176 'edit', 'delete', 'driver', 'link_branch', 'branch_add', 'ubuntupkg',177 'edit', 'delete', 'driver', 'link_branch', 'branch_add', 'ubuntupkg',
177 'create_milestone', 'create_release', 'rdf', 'subscribe',178 'create_milestone', 'create_release', 'rdf', 'subscribe',
179 'set_branch',
178 ]180 ]
179181
180 @enabled_with_permission('launchpad.Edit')182 @enabled_with_permission('launchpad.Edit')
@@ -211,6 +213,21 @@
211 summary = 'Change the branch for this series'213 summary = 'Change the branch for this series'
212 return Link('+linkbranch', text, summary, icon=icon)214 return Link('+linkbranch', text, summary, icon=icon)
213215
216 @enabled_with_permission('launchpad.Edit')
217 def set_branch(self):
218 """Return a link to set the bazaar branch for this series."""
219 # Once +setbranch has been beta tested thoroughly, it should
220 # replace the +linkbranch page.
221 if self.context.branch is None:
222 text = 'Link to branch'
223 icon = 'add'
224 summary = 'Set the branch for this series'
225 else:
226 text = "Change branch"
227 icon = 'edit'
228 summary = 'Change the branch for this series'
229 return Link('+setbranch', text, summary, icon=icon)
230
214 def branch_add(self):231 def branch_add(self):
215 text = 'Register a branch'232 text = 'Register a branch'
216 summary = "Register a new Bazaar branch for this series' project"233 summary = "Register a new Bazaar branch for this series' project"
@@ -734,7 +751,8 @@
734 )751 )
735752
736753
737class ProductSeriesSetBranchView(LaunchpadFormView, ProductSeriesView,754class ProductSeriesSetBranchView(ReturnToReferrerMixin, LaunchpadFormView,
755 ProductSeriesView,
738 BranchNameValidationMixin):756 BranchNameValidationMixin):
739 """The view to set a branch for the ProductSeries."""757 """The view to set a branch for the ProductSeries."""
740758
@@ -919,7 +937,6 @@
919937
920 @action(_('Update'), name='update')938 @action(_('Update'), name='update')
921 def update_action(self, action, data):939 def update_action(self, action, data):
922 self.next_url = canonical_url(self.context)
923 branch_type = data.get('branch_type')940 branch_type = data.get('branch_type')
924 if branch_type == LINK_LP_BZR:941 if branch_type == LINK_LP_BZR:
925 branch_location = data.get('branch_location')942 branch_location = data.get('branch_location')
@@ -1011,13 +1028,10 @@
1011 self._setBranchExists(e.existing_branch, 'branch_name')1028 self._setBranchExists(e.existing_branch, 'branch_name')
1012 return branch1029 return branch
10131030
1014 @property1031
1015 def cancel_url(self):1032class ProductSeriesLinkBranchView(ReturnToReferrerMixin,
1016 """See `LaunchpadFormView`."""1033 ProductSeriesView,
1017 return canonical_url(self.context)1034 LaunchpadEditFormView):
1018
1019
1020class ProductSeriesLinkBranchView(LaunchpadEditFormView, ProductSeriesView):
1021 """View to set the bazaar branch for a product series."""1035 """View to set the bazaar branch for a product series."""
10221036
1023 schema = IProductSeries1037 schema = IProductSeries
@@ -1034,11 +1048,6 @@
1034 """The page title."""1048 """The page title."""
1035 return self.label1049 return self.label
10361050
1037 @property
1038 def next_url(self):
1039 """See `LaunchpadFormView`."""
1040 return canonical_url(self.context)
1041
1042 @action(_('Update'), name='update')1051 @action(_('Update'), name='update')
1043 def update_action(self, action, data):1052 def update_action(self, action, data):
1044 """Update the branch attribute."""1053 """Update the branch attribute."""
@@ -1052,11 +1061,6 @@
1052 self.request.response.addInfoNotification(1061 self.request.response.addInfoNotification(
1053 'Series code location updated.')1062 'Series code location updated.')
10541063
1055 @property
1056 def cancel_url(self):
1057 """See `LaunchpadFormView`."""
1058 return canonical_url(self.context)
1059
10601064
1061class ProductSeriesLinkBranchFromCodeView(ProductSeriesLinkBranchView):1065class ProductSeriesLinkBranchFromCodeView(ProductSeriesLinkBranchView):
1062 """Set the branch link from the code overview page."""1066 """Set the branch link from the code overview page."""
10631067
=== modified file 'lib/lp/registry/browser/tests/pillar-views.txt'
--- lib/lp/registry/browser/tests/pillar-views.txt 2009-09-03 19:26:16 +0000
+++ lib/lp/registry/browser/tests/pillar-views.txt 2010-04-09 18:48:33 +0000
@@ -49,19 +49,19 @@
49 report_bug ask_question49 report_bug ask_question
5050
51 >>> print view.render()51 >>> print view.render()
52 <div id="involvement" class="portlet involvement">52 <div id="involvement" class="portlet">
53 <h2>Get Involved</h2>53 <h2>Get Involved</h2>
54 <ul>54 <ul class="involvement">
55 <li>55 <li>
56 <a href="..." class="...bugs">Report a bug</a>56 <a href=... class="...bugs">Report a bug</a>
57 </li>57 </li>
58 <li>58 <li>
59 <a href="..." class="...answers">Ask a question</a>59 <a href=... class="...answers">Ask a question</a>
60 </li>60 </li>
61 </ul>61 </ul>
62 </div>62 ...
6363
64Products are are supported.64Products are supported.
6565
66 >>> product = factory.makeProduct(name='bread')66 >>> product = factory.makeProduct(name='bread')
67 >>> login_person(product.owner)67 >>> login_person(product.owner)
@@ -69,6 +69,24 @@
69 >>> view = create_view(product, '+get-involved')69 >>> view = create_view(product, '+get-involved')
70 >>> view.official_blueprints70 >>> view.official_blueprints
71 True71 True
72 >>> for link in view.enabled_links:
73 ... print link.name
74 register_blueprint
75
76Products subclass the view to display disabled links to encourage
77configuring that service in Launchpad for the project. The project
78also has configuration links that make it easy to figure out where
79to configure each service.
80
81 >>> for link in view.visible_disabled_links:
82 ... print link.name
83 submit_code
84 >>> for link in view.configuration_links:
85 ... print link.name
86 configure_answers
87 configure_bugtracker
88 configure_translations
89 set_branch
7290
73Project are supported too, but they only display the applications used by91Project are supported too, but they only display the applications used by
74their products.92their products.
@@ -80,13 +98,27 @@
80 >>> view.official_blueprints98 >>> view.official_blueprints
81 True99 True
82100
83Projects cannot make links to register a branch, so official_code is always101The offical_codehosting for a project is based on whether the project's
84false.102development focus series has a branch.
85103
86 >>> product.official_codehosting = True104 >>> print product.development_focus.branch
87 >>> view = create_view(product, '+get-involved')105 None
88 >>> view.official_codehosting106 >>> product.official_codehosting
89 True107 False
108 >>> view = create_view(product, '+get-involved')
109 >>> view.official_codehosting
110 False
111
112 >>> product.development_focus.branch = factory.makeBranch(
113 ... product=product)
114 >>> product.official_codehosting
115 True
116 >>> view = create_view(product, '+get-involved')
117 >>> view.official_codehosting
118 True
119
120Project groups cannot make links to register a branch, so
121official_codehosting is always false.
90122
91 >>> view = create_view(project_group, '+get-involved')123 >>> view = create_view(project_group, '+get-involved')
92 >>> view.official_codehosting124 >>> view.official_codehosting
@@ -108,7 +140,7 @@
108 >>> view = create_view(series, '+get-involved')140 >>> view = create_view(series, '+get-involved')
109 >>> for link in view.enabled_links:141 >>> for link in view.enabled_links:
110 ... print link.name142 ... print link.name
111 submit_code register_blueprint143 register_blueprint
112144
113DistributionSourcePackages can use this view. The distribution is used to145DistributionSourcePackages can use this view. The distribution is used to
114set the links. Despite the fact that the distribution uses blueprints,146set the links. Despite the fact that the distribution uses blueprints,
115147
=== modified file 'lib/lp/registry/doc/product.txt'
--- lib/lp/registry/doc/product.txt 2009-12-13 11:55:40 +0000
+++ lib/lp/registry/doc/product.txt 2010-04-09 18:48:33 +0000
@@ -455,12 +455,15 @@
455455
456== Products With Branches ==456== Products With Branches ==
457457
458Products can now specify whether they officially support Launchpad as a458Products are considered to officially support Launchpad as a location
459location for their branches.459for their branches after a branch is set for the development focus
460series.
460461
462 >>> print firefox.development_focus.branch
463 None
461 >>> print firefox.official_codehosting464 >>> print firefox.official_codehosting
462 False465 False
463 >>> firefox.official_codehosting = True466 >>> firefox.development_focus.branch = factory.makeBranch(product=firefox)
464 >>> print firefox.official_codehosting467 >>> print firefox.official_codehosting
465 True468 True
466469
467470
=== modified file 'lib/lp/registry/model/product.py'
--- lib/lp/registry/model/product.py 2010-04-08 19:27:14 +0000
+++ lib/lp/registry/model/product.py 2010-04-09 18:48:33 +0000
@@ -246,8 +246,6 @@
246 dbName='official_answers', notNull=True, default=False)246 dbName='official_answers', notNull=True, default=False)
247 official_blueprints = BoolCol(247 official_blueprints = BoolCol(
248 dbName='official_blueprints', notNull=True, default=False)248 dbName='official_blueprints', notNull=True, default=False)
249 official_codehosting = BoolCol(
250 dbName='official_codehosting', notNull=True, default=False)
251 official_malone = BoolCol(249 official_malone = BoolCol(
252 dbName='official_malone', notNull=True, default=False)250 dbName='official_malone', notNull=True, default=False)
253 official_rosetta = BoolCol(251 official_rosetta = BoolCol(
@@ -256,6 +254,12 @@
256 name='remote_product', allow_none=True, default=None)254 name='remote_product', allow_none=True, default=None)
257 max_bug_heat = Int()255 max_bug_heat = Int()
258256
257 @property
258 def official_codehosting(self):
259 # XXX Need to remove official_codehosting column from Product
260 # table.
261 return self.development_focus.branch is not None
262
259 def _getMilestoneCondition(self):263 def _getMilestoneCondition(self):
260 """See `HasMilestonesMixin`."""264 """See `HasMilestonesMixin`."""
261 return (Milestone.product == self)265 return (Milestone.product == self)
262266
=== modified file 'lib/lp/registry/stories/product/xx-product-development-focus.txt'
--- lib/lp/registry/stories/product/xx-product-development-focus.txt 2009-11-18 04:51:08 +0000
+++ lib/lp/registry/stories/product/xx-product-development-focus.txt 2010-04-09 18:48:33 +0000
@@ -32,6 +32,12 @@
32 ... print content32 ... print content
33 ... title = a.get('title', '')33 ... title = a.get('title', '')
34 ... print "%s (%s)" % (title, a['href'])34 ... print "%s (%s)" % (title, a['href'])
35 >>> def print_involvement_portlet(browser):
36 ... involvement = find_tag_by_id(browser.contents, 'involvement')
37 ... for a in involvement.findAll('a'):
38 ... for content in a.contents:
39 ... print content
40 ... print a['href']
3541
3642
37Projects without development focus branches43Projects without development focus branches
@@ -39,48 +45,59 @@
3945
40If the project has not specified a development focus branch then the46If the project has not specified a development focus branch then the
41development focus section just contains a link to the development focus47development focus section just contains a link to the development focus
42series, and text telling the user that no branch has been specified.48series.
4349
44 >>> anon_browser.open('http://launchpad.dev/fooix')50 >>> anon_browser.open('http://launchpad.dev/fooix')
45 >>> print_development_focus(anon_browser)51 >>> print_development_focus(anon_browser)
46 Development focus:52 Development focus:
47 trunk series53 trunk series
48 Development focus branch has not been specified
49 Links:54 Links:
50 trunk series (/fooix/trunk)55 trunk series (/fooix/trunk)
56 >>> print_involvement_portlet(anon_browser)
5157
5258
53Setting the development focus branch59Setting the development focus branch
54------------------------------------60------------------------------------
5561
56If the user has rights to change the development focus or to specify the62If the user has rights to change the development focus or to specify the
57development focus branch, then these links are shown next to the text.63development focus branch, then these links are shown in the involvement
64portlet.
5865
59 >>> owner_browser.open('http://launchpad.dev/fooix')66 >>> owner_browser.open('http://launchpad.dev/fooix')
60 >>> print_development_focus(owner_browser)67 >>> print_development_focus(owner_browser)
61 Development focus:68 Development focus:
62 trunk series Change details69 trunk series Change details
63 Development focus branch has not been specified Link to branch
64 Links:70 Links:
65 trunk series (/fooix/trunk)71 trunk series
66 <span class="invisible-link">Change details</span>72 (/fooix/trunk)
67 (http://launchpad.dev/fooix/+edit)73 <span class="invisible-link">Change details</span>
68 <span class="invisible-link">Link to branch</span>74 (http://launchpad.dev/fooix/+edit)
69 Set the branch for this series75 >>> print_involvement_portlet(owner_browser)
70 (http://launchpad.dev/fooix/trunk/+linkbranch)76 Configure support tracker
77 http://launchpad.dev/fooix/+configure-answers
78 Configure bug tracker
79 http://launchpad.dev/fooix/+configure-bugtracker
80 Configure translations
81 http://launchpad.dev/fooix/+configure-translations
82 Configure project branch
83 http://launchpad.dev/fooix/trunk/+setbranch
7184
72The owner can specify the development focus branch from the overview page.85The owner can specify the development focus branch from the overview page.
7386
74 >>> owner_browser.getLink(url='+linkbranch').click()87 >>> owner_browser.getLink(url='+setbranch').click()
75 >>> owner_browser.getControl('Branch').value = '~eric/fooix/trunk'88 >>> owner_browser.getControl(name='field.branch_location').value = (
89 ... '~eric/fooix/trunk')
76 >>> owner_browser.getControl('Update').click()90 >>> owner_browser.getControl('Update').click()
77 >>> print_feedback_messages(owner_browser.contents)91 >>> print_feedback_messages(owner_browser.contents)
78 Series code location updated.92 Series code location updated.
7993
80The owner is taken back to the trunk series page.94The owner is taken back to the project page.
8195
82 >>> print_tag_with_id(owner_browser.contents, 'branch-details')96 >>> print_tag_with_id(owner_browser.contents, 'dev-focus')
83 lp://dev/fooix - Eric Change branch97 Development focus:
98 trunk series Change details
99 lp://dev/fooix Change branch
100 View the branch content
84101
85102
86Projects with development focus branches103Projects with development focus branches
@@ -137,7 +154,6 @@
137 >>> print_development_focus(anon_browser)154 >>> print_development_focus(anon_browser)
138 Development focus:155 Development focus:
139 trunk series156 trunk series
140 Development focus branch has not been specified
141 Links:157 Links:
142 trunk series (/fooix/trunk)158 trunk series (/fooix/trunk)
143159
144160
=== modified file 'lib/lp/registry/stories/product/xx-product-edit.txt'
--- lib/lp/registry/stories/product/xx-product-edit.txt 2009-12-24 01:41:54 +0000
+++ lib/lp/registry/stories/product/xx-product-edit.txt 2010-04-09 18:48:33 +0000
@@ -387,10 +387,12 @@
387The remote_product field - which stores a Product's ID on the remote bug387The remote_product field - which stores a Product's ID on the remote bug
388tracker - can be set from the +edit page, too.388tracker - can be set from the +edit page, too.
389389
390 >>> user_browser.open('http://launchpad.dev/thunderbird/+edit')390 >>> user_browser.open(
391 ... 'http://launchpad.dev/thunderbird/+configure-bugtracker')
391 >>> user_browser.getControl('Remote project').value = 'Thunderbird'392 >>> user_browser.getControl('Remote project').value = 'Thunderbird'
392 >>> user_browser.getControl('Change').click()393 >>> user_browser.getControl('Change').click()
393394
394 >>> user_browser.open('http://launchpad.dev/thunderbird/+edit')395 >>> user_browser.open(
396 ... 'http://launchpad.dev/thunderbird/+configure-bugtracker')
395 >>> print user_browser.getControl('Remote project').value397 >>> print user_browser.getControl('Remote project').value
396 Thunderbird398 Thunderbird
397399
=== modified file 'lib/lp/registry/stories/product/xx-product-launchpad-usage.txt'
--- lib/lp/registry/stories/product/xx-product-launchpad-usage.txt 2010-01-20 23:10:13 +0000
+++ lib/lp/registry/stories/product/xx-product-launchpad-usage.txt 2010-04-09 18:48:33 +0000
@@ -28,20 +28,14 @@
28 >>> registrant_browser = setupBrowser(28 >>> registrant_browser = setupBrowser(
29 ... auth='Basic test@canonical.com:test')29 ... auth='Basic test@canonical.com:test')
30 >>> registrant_browser.open('http://launchpad.dev/firefox')30 >>> registrant_browser.open('http://launchpad.dev/firefox')
31 >>> registrant_browser.getLink('Change details').click()31 >>> registrant_browser.getLink('Configure bug tracker').click()
32 >>> registrant_browser.url32 >>> registrant_browser.url
33 'http://launchpad.dev/firefox/+edit'33 'http://launchpad.dev/firefox/+configure-bugtracker'
3434
35Firefox is currently marked as using Bugs. Let's specify that it35Firefox is currently marked as using Bugs. Let's specify that it
36doesn't use any bug tracker at all.36doesn't use any bug tracker at all.
3737
38 >>> registrant_browser.getControl(38 >>> registrant_browser.getControl(
39 ... 'Translations for this project are done in Launchpad').selected
40 False
41 >>> registrant_browser.getControl(
42 ... 'People can ask questions in Launchpad Answers').selected
43 True
44 >>> registrant_browser.getControl(
45 ... 'In Launchpad').selected39 ... 'In Launchpad').selected
46 True40 True
47 >>> registrant_browser.getControl(41 >>> registrant_browser.getControl(
@@ -49,12 +43,39 @@
49 ... 'become inactive').selected43 ... 'become inactive').selected
50 False44 False
51 >>> registrant_browser.getControl('Somewhere else').selected = True45 >>> registrant_browser.getControl('Somewhere else').selected = True
46 >>> registrant_browser.getControl('Change').click()
5247
53We'll also set it as officially using codehosting.48We'll also set it as officially using codehosting.
5449
55 >>> registrant_browser.getControl(50 >>> registrant_browser.getLink('Configure project branch').click()
56 ... 'Code for this project is published in Bazaar branches on'51 >>> registrant_browser.getControl(name='field.branch_location').value = (
57 ... ' Launchpad').selected = True52 ... '~name12/firefox/main')
53 >>> registrant_browser.getControl('Update').click()
54
55Translations can be enabled.
56
57 >>> registrant_browser.open('http://launchpad.dev/firefox')
58 >>> registrant_browser.getLink('Configure translations').click()
59 >>> registrant_browser.url
60 'http://launchpad.dev/firefox/+configure-translations'
61 >>> control = registrant_browser.getControl(
62 ... 'Translations for this project are done in Launchpad')
63 >>> control.selected
64 False
65 >>> control.selected = True
66 >>> registrant_browser.getControl('Change').click()
67
68Answers can be disabled.
69
70 >>> registrant_browser.open('http://launchpad.dev/firefox')
71 >>> registrant_browser.getLink('Configure support tracker').click()
72 >>> registrant_browser.url
73 'http://launchpad.dev/firefox/+configure-answers'
74 >>> control = registrant_browser.getControl(
75 ... 'People can ask questions in Launchpad Answers')
76 >>> control.selected
77 True
78 >>> control.selected = False
58 >>> registrant_browser.getControl('Change').click()79 >>> registrant_browser.getControl('Change').click()
5980
60On the product page, we can see that the product doesn't use any bug81On the product page, we can see that the product doesn't use any bug
@@ -62,7 +83,7 @@
6283
63 >>> uses = find_tag_by_id(registrant_browser.contents, id='uses')84 >>> uses = find_tag_by_id(registrant_browser.contents, id='uses')
64 >>> print extract_text(uses)85 >>> print extract_text(uses)
65 Uses Launchpad for: Answers and Branches.86 Uses Launchpad for: Branches and Translations.
6687
6788
68Tracking bugs by email89Tracking bugs by email
@@ -71,7 +92,8 @@
71Instead if using a web-based bug tracker, projects can specify an92Instead if using a web-based bug tracker, projects can specify an
72email address where bug reports should be sent.93email address where bug reports should be sent.
7394
74 >>> registrant_browser.open('http://launchpad.dev/firefox/+edit')95 >>> registrant_browser.open(
96 ... 'http://launchpad.dev/firefox/+configure-bugtracker')
75 >>> registrant_browser.getControl(97 >>> registrant_browser.getControl(
76 ... 'By emailing an upstream bug contact').selected = True98 ... 'By emailing an upstream bug contact').selected = True
77 >>> registrant_browser.getControl(99 >>> registrant_browser.getControl(
@@ -90,14 +112,15 @@
90112
91An error message is shown if the email address is not filled in.113An error message is shown if the email address is not filled in.
92114
93 >>> registrant_browser.open('http://launchpad.dev/firefox/+edit')115 >>> registrant_browser.open(
116 ... 'http://launchpad.dev/firefox/+configure-bugtracker')
94 >>> registrant_browser.getControl(117 >>> registrant_browser.getControl(
95 ... 'By emailing an upstream bug contact').selected = True118 ... 'By emailing an upstream bug contact').selected = True
96 >>> registrant_browser.getControl(119 >>> registrant_browser.getControl(
97 ... name='field.bugtracker.upstream_email_address').value = ''120 ... name='field.bugtracker.upstream_email_address').value = ''
98 >>> registrant_browser.getControl('Change').click()121 >>> registrant_browser.getControl('Change').click()
99 >>> registrant_browser.url122 >>> registrant_browser.url
100 'http://launchpad.dev/firefox/+edit'123 'http://launchpad.dev/firefox/+configure-bugtracker'
101 >>> for message in find_tags_by_class(124 >>> for message in find_tags_by_class(
102 ... registrant_browser.contents, 'message'):125 ... registrant_browser.contents, 'message'):
103 ... print extract_text(message)126 ... print extract_text(message)
@@ -124,7 +147,7 @@
124 >>> registrant_browser.title147 >>> registrant_browser.title
125 'Jokosher Audio Editor in Launchpad'148 'Jokosher Audio Editor in Launchpad'
126149
127 >>> registrant_browser.getLink('Change details').click()150 >>> registrant_browser.getLink('Configure bug tracker').click()
128 >>> registrant_browser.getControl('In Launchpad').selected151 >>> registrant_browser.getControl('In Launchpad').selected
129 True152 True
130153
@@ -145,7 +168,7 @@
145Reviewing the edit page again, Dafydd, can see that bug expiration was168Reviewing the edit page again, Dafydd, can see that bug expiration was
146also disabled by the switch from Launchpad Bugs.169also disabled by the switch from Launchpad Bugs.
147170
148 >>> registrant_browser.getLink('Change details').click()171 >>> registrant_browser.getLink('Configure bug tracker').click()
149 >>> registrant_browser.getControl('In Launchpad').selected172 >>> registrant_browser.getControl('In Launchpad').selected
150 False173 False
151174
152175
=== modified file 'lib/lp/registry/templates/pillar-involvement-portlet.pt'
--- lib/lp/registry/templates/pillar-involvement-portlet.pt 2009-08-15 05:35:13 +0000
+++ lib/lp/registry/templates/pillar-involvement-portlet.pt 2010-04-09 18:48:33 +0000
@@ -1,13 +1,40 @@
1<div1<div
2 xmlns:tal="http://xml.zope.org/namespaces/tal"2 xmlns:tal="http://xml.zope.org/namespaces/tal"
3 xmlns:i18n="http://xml.zope.org/namespaces/i18n"3 xmlns:i18n="http://xml.zope.org/namespaces/i18n"
4 id="involvement" class="portlet involvement"4 id="involvement" class="portlet"
5 tal:condition="view/has_involvement">5 tal:condition="view/has_involvement"
6 >
6 <h2>Get Involved</h2>7 <h2>Get Involved</h2>
78
8 <ul>9 <ul class="involvement">
9 <li tal:repeat="link view/enabled_links">10 <li tal:repeat="link view/enabled_links">
10 <a tal:replace="structure link/fmt:link" />11 <a tal:replace="structure link/fmt:link" />
11 </li>12 </li>
13
14 <tal:disabled repeat="link view/visible_disabled_links">
15 <li tal:condition="not: link/enabled"
16 tal:attributes="title string:Launchpad needs to know where the user can ${link/text/lower}"
17 class="disabled">
18 <div style="padding: 0.3em 0 0.3em 0.3em">
19 <div style="display: inline-block"
20 class="sprite icon-only warning-icon"></div>
21
22 <div style="height: 1.2em; float: right">
23 <img src="/@@/gray-arrow-right.png"
24 style="top: 50%; bottom: 50%; margin-top: -5px;
25 position: relative;
26 height: 9px; width: 14px; padding: 0"/>
27 </div>
28
29 <span tal:content="link/text"/>
30 </div>
31 </li>
32 </tal:disabled>
33 </ul>
34
35 <ul tal:condition="view/configuration_links" style="padding-top: 1em">
36 <li tal:repeat="link view/configuration_links">
37 <a tal:replace="structure link/fmt:link" />
38 </li>
12 </ul>39 </ul>
13</div>40</div>
1441
=== modified file 'lib/lp/registry/templates/product-index.pt'
--- lib/lp/registry/templates/product-index.pt 2009-11-18 04:51:08 +0000
+++ lib/lp/registry/templates/product-index.pt 2010-04-09 18:48:33 +0000
@@ -116,10 +116,6 @@
116 <br/>116 <br/>
117 <a tal:replace="structure trunk/menu:context/source/fmt:link"/>117 <a tal:replace="structure trunk/menu:context/source/fmt:link"/>
118 </p>118 </p>
119 <p tal:condition="not: trunk_visible">
120 Development focus branch has not been specified
121 <a tal:replace="structure dev_focus/menu:overview/link_branch/fmt:icon" />
122 </p>
123 </dd>119 </dd>
124 </dl>120 </dl>
125121
126122
=== modified file 'lib/lp/translations/stories/productseries/xx-productseries-translations.txt'
--- lib/lp/translations/stories/productseries/xx-productseries-translations.txt 2010-01-29 16:16:19 +0000
+++ lib/lp/translations/stories/productseries/xx-productseries-translations.txt 2010-04-09 18:48:33 +0000
@@ -159,14 +159,14 @@
159 ... find_tag_by_id(159 ... find_tag_by_id(
160 ... owner_browser.contents, 'not-translated-in-launchpad'))160 ... owner_browser.contents, 'not-translated-in-launchpad'))
161 This project is not using Launchpad for translations.161 This project is not using Launchpad for translations.
162 You can change this in the project settings. (Getting162 Configure translations
163 started with translating your project in Launchpad)163 Getting started with translating your project in Launchpad
164164
165The notice links to the project settings where the option can be set.165The notice links to the page for configuring translations on the project.
166166
167 >>> owner_browser.getLink('project settings').click()167 >>> owner_browser.getLink('Configure translations').click()
168 >>> print owner_browser.url168 >>> print owner_browser.url
169 http://.../bazaar/+edit169 http://.../bazaar/+configure-translations
170170
171An administrator also sees the notice.171An administrator also sees the notice.
172172
@@ -177,8 +177,8 @@
177 ... find_tag_by_id(177 ... find_tag_by_id(
178 ... admin_browser.contents, 'not-translated-in-launchpad'))178 ... admin_browser.contents, 'not-translated-in-launchpad'))
179 This project is not using Launchpad for translations.179 This project is not using Launchpad for translations.
180 You can change this in the project settings. (Getting180 Configure translations
181 started with translating your project in Launchpad)181 Getting started with translating your project in Launchpad
182182
183A Translations admin who is neither a Launchpad admin nor the project183A Translations admin who is neither a Launchpad admin nor the project
184owner (and so won't be able to change the project's settings) sees the184owner (and so won't be able to change the project's settings) sees the
@@ -213,7 +213,7 @@
213 ... find_tag_by_id(213 ... find_tag_by_id(
214 ... jtv_browser.contents, 'not-translated-in-launchpad'))214 ... jtv_browser.contents, 'not-translated-in-launchpad'))
215 This project is not using Launchpad for translations.215 This project is not using Launchpad for translations.
216 (Getting started with translating your project in Launchpad)216 Getting started with translating your project in Launchpad
217217
218218
219Branch synchronization options219Branch synchronization options
220220
=== modified file 'lib/lp/translations/stories/standalone/xx-product-translations.txt'
--- lib/lp/translations/stories/standalone/xx-product-translations.txt 2010-01-15 14:00:30 +0000
+++ lib/lp/translations/stories/standalone/xx-product-translations.txt 2010-04-09 18:48:33 +0000
@@ -49,20 +49,21 @@
49 ... find_tag_by_id(49 ... find_tag_by_id(
50 ... registrant.contents, 'not-translated-in-launchpad'))50 ... registrant.contents, 'not-translated-in-launchpad'))
51 This project is not using Launchpad for translations.51 This project is not using Launchpad for translations.
52 You can change this in the project settings. (Getting52 Configure translations
53 started with translating your project in Launchpad)53 Getting started with translating your project in Launchpad
5454
55 >>> registrant.getLink(55 >>> registrant.getLink(
56 ... url=('/gnomebaker/trunk/'56 ... url=('/gnomebaker/trunk/'
57 ... '+translations-upload')) is not None57 ... '+translations-upload')) is not None
58 True58 True
5959
60The instructions for the registrant link to the settings page, where they can60The instructions for the registrant link to the translations
61configure the project to use Launchpad for translations if desired.61configuration page, where they can configure the project to use
62Launchpad for translations if desired.
6263
63 >>> registrant.getLink('project settings').click()64 >>> registrant.getLink('Configure translations').click()
64 >>> print registrant.url65 >>> print registrant.url
65 http://.../gnomebaker/+edit66 http://.../gnomebaker/+configure-translations
6667
67(The template upload process is tested in xx-translation-import-queue.txt.)68(The template upload process is tested in xx-translation-import-queue.txt.)
6869
@@ -140,7 +141,7 @@
140 >>> admin_browser.getLink('Overview').click()141 >>> admin_browser.getLink('Overview').click()
141 >>> print admin_browser.title142 >>> print admin_browser.title
142 Network Applet in Launchpad143 Network Applet in Launchpad
143 >>> admin_browser.getLink('Change details').click()144 >>> admin_browser.getLink('Configure translations').click()
144 >>> admin_browser.getControl(145 >>> admin_browser.getControl(
145 ... 'Translations for this project are done in Launchpad').selected146 ... 'Translations for this project are done in Launchpad').selected
146 False147 False
147148
=== modified file 'lib/lp/translations/stories/translationgroups/15-product-translation-group.txt'
--- lib/lp/translations/stories/translationgroups/15-product-translation-group.txt 2009-09-18 15:42:19 +0000
+++ lib/lp/translations/stories/translationgroups/15-product-translation-group.txt 2010-04-09 18:48:33 +0000
@@ -10,9 +10,10 @@
10 ... find_tag_by_id(netapplet_owner_browser.contents, 'uses'))10 ... find_tag_by_id(netapplet_owner_browser.contents, 'uses'))
11 Does not use Launchpad for development.11 Does not use Launchpad for development.
1212
13 >>> netapplet_owner_browser.getLink('Change details').click()13 >>> netapplet_owner_browser.getLink(
14 ... 'Configure translations').click()
14 >>> print netapplet_owner_browser.title15 >>> print netapplet_owner_browser.title
15 Change Network Applet's details...16 Configure Translations : NetApplet
1617
17 >>> netapplet_owner_browser.getControl(18 >>> netapplet_owner_browser.getControl(
18 ... 'Translations for this project are done in Launchpad'19 ... 'Translations for this project are done in Launchpad'
1920
=== modified file 'lib/lp/translations/stories/translationgroups/46-test-distro-structured-permissions.txt'
--- lib/lp/translations/stories/translationgroups/46-test-distro-structured-permissions.txt 2010-02-16 21:21:14 +0000
+++ lib/lp/translations/stories/translationgroups/46-test-distro-structured-permissions.txt 2010-04-09 18:48:33 +0000
@@ -1,7 +1,7 @@
1First, we state that netapplet is using Launchpad Translations.1First, we state that netapplet is using Launchpad Translations.
22
3 >>> admin_browser.open('http://launchpad.dev/netapplet')3 >>> admin_browser.open('http://launchpad.dev/netapplet')
4 >>> admin_browser.getLink('Change details').click()4 >>> admin_browser.getLink('Configure translations').click()
5 >>> admin_browser.getControl(5 >>> admin_browser.getControl(
6 ... 'Translations for this project are done in Launchpad'6 ... 'Translations for this project are done in Launchpad'
7 ... ).selected = True7 ... ).selected = True
88
=== modified file 'lib/lp/translations/stories/translations/55-rosetta-potemplates.txt'
--- lib/lp/translations/stories/translations/55-rosetta-potemplates.txt 2009-12-21 17:27:17 +0000
+++ lib/lp/translations/stories/translations/55-rosetta-potemplates.txt 2010-04-09 18:48:33 +0000
@@ -47,7 +47,8 @@
4747
48 # To check this, we need to state that this project uses Launchpad for48 # To check this, we need to state that this project uses Launchpad for
49 # translations.49 # translations.
50 >>> admin_browser.open('http://launchpad.dev/netapplet/+edit')50 >>> admin_browser.open(
51 ... 'http://launchpad.dev/netapplet/+configure-translations')
51 >>> admin_browser.getControl(52 >>> admin_browser.getControl(
52 ... 'Translations for this project are done in Launchpad'53 ... 'Translations for this project are done in Launchpad'
53 ... ).selected = True54 ... ).selected = True
5455
=== modified file 'lib/lp/translations/templates/product-portlet-not-using-launchpad.pt'
--- lib/lp/translations/templates/product-portlet-not-using-launchpad.pt 2009-11-01 20:18:32 +0000
+++ lib/lp/translations/templates/product-portlet-not-using-launchpad.pt 2010-04-09 18:48:33 +0000
@@ -4,17 +4,20 @@
4 xmlns:i18n="http://xml.zope.org/namespaces/i18n"4 xmlns:i18n="http://xml.zope.org/namespaces/i18n"
5 omit-tag="">5 omit-tag="">
66
7 <p id="not-translated-in-launchpad"7 <div id="not-translated-in-launchpad"
8 tal:condition="not: context/official_rosetta">8 tal:condition="not: context/official_rosetta">
9 <strong>9 <strong>
10 This project is not using Launchpad for translations.10 This project is not using Launchpad for translations.
11 </strong>11 </strong>
12 <tal:admin_or_owner condition="context/required:launchpad.Edit">12 <ul>
13 You can change this in the13 <li>
14 <a tal:attributes="href context/fmt:url/+edit">14 <a tal:replace="structure context/menu:overview/configure_translations/fmt:link"/>
15 project settings</a>.15 </li>
16 </tal:admin_or_owner>16 <li>
17 (<a href="/+help/getting-started-for-your-project.html" target="help">Getting started with translating your project in Launchpad</a>)17 <a href="/+help/getting-started-for-your-project.html" target="help"
18 </p>18 >Getting started with translating your project in Launchpad</a>
19 </li>
20 </ul>
21 </div>
1922
20</tal:root>23</tal:root>