Merge lp:~bac/launchpad/clarity into lp:launchpad

Proposed by Brad Crittenden
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: no longer in the source branch.
Merged at revision: 11025
Proposed branch: lp:~bac/launchpad/clarity
Merge into: lp:launchpad
Diff against target: 785 lines (+249/-111)
26 files modified
lib/canonical/launchpad/interfaces/launchpad.py (+1/-1)
lib/canonical/launchpad/webapp/menu.py (+0/-1)
lib/lp/bugs/browser/bugrole.py (+0/-13)
lib/lp/bugs/browser/tests/test_bugsupervisor.py (+1/-10)
lib/lp/bugs/browser/tests/test_configure_bugtracker_links.py (+105/-0)
lib/lp/bugs/interfaces/bugsupervisor.py (+8/-1)
lib/lp/bugs/interfaces/bugtarget.py (+4/-3)
lib/lp/bugs/interfaces/securitycontact.py (+4/-1)
lib/lp/bugs/stories/bug-also-affects/xx-upstream-bugtracker-links.txt (+3/-2)
lib/lp/bugs/stories/bug-release-management/50-defer-distribution-bug.txt (+4/-1)
lib/lp/bugs/stories/bug-release-management/60-defer-product-bug.txt (+4/-1)
lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.txt (+3/-4)
lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt (+9/-9)
lib/lp/bugs/templates/bugtarget-bugs.pt (+12/-2)
lib/lp/bugs/templates/bugtarget-macros-filebug.pt (+1/-1)
lib/lp/registry/browser/distribution.py (+2/-20)
lib/lp/registry/browser/distributionsourcepackage.py (+2/-5)
lib/lp/registry/browser/pillar.py (+31/-2)
lib/lp/registry/browser/product.py (+5/-18)
lib/lp/registry/help/driver.html (+26/-0)
lib/lp/registry/interfaces/product.py (+5/-4)
lib/lp/registry/stories/person/xx-person-home.txt (+4/-3)
lib/lp/registry/stories/product/xx-product-launchpad-usage.txt (+3/-3)
lib/lp/registry/templates/person-portlet-contact-details.pt (+2/-2)
lib/lp/registry/templates/pillar-involvement-portlet.pt (+0/-1)
lib/lp/registry/templates/product-index.pt (+10/-3)
To merge this branch: bzr merge lp:~bac/launchpad/clarity
Reviewer Review Type Date Requested Status
Jelmer Vernooij (community) code Approve
Matthew Revell (community) text Approve
Review via email: mp+27747@code.launchpad.net

Description of the change

= Summary =

This branch fixes a slew of bugs related to better wording for various
concepts and other small improvements. The bugs are:

* Bug #91905: Better text for: Product>Bugs>Change Bug Contact
* Bug #91911: Better text for: Product>Bugs>Change Security Contact

 - Simply change the wording in the interface.

* Bug #305482: <project/project-group/distro>/+edit page shows
  misleading instructions for bug reporting guidelines

 - Reword the instructions for entering bug reporting guidelines. Also
change the display to say "Ubuntu bug reporting guidelines" rather than
the older, terse "Ubuntu guidelines".

* Bug #419020: there's no help on the meaning of 'driver' or 'bug
  supervisor'

 - Add a pop-up help page with the definition of driver. Fix the
description of bug supervisor.

* Bug #240369: Editing bug-reporting guidelines should start from Bugs

 - Add a link on the bugs page in the involvement portlet for setting
the bug tracker. Required some refactoring of the bugs menus and the
introduction of a PillarBugsMenu superclass.

Before and after screenshot can be found at:
http://people.canonical.com/~bac/claritynow/

== Proposed fix ==

As above.

== Pre-implementation notes ==

Calls with Curtis.

== Implementation details ==

As above.

== Tests ==

So many tests are affected it is best just to run all registry and bugs
tests:

bin/test -vvm lp.registry
bin/test -vvm lp.bugs

== Demo and Q/A ==

Visit the following URLs and examine the new text:

https://launchpad.dev/applets/+configure-bugtracker
https://launchpad.dev/applets/+securitycontact
https://launchpad.dev/applets/+bugsupervisor
https://launchpad.dev/applets and click on the driver (?) link

= Launchpad lint =

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/lp/bugs/browser/tests/test_configure_bugtracker_links.py
  lib/lp/bugs/browser/bugrole.py
  lib/lp/registry/templates/product-index.pt
  lib/canonical/launchpad/interfaces/launchpad.py
  lib/lp/bugs/templates/bugtarget-macros-filebug.pt
  lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt
  lib/lp/registry/browser/product.py
  lib/lp/registry/stories/person/xx-person-home.txt
  lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.txt
  lib/lp/registry/browser/distributionsourcepackage.py
  lib/lp/registry/interfaces/product.py
  lib/lp/registry/templates/person-portlet-contact-details.pt
  lib/lp/bugs/stories/bug-release-management/50-defer-distribution-bug.txt
  lib/lp/registry/browser/pillar.py
  lib/lp/bugs/interfaces/securitycontact.py
  lib/lp/bugs/browser/tests/test_bugsupervisor.py
  lib/lp/bugs/stories/bug-release-management/60-defer-product-bug.txt
  lib/lp/registry/templates/pillar-involvement-portlet.pt
  lib/lp/registry/stories/product/xx-product-launchpad-usage.txt
  lib/lp/bugs/interfaces/bugtarget.py
  lib/lp/bugs/templates/bugtarget-bugs.pt
  lib/canonical/launchpad/webapp/menu.py
  lib/lp/bugs/interfaces/bugsupervisor.py
  lib/lp/registry/help/driver.html
  lib/lp/registry/browser/distribution.py
  lib/lp/bugs/stories/bug-also-affects/xx-upstream-bugtracker-links.txt

== Pyflakes notices ==

lib/lp/registry/browser/distribution.py
    9: undefined name 'DistributionLanguagePackAdminView' in __all__
    538: local variable 'more_than_five' is assigned to but never used

== Pylint notices ==

lib/lp/registry/interfaces/product.py
    796: [C0322, IProductSet.createProduct] Operator not preceded by a space
    freshmeatproject='freshmeat_project', wikiurl='wiki_url',
    ^
    downloadurl='download_url',
    sourceforgeproject='sourceforge_project',
    programminglang='programming_lang')
    @export_factory_operation(
    IProduct, ['name', 'displayname', 'title', 'summary', 'description',
    'project', 'homepageurl', 'screenshotsurl',
    'downloadurl', 'freshmeatproject', 'wikiurl',
    'sourceforgeproject', 'programminglang',
    'license_reviewed', 'licenses', 'license_info',
    'registrant'])
    @export_operation_as('new_project')
    def createProduct(owner, name, displayname, title, summary,
    description=None, project=None, homepageurl=None,
    screenshotsurl=None, wikiurl=None,
    downloadurl=None, freshmeatproject=None,
    sourceforgeproject=None, programminglang=None,
    license_reviewed=False, mugshot=None, logo=None,
    icon=None, licenses=None, license_info=None,
    registrant=None):

lib/lp/bugs/interfaces/bugtarget.py
    69: [C0322, IHasBugs.searchTasks] Operator not preceded by a space
    value_type=Text(),
    ^
    required=False),
    search_text=copy_field(IBugTaskSearch['searchtext']),
    status=copy_field(IBugTaskSearch['status']),
    importance=copy_field(IBugTaskSearch['importance']),
    assignee=Reference(schema=Interface),
    bug_reporter=Reference(schema=Interface),
    bug_supervisor=Reference(schema=Interface),
    bug_commenter=Reference(schema=Interface),
    bug_subscriber=Reference(schema=Interface),
    structural_subscriber=Reference(schema=Interface),
    owner=Reference(schema=Interface),
    affected_user=Reference(schema=Interface),
    has_patch=copy_field(IBugTaskSearch['has_patch']),
    has_cve=copy_field(IBugTaskSearch['has_cve']),
    tags=copy_field(IBugTaskSearch['tag']),
    tags_combinator=copy_field(IBugTaskSearch['tags_combinator']),
    omit_duplicates=copy_field(IBugTaskSearch['omit_dupes']),
    omit_targeted=copy_field(IBugTaskSearch['omit_targeted']),
    status_upstream=copy_field(IBugTaskSearch['status_upstream']),
    milestone_assignment=copy_field(
    IBugTaskSearch['milestone_assignment']),
    milestone=copy_field(IBugTaskSearch['milestone']),
    component=copy_field(IBugTaskSearch['component']),
    nominated_for=Reference(schema=Interface),
    has_no_package=copy_field(IBugTaskSearch['has_no_package']),
    hardware_bus=Choice(
    title=u'The bus of a hardware device related to a bug',

    vocabulary=DBEnumeratedType, required=False),
    hardware_vendor_id=TextLine(
    title=(
    u"The vendor ID of a hardware device related to a bug."),
    description=(
    u"Allowed values of the vendor ID depend on the bus of the "
    "device.nn"
    "Vendor IDs of PCI, PCCard and USB devices are hexadecimal "
    "string representations of 16 bit integers in the format "
    "'0x01ab': The prefix '0x', followed by exactly 4 digits; "
    "where a digit is one of the characters 0..9, a..f. The "
    "characters A..F are not allowed.nn"
    "SCSI vendor IDs are strings with exactly 8 characters. "
    "Shorter names are right-padded with space (0x20) characters."
    "nn"
    "IDs for other buses may be arbitrary strings."),
    required=False),
    hardware_product_id=TextLine(
    title=(
    u"The product ID of a hardware device related to a bug."),
    description=(
    u"Allowed values of the product ID depend on the bus of the "
    "device.nn"
    "Product IDs of PCI, PCCard and USB devices are hexadecimal "
    "string representations of 16 bit integers in the format "
    "'0x01ab': The prefix '0x', followed by exactly 4 digits; "
    "where a digit is one of the characters 0..9, a..f. The "
    "characters A..F are not allowed.nn"
    "SCSI product IDs are strings with exactly 16 characters. "
    "Shorter names are right-padded with space (0x20) characters."
    "nn"
    "IDs for other buses may be arbitrary strings."),
    required=False),
    hardware_driver_name=TextLine(
    title=(
    u"The driver controlling a hardware device related to a "
    "bug."),
    required=False),
    hardware_driver_package_name=TextLine(
    title=(
    u"The package of the driver which controls a hardware "
    "device related to a bug."),
    required=False),
    hardware_owner_is_bug_reporter=Bool(
    title=(
    u"Search for bugs reported by people who own the given "
    "device or who use the given hardware driver."),
    required=False),
    hardware_owner_is_affected_by_bug=Bool(
    title=(
    u"Search for bugs where people affected by a bug own the "
    "given device or use the given hardware driver."),
    required=False),
    hardware_owner_is_subscribed_to_bug=Bool(
    title=(
    u"Search for bugs where a bug subscriber owns the "
    "given device or uses the given hardware driver."),
    required=False),
    hardware_is_linked_to_bug=Bool(
    title=(
    u"Search for bugs which are linked to hardware reports "
    "which contain the given device or whcih contain a device"
    "controlled by the given driver."),
    required=False),
    linked_branches=Choice(
    title=(
    u"Search for bugs that are linked to branches or for bugs "
    "that are not linked to branches."),
    vocabulary=BugBranchSearch, required=False))
    @operation_returns_collection_of(IBugTask)
    @export_read_operation()
    def searchTasks(search_params, user=None,
    order_by=None, search_text=None,
    status=None, importance=None,
    assignee=None, bug_reporter=None, bug_supervisor=None,
    bug_commenter=None, bug_subscriber=None, owner=None,
    affected_user=None, has_patch=None, has_cve=None,
    distribution=None, tags=None,
    tags_combinator=BugTagsSearchCombinator.ALL,
    omit_duplicates=True, omit_targeted=None,
    status_upstream=None, milestone_assignment=None,
    milestone=None, component=None, nominated_for=None,
    sourcepackagename=None, has_no_package=None,
    hardware_bus=None, hardware_vendor_id=None,
    hardware_product_id=None, hardware_driver_name=None,
    hardware_driver_package_name=None,
    hardware_owner_is_bug_reporter=None,
    hardware_owner_is_affected_by_bug=False,
    hardware_owner_is_subscribed_to_bug=False,
    hardware_is_linked_to_bug=False, linked_branches=None,
    structural_subscriber=None):

lib/lp/bugs/interfaces/bugsupervisor.py
    31: [C0301] Line too long (79/78)

I'll take care of this last lint issue.

To post a comment you must log in.
Revision history for this message
Matthew Revell (matthew.revell) wrote :

Thank you for doing this work, Brad. This will greatly help.

I have one small suggestion and it is not a show-stopper: I wonder if "Incomplete" in lib/canonical/launchpad/interfaces/launchpad.py should link to https://help.launchpad.net/Bugs/Statuses ... I'm not certain it should, I'm just offering it for your consideration.

review: Approve (text)
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

Nice work, another step towards a less overwhelming project page for new users.

I don't see any issues, though I noticed two small formatting glitches:

There doesn't appear to be a (trivial) docstring in lib/lp/bugs/browser/tests/test_configure_bugtracker_links.py

There appears to be a missing whileline above the definition of PillarBugsMenu in lib/lp/registry/browser/pillar.py.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/canonical/launchpad/interfaces/launchpad.py'
--- lib/canonical/launchpad/interfaces/launchpad.py 2010-05-18 23:19:36 +0000
+++ lib/canonical/launchpad/interfaces/launchpad.py 2010-06-17 15:28:31 +0000
@@ -636,5 +636,5 @@
636 official_anything = Bool (636 official_anything = Bool (
637 title=_('Uses Launchpad for something'),)637 title=_('Uses Launchpad for something'),)
638 enable_bug_expiration = Bool(638 enable_bug_expiration = Bool(
639 title=_('Expire Incomplete bug reports when they become inactive'),639 title=_('Expire "Incomplete" bug reports when they become inactive'),
640 required=True)640 required=True)
641641
=== modified file 'lib/canonical/launchpad/webapp/menu.py'
--- lib/canonical/launchpad/webapp/menu.py 2010-01-21 23:50:03 +0000
+++ lib/canonical/launchpad/webapp/menu.py 2010-06-17 15:28:31 +0000
@@ -10,7 +10,6 @@
10 'get_current_view',10 'get_current_view',
11 'get_facet',11 'get_facet',
12 'structured',12 'structured',
13 'translate_if_msgid',
14 'FacetMenu',13 'FacetMenu',
15 'ApplicationMenu',14 'ApplicationMenu',
16 'ContextMenu',15 'ContextMenu',
1716
=== modified file 'lib/lp/bugs/browser/bugrole.py'
--- lib/lp/bugs/browser/bugrole.py 2010-05-25 20:36:49 +0000
+++ lib/lp/bugs/browser/bugrole.py 2010-06-17 15:28:31 +0000
@@ -79,19 +79,6 @@
7979
80 def changeBugSupervisor(self, bug_supervisor):80 def changeBugSupervisor(self, bug_supervisor):
81 self.context.setBugSupervisor(bug_supervisor, self.user)81 self.context.setBugSupervisor(bug_supervisor, self.user)
82 if bug_supervisor is not None:
83 self.request.response.addNotification(structured(
84 'Successfully changed the bug supervisor to '
85 '<a href="%(supervisor_url)s">%(displayname)s</a>.'
86 '<br /><a href="%(supervisor_url)s">%(displayname)s</a> '
87 'has also been subscribed to bug notifications for '
88 '%(targetname)s.<br />You can '
89 '<a href="%(targeturl)s/+subscribe">change the '
90 'subscriptions</a> for %(targetname)s at any time.',
91 supervisor_url=canonical_url(bug_supervisor),
92 displayname=bug_supervisor.displayname,
93 targetname=self.context.displayname,
94 targeturl=canonical_url(self.context)))
9582
96 def validateSecurityContact(self, data):83 def validateSecurityContact(self, data):
97 """Validates the new security contact.84 """Validates the new security contact.
9885
=== modified file 'lib/lp/bugs/browser/tests/test_bugsupervisor.py'
--- lib/lp/bugs/browser/tests/test_bugsupervisor.py 2010-06-08 20:42:35 +0000
+++ lib/lp/bugs/browser/tests/test_bugsupervisor.py 2010-06-17 15:28:31 +0000
@@ -65,16 +65,7 @@
65 self.assertEqual([], view.errors)65 self.assertEqual([], view.errors)
66 self.assertEqual(self.product.bug_supervisor, self.owner)66 self.assertEqual(self.product.bug_supervisor, self.owner)
67 notifications = view.request.response.notifications67 notifications = view.request.response.notifications
68 self.assertEqual(1, len(notifications))68 self.assertEqual(0, len(notifications))
69 expected = (
70 'Successfully changed the bug supervisor to '
71 '<a href="http://launchpad.dev/~splat">&lt;splat /&gt;</a>.'
72 '<br /><a href="http://launchpad.dev/~splat">&lt;splat /&gt;</a> '
73 'has also been subscribed to bug notifications for '
74 '&lt;boing /&gt;.<br />You can '
75 '<a href="http://launchpad.dev/boing/+subscribe">change '
76 'the subscriptions</a> for &lt;boing /&gt; at any time.')
77 self.assertEqual(expected, notifications.pop().message)
7869
79 def test_owner_appoint_self_from_another(self):70 def test_owner_appoint_self_from_another(self):
80 self.product.setBugSupervisor(self.team, self.owner)71 self.product.setBugSupervisor(self.team, self.owner)
8172
=== added file 'lib/lp/bugs/browser/tests/test_configure_bugtracker_links.py'
--- lib/lp/bugs/browser/tests/test_configure_bugtracker_links.py 1970-01-01 00:00:00 +0000
+++ lib/lp/bugs/browser/tests/test_configure_bugtracker_links.py 2010-06-17 15:28:31 +0000
@@ -0,0 +1,105 @@
1# Copyright 2010 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""Unit tests for bug tracker configuration link visibility."""
5
6__metaclass__ = type
7
8import unittest
9
10from canonical.launchpad.ftests import ANONYMOUS, login
11from canonical.launchpad.layers import BugsLayer
12from canonical.testing import LaunchpadFunctionalLayer
13
14from lp.testing import login_person, TestCaseWithFactory
15from lp.testing.views import create_initialized_view
16
17from lp.registry.browser.product import ProductBugsMenu
18from lp.registry.browser.distribution import DistributionBugsMenu
19from lp.registry.browser.distributionsourcepackage import (
20 DistributionSourcePackageBugsMenu)
21
22
23class TestConfigureBugTrackerBase(TestCaseWithFactory):
24
25 layer = LaunchpadFunctionalLayer
26
27 def setUp(self):
28 super(TestConfigureBugTrackerBase, self).setUp()
29 login('test@canonical.com')
30 self.target = self.makeTarget()
31 self.menu = self.getMenu()
32 self.view = create_initialized_view(self.target, name="+index",
33 layer=BugsLayer)
34
35 def makeTarget(self):
36 raise NotImplementedError
37
38 def getOwner(self):
39 return self.target.owner
40
41
42class TestConfigureBugTrackerProduct(TestConfigureBugTrackerBase):
43
44 def makeTarget(self):
45 return self.factory.makeProduct(name="vuvuzela")
46
47 def getMenu(self):
48 return ProductBugsMenu(self.target)
49
50 def test_link_visible_to_owner(self):
51 login_person(self.getOwner())
52 link = self.menu.configure_bugtracker()
53 self.assertTrue(link.enabled, "Link not enabled")
54
55 def test_link_visible_to_admin(self):
56 login('foo.bar@canonical.com')
57 link = self.menu.configure_bugtracker()
58 self.assertTrue(link.enabled, "Link not enabled")
59
60 def test_not_visible_to_regular_user(self):
61 login('no-priv@canonical.com')
62 link = self.menu.configure_bugtracker()
63 self.assertFalse(link.enabled, "Link enabled")
64
65 def test_not_visible_to_anon(self):
66 login(ANONYMOUS)
67 link = self.menu.configure_bugtracker()
68 self.assertFalse(link.enabled, "Link enabled")
69
70
71class TestConfigureBugTrackerDistro(TestConfigureBugTrackerBase):
72
73 def makeTarget(self):
74 return self.factory.makeDistribution()
75
76 def getMenu(self):
77 return DistributionBugsMenu(self.target)
78
79 def test_link_not_present(self):
80 login_person(self.getOwner())
81 self.assertFalse(hasattr(self.menu, 'configure_bugtracker'))
82
83
84class TestConfigureBugTrackerDSP(TestConfigureBugTrackerDistro):
85
86 def makeTarget(self):
87 return self.factory.makeDistributionSourcePackage()
88
89 def getMenu(self):
90 return DistributionSourcePackageBugsMenu(self.target)
91
92 def getOwner(self):
93 return self.target.distribution.owner
94
95
96def test_suite():
97 suite = unittest.TestSuite()
98 suite.addTest(unittest.makeSuite(TestConfigureBugTrackerProduct))
99 suite.addTest(unittest.makeSuite(TestConfigureBugTrackerDistro))
100 suite.addTest(unittest.makeSuite(TestConfigureBugTrackerDSP))
101 return suite
102
103
104if __name__ == '__main__':
105 unittest.TextTestRunner().run(test_suite())
0106
=== modified file 'lib/lp/bugs/interfaces/bugsupervisor.py'
--- lib/lp/bugs/interfaces/bugsupervisor.py 2010-06-08 20:42:35 +0000
+++ lib/lp/bugs/interfaces/bugsupervisor.py 2010-06-17 15:28:31 +0000
@@ -27,7 +27,14 @@
27 bug_supervisor = exported(ParticipatingPersonChoice(27 bug_supervisor = exported(ParticipatingPersonChoice(
28 title=_("Bug Supervisor"),28 title=_("Bug Supervisor"),
29 description=_(29 description=_(
30 "The person or team responsible for bug management."),30 "The Launchpad id of the person or team (preferred) responsible "
31 "for bug management. The bug supervisor will be subscribed to "
32 "all bugs and will receive email about all activity on all bugs "
33 "for this project, so that should be a factor in your decision. "
34 "The bug supervisor will also have access to all private bugs."),
35
36
37
31 required=False, vocabulary='ValidPersonOrTeam', readonly=True))38 required=False, vocabulary='ValidPersonOrTeam', readonly=True))
3239
33 @mutator_for(bug_supervisor)40 @mutator_for(bug_supervisor)
3441
=== modified file 'lib/lp/bugs/interfaces/bugtarget.py'
--- lib/lp/bugs/interfaces/bugtarget.py 2010-06-09 08:26:26 +0000
+++ lib/lp/bugs/interfaces/bugtarget.py 2010-06-17 15:28:31 +0000
@@ -231,11 +231,12 @@
231 bug_reporting_guidelines = exported(231 bug_reporting_guidelines = exported(
232 Text(232 Text(
233 title=(233 title=(
234 u"If I\N{right single quotation mark}m reporting a bug, "234 u"Helpful guidelines for reporting a bug"),
235 u"I should include, if possible"),
236 description=(235 description=(
237 u"These guidelines will be shown to "236 u"These guidelines will be shown to "
238 "anyone reporting a bug."),237 "everyone reporting a bug and should be "
238 "text or a bulleted list with your particular "
239 "requirements, if any."),
239 required=False,240 required=False,
240 max_length=50000))241 max_length=50000))
241242
242243
=== modified file 'lib/lp/bugs/interfaces/securitycontact.py'
--- lib/lp/bugs/interfaces/securitycontact.py 2010-05-18 21:24:27 +0000
+++ lib/lp/bugs/interfaces/securitycontact.py 2010-06-17 15:28:31 +0000
@@ -25,5 +25,8 @@
25 security_contact = exported(PublicPersonChoice(25 security_contact = exported(PublicPersonChoice(
26 title=_("Security Contact"),26 title=_("Security Contact"),
27 description=_(27 description=_(
28 "The person or team who handles security-related bug reports"),28 "The Launchpad id of the person or team (preferred) who handles "
29 "security-related bug reports. The security contact will be "
30 "subscribed to all bugs marked as a security vulnerability and "
31 "will receive email about all activity on all security bugs."),
29 required=False, vocabulary='ValidPersonOrTeam'))32 required=False, vocabulary='ValidPersonOrTeam'))
3033
=== 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 2010-05-19 21:22:00 +0000
+++ lib/lp/bugs/stories/bug-also-affects/xx-upstream-bugtracker-links.txt 2010-06-17 15:28:31 +0000
@@ -122,10 +122,11 @@
122122
123 >>> admin_browser.open(123 >>> admin_browser.open(
124 ... 'http://launchpad.dev/thunderbird/+configure-bugtracker')124 ... 'http://launchpad.dev/thunderbird/+configure-bugtracker')
125 >>> admin_browser.getControl('Remote project').value = 'Thunderbird'125 >>> admin_browser.getControl('Remote bug tracker project id').value = (
126 ... 'Thunderbird')
126 >>> admin_browser.getControl('Change').click()127 >>> admin_browser.getControl('Change').click()
127128
128 >>> admin_browser.open(129 >>> admin_browser.open(
129 ... 'http://launchpad.dev/thunderbird/+configure-bugtracker')130 ... 'http://launchpad.dev/thunderbird/+configure-bugtracker')
130 >>> print admin_browser.getControl('Remote project').value131 >>> print admin_browser.getControl('Remote bug tracker project id').value
131 Thunderbird132 Thunderbird
132133
=== modified file 'lib/lp/bugs/stories/bug-release-management/50-defer-distribution-bug.txt'
--- lib/lp/bugs/stories/bug-release-management/50-defer-distribution-bug.txt 2009-06-12 16:36:02 +0000
+++ lib/lp/bugs/stories/bug-release-management/50-defer-distribution-bug.txt 2010-06-17 15:28:31 +0000
@@ -25,7 +25,10 @@
2525
26 >>> for tag in find_tags_by_class(admin_browser.contents, 'message'):26 >>> for tag in find_tags_by_class(admin_browser.contents, 'message'):
27 ... print tag.renderContents()27 ... print tag.renderContents()
28 Successfully changed the bug supervisor to...No Privileges Person...28
29 >>> print extract_text(find_tag_by_id(admin_browser.contents, 'bug-supervisor'))
30 Bug supervisor:
31 No Privileges Person
2932
30 >>> user_browser.reload()33 >>> user_browser.reload()
3134
3235
=== modified file 'lib/lp/bugs/stories/bug-release-management/60-defer-product-bug.txt'
--- lib/lp/bugs/stories/bug-release-management/60-defer-product-bug.txt 2009-06-12 16:36:02 +0000
+++ lib/lp/bugs/stories/bug-release-management/60-defer-product-bug.txt 2010-06-17 15:28:31 +0000
@@ -25,7 +25,10 @@
2525
26 >>> for tag in find_tags_by_class(admin_browser.contents, 'message'):26 >>> for tag in find_tags_by_class(admin_browser.contents, 'message'):
27 ... print tag.renderContents()27 ... print tag.renderContents()
28 Successfully changed the bug supervisor to...No Privileges Person...28
29 >>> print extract_text(find_tag_by_id(admin_browser.contents, 'bug-supervisor'))
30 Bug supervisor:
31 No Privileges Person
2932
30 >>> user_browser.reload()33 >>> user_browser.reload()
3134
3235
=== modified file 'lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.txt'
--- lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.txt 2009-09-02 22:13:06 +0000
+++ lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.txt 2010-06-17 15:28:31 +0000
@@ -57,9 +57,9 @@
57 ... 'test@canonical.com')57 ... 'test@canonical.com')
58 >>> admin_browser.getControl('Change').click()58 >>> admin_browser.getControl('Change').click()
5959
60 >>> for tag in find_tags_by_class(admin_browser.contents, 'message'):60 >>> print extract_text(find_tag_by_id(admin_browser.contents, 'bug-supervisor'))
61 ... print tag.renderContents()61 Bug supervisor:
62 Successfully changed the bug supervisor to...Sample Person...62 Sample Person
6363
64The new Bug Supervisor for Ubuntu can change the status to Won't Fix:64The new Bug Supervisor for Ubuntu can change the status to Won't Fix:
6565
@@ -124,4 +124,3 @@
124 http://bugs.launchpad.dev/ubuntu/+source/iceweasel/+bug/1124 http://bugs.launchpad.dev/ubuntu/+source/iceweasel/+bug/1
125 >>> print_highlighted_bugtask(bug_supervisor_browser)125 >>> print_highlighted_bugtask(bug_supervisor_browser)
126 iceweasel (Ubuntu) ... Triaged Medium Unassigned ...126 iceweasel (Ubuntu) ... Triaged Medium Unassigned ...
127
128127
=== modified file 'lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt'
--- lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt 2010-06-14 15:52:41 +0000
+++ lib/lp/bugs/stories/guided-filebug/xx-bug-reporting-guidelines.txt 2010-06-17 15:28:31 +0000
@@ -65,32 +65,32 @@
65 *65 *
66 Ubuntu66 Ubuntu
67 <http://launchpad.dev/ubuntu/+filebug>67 <http://launchpad.dev/ubuntu/+filebug>
68 Ubuntu guidelines:68 Ubuntu bug reporting guidelines:
69 The version of Ubuntu you're using.69 The version of Ubuntu you're using.
70 Thank you for filing a bug for Ubuntu70 Thank you for filing a bug for Ubuntu
71 *71 *
72 Mozilla72 Mozilla
73 <http://launchpad.dev/mozilla/+filebug>73 <http://launchpad.dev/mozilla/+filebug>
74 The Mozilla Project guidelines:74 The Mozilla Project bug reporting guidelines:
75 The version of Mozilla you're using.75 The version of Mozilla you're using.
76 Thank you for filing a bug for Mozilla76 Thank you for filing a bug for Mozilla
77 *77 *
78 Firefox78 Firefox
79 <http://launchpad.dev/firefox/+filebug>79 <http://launchpad.dev/firefox/+filebug>
80 Mozilla Firefox guidelines:80 Mozilla Firefox bug reporting guidelines:
81 The version of Firefox you're using.81 The version of Firefox you're using.
82 Thank you for filing a bug for Firefox82 Thank you for filing a bug for Firefox
83 *83 *
84 alsa-utils in Ubuntu84 alsa-utils in Ubuntu
85 <http://launchpad.dev/ubuntu/+source/alsa-utils/+filebug>85 <http://launchpad.dev/ubuntu/+source/alsa-utils/+filebug>
86 alsa-utils (Ubuntu) guidelines:86 alsa-utils (Ubuntu) bug reporting guidelines:
87 The version of alsa-utils in Ubuntu you're using.87 The version of alsa-utils in Ubuntu you're using.
88 Ubuntu guidelines:88 Ubuntu bug reporting guidelines:
89 The version of Ubuntu you're using.89 The version of Ubuntu you're using.
90 Thank you for filing a bug for alsa-utils in Ubuntu90 Thank you for filing a bug for alsa-utils in Ubuntu
9191
92Note how the alsa-utils in Ubuntu specific guidelines were displayed92Note how the alsa-utils in Ubuntu specific guidelines were displayed
93followed by the general Ubuntu guidelines.93followed by the general Ubuntu bug reporting guidelines.
9494
95Bugs can also be reported directly against a distribution series, for95Bugs can also be reported directly against a distribution series, for
96which the guidelines are taken from the respective distribution.96which the guidelines are taken from the respective distribution.
@@ -101,7 +101,7 @@
101 >>> user_browser.getControl('Continue').click()101 >>> user_browser.getControl('Continue').click()
102 >>> print extract_text(find_tag_by_id(102 >>> print extract_text(find_tag_by_id(
103 ... user_browser.contents, 'bug-reporting-guidelines'))103 ... user_browser.contents, 'bug-reporting-guidelines'))
104 Ubuntu guidelines:104 Ubuntu bug reporting guidelines:
105 The version of Ubuntu you're using.105 The version of Ubuntu you're using.
106106
107107
@@ -127,7 +127,7 @@
127 >>> user_browser.getControl('Continue').click()127 >>> user_browser.getControl('Continue').click()
128 >>> print extract_text(find_tag_by_id(128 >>> print extract_text(find_tag_by_id(
129 ... user_browser.contents, 'bug-reporting-guidelines'))129 ... user_browser.contents, 'bug-reporting-guidelines'))
130 Ubuntu guidelines:130 Ubuntu bug reporting guidelines:
131 The version of Ubuntu you're using.131 The version of Ubuntu you're using.
132132
133Changing the package to alsa-utils does not make the alsa-utils133Changing the package to alsa-utils does not make the alsa-utils
@@ -139,7 +139,7 @@
139 ... name='field.packagename').value = "alsa-utils"139 ... name='field.packagename').value = "alsa-utils"
140 >>> print extract_text(find_tag_by_id(140 >>> print extract_text(find_tag_by_id(
141 ... user_browser.contents, 'bug-reporting-guidelines'))141 ... user_browser.contents, 'bug-reporting-guidelines'))
142 Ubuntu guidelines:142 Ubuntu bug reporting guidelines:
143 The version of Ubuntu you're using.143 The version of Ubuntu you're using.
144144
145XXX: allenap 2008-11-14 bug=297743: These limitations have been filed145XXX: allenap 2008-11-14 bug=297743: These limitations have been filed
146146
=== modified file 'lib/lp/bugs/templates/bugtarget-bugs.pt'
--- lib/lp/bugs/templates/bugtarget-bugs.pt 2010-06-09 13:58:08 +0000
+++ lib/lp/bugs/templates/bugtarget-bugs.pt 2010-06-17 15:28:31 +0000
@@ -16,8 +16,8 @@
16 </metal:block>16 </metal:block>
17 <body>17 <body>
18 <tal:side metal:fill-slot="side" condition="view/uses_launchpad_bugtracker">18 <tal:side metal:fill-slot="side" condition="view/uses_launchpad_bugtracker">
19 <div id="involvement" class="portlet involvement">19 <div id="involvement" class="portlet">
20 <ul>20 <ul class="involvement">
21 <li style="border: none">21 <li style="border: none">
22 <a href="+filebug" class="menu-link-filebug sprite bugs">22 <a href="+filebug" class="menu-link-filebug sprite bugs">
23 Report a bug23 Report a bug
@@ -32,6 +32,16 @@
32 </a>32 </a>
33 </li>33 </li>
34 </ul>34 </ul>
35 <tal:bugtracker
36 define="link context/menu:bugs/configure_bugtracker|nothing"
37 condition="link">
38 <ul tal:condition="link/enabled"
39 style="padding-top: 1em">
40 <li>
41 <a tal:replace="structure link/fmt:link" />
42 </li>
43 </ul>
44 </tal:bugtracker>
35 </div>45 </div>
36 <div class="portlet">46 <div class="portlet">
37 <dl tal:define="bug_supervisor context/bug_supervisor"47 <dl tal:define="bug_supervisor context/bug_supervisor"
3848
=== modified file 'lib/lp/bugs/templates/bugtarget-macros-filebug.pt'
--- lib/lp/bugs/templates/bugtarget-macros-filebug.pt 2010-06-14 13:54:39 +0000
+++ lib/lp/bugs/templates/bugtarget-macros-filebug.pt 2010-06-17 15:28:31 +0000
@@ -353,7 +353,7 @@
353 tal:condition="guidelines">353 tal:condition="guidelines">
354 <td colspan="2" id="bug-reporting-guidelines">354 <td colspan="2" id="bug-reporting-guidelines">
355 <tal:guidelines repeat="guideline guidelines">355 <tal:guidelines repeat="guideline guidelines">
356 <h3><span tal:replace="guideline/source" /> guidelines:</h3>356 <h3><span tal:replace="guideline/source" /> bug reporting guidelines:</h3>
357 <div tal:content="structure guideline/content/fmt:text-to-html" />357 <div tal:content="structure guideline/content/fmt:text-to-html" />
358 </tal:guidelines>358 </tal:guidelines>
359 </td>359 </td>
360360
=== modified file 'lib/lp/registry/browser/distribution.py'
--- lib/lp/registry/browser/distribution.py 2010-06-14 15:52:41 +0000
+++ lib/lp/registry/browser/distribution.py 2010-06-17 15:28:31 +0000
@@ -51,6 +51,7 @@
51from lp.registry.browser.announcement import HasAnnouncementsView51from lp.registry.browser.announcement import HasAnnouncementsView
52from lp.registry.browser.menu import (52from lp.registry.browser.menu import (
53 IRegistryCollectionNavigationMenu, RegistryCollectionActionMenuBase)53 IRegistryCollectionNavigationMenu, RegistryCollectionActionMenuBase)
54from lp.registry.browser.pillar import PillarBugsMenu
54from lp.bugs.browser.bugtask import BugTargetTraversalMixin55from lp.bugs.browser.bugtask import BugTargetTraversalMixin
55from lp.answers.browser.faqtarget import FAQTargetNavigationMixin56from lp.answers.browser.faqtarget import FAQTargetNavigationMixin
56from canonical.launchpad.browser.feeds import FeedsMixin57from canonical.launchpad.browser.feeds import FeedsMixin
@@ -73,7 +74,6 @@
73from lp.soyuz.interfaces.publishedpackage import (74from lp.soyuz.interfaces.publishedpackage import (
74 IPublishedPackageSet)75 IPublishedPackageSet)
75from lp.registry.browser.structuralsubscription import (76from lp.registry.browser.structuralsubscription import (
76 StructuralSubscriptionMenuMixin,
77 StructuralSubscriptionTargetTraversalMixin)77 StructuralSubscriptionTargetTraversalMixin)
78from canonical.launchpad.webapp import (78from canonical.launchpad.webapp import (
79 action, ApplicationMenu, canonical_url, ContextMenu, custom_widget,79 action, ApplicationMenu, canonical_url, ContextMenu, custom_widget,
@@ -415,7 +415,7 @@
415 return Link('+addseries', text, icon='add')415 return Link('+addseries', text, icon='add')
416416
417417
418class DistributionBugsMenu(ApplicationMenu, StructuralSubscriptionMenuMixin):418class DistributionBugsMenu(PillarBugsMenu):
419419
420 usedfor = IDistribution420 usedfor = IDistribution
421 facet = 'bugs'421 facet = 'bugs'
@@ -427,24 +427,6 @@
427 'subscribe',427 'subscribe',
428 )428 )
429429
430 def cve(self):
431 text = 'CVE reports'
432 return Link('+cve', text, icon='cve')
433
434 @enabled_with_permission('launchpad.Edit')
435 def bugsupervisor(self):
436 text = 'Change bug supervisor'
437 return Link('+bugsupervisor', text, icon='edit')
438
439 @enabled_with_permission('launchpad.Edit')
440 def securitycontact(self):
441 text = 'Change security contact'
442 return Link('+securitycontact', text, icon='edit')
443
444 def filebug(self):
445 text = 'Report a bug'
446 return Link('+filebug', text, icon='bug')
447
448430
449class DistributionSpecificationsMenu(NavigationMenu,431class DistributionSpecificationsMenu(NavigationMenu,
450 HasSpecificationsMenuMixin):432 HasSpecificationsMenuMixin):
451433
=== modified file 'lib/lp/registry/browser/distributionsourcepackage.py'
--- lib/lp/registry/browser/distributionsourcepackage.py 2010-06-14 15:52:41 +0000
+++ lib/lp/registry/browser/distributionsourcepackage.py 2010-06-17 15:28:31 +0000
@@ -41,6 +41,7 @@
41 QuestionTargetFacetMixin, QuestionTargetTraversalMixin)41 QuestionTargetFacetMixin, QuestionTargetTraversalMixin)
42from lp.answers.interfaces.questionenums import QuestionStatus42from lp.answers.interfaces.questionenums import QuestionStatus
43from lp.bugs.browser.bugtask import BugTargetTraversalMixin43from lp.bugs.browser.bugtask import BugTargetTraversalMixin
44from lp.registry.browser.pillar import PillarBugsMenu
44from lp.soyuz.browser.sourcepackagerelease import (45from lp.soyuz.browser.sourcepackagerelease import (
45 extract_bug_numbers, extract_email_addresses, linkify_changelog)46 extract_bug_numbers, extract_email_addresses, linkify_changelog)
46from lp.soyuz.interfaces.archive import IArchiveSet47from lp.soyuz.interfaces.archive import IArchiveSet
@@ -107,16 +108,12 @@
107108
108109
109class DistributionSourcePackageBugsMenu(110class DistributionSourcePackageBugsMenu(
110 DistributionSourcePackageOverviewMenu):111 PillarBugsMenu, DistributionSourcePackageLinksMixin):
111112
112 usedfor = IDistributionSourcePackage113 usedfor = IDistributionSourcePackage
113 facet = 'bugs'114 facet = 'bugs'
114 links = ['filebug', 'subscribe']115 links = ['filebug', 'subscribe']
115116
116 def filebug(self):
117 text = 'Report a bug'
118 return Link('+filebug', text, icon='bug')
119
120117
121class DistributionSourcePackageNavigation(Navigation,118class DistributionSourcePackageNavigation(Navigation,
122 BugTargetTraversalMixin, HasCustomLanguageCodesTraversalMixin,119 BugTargetTraversalMixin, HasCustomLanguageCodesTraversalMixin,
123120
=== modified file 'lib/lp/registry/browser/pillar.py'
--- lib/lp/registry/browser/pillar.py 2010-05-03 18:28:16 +0000
+++ lib/lp/registry/browser/pillar.py 2010-06-17 15:28:31 +0000
@@ -1,4 +1,4 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the1# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Common views for objects that implement `IPillar`."""4"""Common views for objects that implement `IPillar`."""
@@ -8,6 +8,7 @@
8__all__ = [8__all__ = [
9 'InvolvedMenu',9 'InvolvedMenu',
10 'PillarView',10 'PillarView',
11 'PillarBugsMenu',
11 ]12 ]
1213
1314
@@ -16,10 +17,13 @@
16from zope.interface import implements, Interface17from zope.interface import implements, Interface
1718
18from canonical.cachedproperty import cachedproperty19from canonical.cachedproperty import cachedproperty
19from canonical.launchpad.webapp.menu import Link, NavigationMenu20from canonical.launchpad.webapp.menu import (
21 ApplicationMenu, enabled_with_permission, Link, NavigationMenu)
20from canonical.launchpad.webapp.publisher import LaunchpadView, nearest22from canonical.launchpad.webapp.publisher import LaunchpadView, nearest
21from canonical.launchpad.webapp.tales import MenuAPI23from canonical.launchpad.webapp.tales import MenuAPI
2224
25from lp.registry.browser.structuralsubscription import (
26 StructuralSubscriptionMenuMixin)
23from lp.registry.interfaces.distroseries import IDistroSeries27from lp.registry.interfaces.distroseries import IDistroSeries
24from lp.registry.interfaces.distributionsourcepackage import (28from lp.registry.interfaces.distributionsourcepackage import (
25 IDistributionSourcePackage)29 IDistributionSourcePackage)
@@ -149,3 +153,28 @@
149 return sorted([153 return sorted([
150 link for link in important_links if not link.enabled],154 link for link in important_links if not link.enabled],
151 key=attrgetter('sort_key'))155 key=attrgetter('sort_key'))
156
157
158class PillarBugsMenu(ApplicationMenu, StructuralSubscriptionMenuMixin):
159 """Base class for pillar bugs menus."""
160
161 facet = 'bugs'
162 configurable_bugtracker = False
163
164 @enabled_with_permission('launchpad.Edit')
165 def bugsupervisor(self):
166 text = 'Change bug supervisor'
167 return Link('+bugsupervisor', text, icon='edit')
168
169 def cve(self):
170 text = 'CVE reports'
171 return Link('+cve', text, icon='cve')
172
173 def filebug(self):
174 text = 'Report a bug'
175 return Link('+filebug', text, icon='bug')
176
177 @enabled_with_permission('launchpad.Edit')
178 def securitycontact(self):
179 text = 'Change security contact'
180 return Link('+securitycontact', text, icon='edit')
152181
=== modified file 'lib/lp/registry/browser/product.py'
--- lib/lp/registry/browser/product.py 2010-06-11 04:02:27 +0000
+++ lib/lp/registry/browser/product.py 2010-06-17 15:28:31 +0000
@@ -95,6 +95,7 @@
95from lp.registry.browser.distribution import UsesLaunchpadMixin95from lp.registry.browser.distribution import UsesLaunchpadMixin
96from lp.registry.browser.menu import (96from lp.registry.browser.menu import (
97 IRegistryCollectionNavigationMenu, RegistryCollectionActionMenuBase)97 IRegistryCollectionNavigationMenu, RegistryCollectionActionMenuBase)
98from lp.registry.browser.pillar import PillarBugsMenu
98from lp.answers.browser.faqtarget import FAQTargetNavigationMixin99from lp.answers.browser.faqtarget import FAQTargetNavigationMixin
99from canonical.launchpad.browser.feeds import FeedsMixin100from canonical.launchpad.browser.feeds import FeedsMixin
100from lp.registry.browser.pillar import PillarView101from lp.registry.browser.pillar import PillarView
@@ -555,7 +556,8 @@
555 return Link('+addbranch', text, summary, icon='add')556 return Link('+addbranch', text, summary, icon='add')
556557
557558
558class ProductBugsMenu(ApplicationMenu, StructuralSubscriptionMenuMixin):559class ProductBugsMenu(PillarBugsMenu,
560 ProductEditLinksMixin):
559561
560 usedfor = IProduct562 usedfor = IProduct
561 facet = 'bugs'563 facet = 'bugs'
@@ -565,24 +567,9 @@
565 'securitycontact',567 'securitycontact',
566 'cve',568 'cve',
567 'subscribe',569 'subscribe',
570 'configure_bugtracker',
568 )571 )
569572 configurable_bugtracker = True
570 def filebug(self):
571 text = 'Report a bug'
572 return Link('+filebug', text, icon='bug')
573
574 def cve(self):
575 return Link('+cve', 'CVE reports', icon='cve')
576
577 @enabled_with_permission('launchpad.Edit')
578 def bugsupervisor(self):
579 text = 'Change bug supervisor'
580 return Link('+bugsupervisor', text, icon='edit')
581
582 @enabled_with_permission('launchpad.Edit')
583 def securitycontact(self):
584 text = 'Change security contact'
585 return Link('+securitycontact', text, icon='edit')
586573
587574
588class ProductSpecificationsMenu(NavigationMenu, ProductEditLinksMixin,575class ProductSpecificationsMenu(NavigationMenu, ProductEditLinksMixin,
589576
=== added file 'lib/lp/registry/help/driver.html'
--- lib/lp/registry/help/driver.html 1970-01-01 00:00:00 +0000
+++ lib/lp/registry/help/driver.html 2010-06-17 15:28:31 +0000
@@ -0,0 +1,26 @@
1<html>
2 <head>
3 <title>What is a project driver?</title>
4 <link rel="stylesheet" type="text/css"
5 href="/+icing/yui/cssreset/reset.css" />
6 <link rel="stylesheet" type="text/css"
7 href="/+icing/yui/cssfonts/fonts.css" />
8 <link rel="stylesheet" type="text/css"
9 href="/+icing/yui/cssbase/base.css" />
10 </head>
11 <body>
12 <h1>What is a project driver?</h1>
13
14 <p>
15 The project driver is a person or team who is responsible for setting
16 the direction for the project. The driver can set goals, approve bug
17 targeting, or set backporting for <b>any</b> major series in the
18 project.
19 </p>
20 <p>
21 Alternatively, you can chose to leave the project driver unset and
22 appoint a team for each series.
23 </p>
24
25 </body>
26</html>
027
=== modified file 'lib/lp/registry/interfaces/product.py'
--- lib/lp/registry/interfaces/product.py 2010-05-24 21:39:43 +0000
+++ lib/lp/registry/interfaces/product.py 2010-06-17 15:28:31 +0000
@@ -663,9 +663,10 @@
663663
664 remote_product = exported(664 remote_product = exported(
665 TextLine(665 TextLine(
666 title=_('Remote project'), required=False,666 title=_('Remote bug tracker project id'), required=False,
667 description=_(667 description=_(
668 "The ID of this project on its remote bug tracker.")))668 "Some bug trackers host multiple projects at the same URL "
669 "and require an identifier for the specific project.")))
669670
670 def redeemSubscriptionVoucher(voucher, registrant, purchaser,671 def redeemSubscriptionVoucher(voucher, registrant, purchaser,
671 subscription_months, whiteboard=None,672 subscription_months, whiteboard=None,
@@ -731,8 +732,8 @@
731732
732733
733class IProduct(734class IProduct(
734 IHasBugSupervisor, IProductEditRestricted, 735 IHasBugSupervisor, IProductEditRestricted,
735 IProductProjectReviewRestricted, IProductDriverRestricted, 736 IProductProjectReviewRestricted, IProductDriverRestricted,
736 IProductPublic, IRootContext, IStructuralSubscriptionTarget):737 IProductPublic, IRootContext, IStructuralSubscriptionTarget):
737 """A Product.738 """A Product.
738739
739740
=== modified file 'lib/lp/registry/stories/person/xx-person-home.txt'
--- lib/lp/registry/stories/person/xx-person-home.txt 2010-03-23 21:59:13 +0000
+++ lib/lp/registry/stories/person/xx-person-home.txt 2010-06-17 15:28:31 +0000
@@ -58,11 +58,12 @@
58 >>> user_browser.open('http://launchpad.dev/~no-priv')58 >>> user_browser.open('http://launchpad.dev/~no-priv')
59 >>> print extract_text(59 >>> print extract_text(
60 ... find_tag_by_id(user_browser.contents, 'openid-info'))60 ... find_tag_by_id(user_browser.contents, 'openid-info'))
61 OpenID login: http://launchpad.dev/~no-priv ...61 OpenID login:
62 http://launchpad.dev/~no-priv
6263
63The URL is followed by a helpful link.64The URL is followed by a helpful link.
6465
65 >>> print user_browser.getLink('(What\xe2\x80\x99s\xc2\xa0this?)').url66 >>> print user_browser.getLink('openid help').url
66 http://launchpad.dev/+help/openid.html67 http://launchpad.dev/+help/openid.html
6768
68However, when the user visits someone else's page, they see no such URL.69However, when the user visits someone else's page, they see no such URL.
@@ -73,7 +74,7 @@
7374
74And there is no helpful link.75And there is no helpful link.
7576
76 >>> print user_browser.getLink(u"What&#8217;s\xa0this?").url77 >>> print user_browser.getLink('openid help').url
77 Traceback (most recent call last):78 Traceback (most recent call last):
78 ...79 ...
79 LinkNotFoundError80 LinkNotFoundError
8081
=== modified file 'lib/lp/registry/stories/product/xx-product-launchpad-usage.txt'
--- lib/lp/registry/stories/product/xx-product-launchpad-usage.txt 2010-04-09 02:25:21 +0000
+++ lib/lp/registry/stories/product/xx-product-launchpad-usage.txt 2010-06-17 15:28:31 +0000
@@ -39,7 +39,7 @@
39 ... 'In Launchpad').selected39 ... 'In Launchpad').selected
40 True40 True
41 >>> registrant_browser.getControl(41 >>> registrant_browser.getControl(
42 ... 'Expire Incomplete bug reports when they '42 ... 'Expire "Incomplete" bug reports when they '
43 ... 'become inactive').selected43 ... 'become inactive').selected
44 False44 False
45 >>> registrant_browser.getControl('Somewhere else').selected = True45 >>> registrant_browser.getControl('Somewhere else').selected = True
@@ -152,7 +152,7 @@
152 True152 True
153153
154 >>> registrant_browser.getControl(154 >>> registrant_browser.getControl(
155 ... 'Expire Incomplete bug reports when they '155 ... 'Expire "Incomplete" bug reports when they '
156 ... 'become inactive').selected156 ... 'become inactive').selected
157 True157 True
158158
@@ -173,6 +173,6 @@
173 False173 False
174174
175 >>> registrant_browser.getControl(175 >>> registrant_browser.getControl(
176 ... 'Expire Incomplete bug reports when they '176 ... 'Expire "Incomplete" bug reports when they '
177 ... 'become inactive').selected177 ... 'become inactive').selected
178 False178 False
179179
=== modified file 'lib/lp/registry/templates/person-portlet-contact-details.pt'
--- lib/lp/registry/templates/person-portlet-contact-details.pt 2010-04-19 02:45:43 +0000
+++ lib/lp/registry/templates/person-portlet-contact-details.pt 2010-06-17 15:28:31 +0000
@@ -67,8 +67,8 @@
67 <dd>67 <dd>
68 <img src="/@@/private" alt="" />68 <img src="/@@/private" alt="" />
69 <tal:openid-login content="view/openid_identity_url" />69 <tal:openid-login content="view/openid_identity_url" />
70 <a target="help" href="/+help/openid.html"70 <a target="help" href="/+help/openid.html" class="icon">
71 >(What&rsquo;s&nbsp;this?)</a>71 <img src="/@@/maybe" alt="openid help" /></a>
72 </dd>72 </dd>
73 </dl>73 </dl>
7474
7575
=== modified file 'lib/lp/registry/templates/pillar-involvement-portlet.pt'
--- lib/lp/registry/templates/pillar-involvement-portlet.pt 2010-03-19 16:06:30 +0000
+++ lib/lp/registry/templates/pillar-involvement-portlet.pt 2010-06-17 15:28:31 +0000
@@ -10,7 +10,6 @@
10 <li tal:repeat="link view/enabled_links">10 <li tal:repeat="link view/enabled_links">
11 <a tal:replace="structure link/fmt:link" />11 <a tal:replace="structure link/fmt:link" />
12 </li>12 </li>
13
14 <tal:disabled repeat="link view/visible_disabled_links">13 <tal:disabled repeat="link view/visible_disabled_links">
15 <li tal:condition="not: link/enabled"14 <li tal:condition="not: link/enabled"
16 tal:attributes="title string:Launchpad needs to know where the user can ${link/text/lower}"15 tal:attributes="title string:Launchpad needs to know where the user can ${link/text/lower}"
1716
=== modified file 'lib/lp/registry/templates/product-index.pt'
--- lib/lp/registry/templates/product-index.pt 2010-04-19 22:36:58 +0000
+++ lib/lp/registry/templates/product-index.pt 2010-06-17 15:28:31 +0000
@@ -79,13 +79,20 @@
7979
80 <dl id="driver">80 <dl id="driver">
81 <dt>Driver:</dt>81 <dt>Driver:</dt>
82 <dd tal:condition="view/effective_driver">82 <dd>
83
84 <tal:driver_set condition="view/effective_driver">
83 <a tal:replace="structure view/effective_driver/fmt:link" />85 <a tal:replace="structure view/effective_driver/fmt:link" />
84 <a tal:replace="structure overview_menu/reassign/fmt:icon" />86 <a tal:replace="structure overview_menu/reassign/fmt:icon" />
85 </dd>87 </tal:driver_set>
86 <dd tal:condition="not: view/effective_driver">88
89 <tal:driver_unset condition="not: view/effective_driver">
87 Not yet appointed.90 Not yet appointed.
88 <a tal:replace="structure overview_menu/reassign/fmt:icon" />91 <a tal:replace="structure overview_menu/reassign/fmt:icon" />
92 </tal:driver_unset>
93
94 <a target="help" href="/+help/driver.html" class="icon">
95 <img src="/@@/maybe" alt="help" /></a>
89 </dd>96 </dd>
90 </dl>97 </dl>
9198