Merge lp:~edwin-grubbs/launchpad/bug-525956-unlink-button into lp:launchpad
- bug-525956-unlink-button
- Merge into devel
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-525956-unlink-button |
Merge into: | lp:launchpad |
Diff against target: |
1398 lines (+373/-417) 26 files modified
lib/canonical/launchpad/icing/style-3-0.css.in (+1/-1) lib/canonical/launchpad/templates/launchpad-form.pt (+7/-0) lib/canonical/launchpad/webapp/launchpadform.py (+31/-3) lib/lp/registry/browser/configure.zcml (+16/-0) lib/lp/registry/browser/distributionsourcepackage.py (+1/-22) lib/lp/registry/browser/packaging.py (+0/-96) lib/lp/registry/browser/product.py (+11/-48) lib/lp/registry/browser/sourcepackage.py (+48/-15) lib/lp/registry/browser/tests/packaging-views.txt (+41/-46) lib/lp/registry/browser/tests/sourcepackage-views.txt (+52/-6) lib/lp/registry/browser/tests/test_packaging.py (+4/-2) lib/lp/registry/model/productseries.py (+4/-2) lib/lp/registry/model/sourcepackage.py (+5/-4) lib/lp/registry/stories/distroseries/xx-show-distroseries-packaging.txt (+5/-4) lib/lp/registry/stories/packaging/xx-distributionsourcepackage-packaging-concurrent-deletion.txt (+9/-14) lib/lp/registry/stories/packaging/xx-distributionsourcepackage-packaging.txt (+10/-6) lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt (+1/-3) lib/lp/registry/stories/product/xx-product-package-pages.txt (+11/-8) lib/lp/registry/stories/productseries/xx-productseries-delete.txt (+4/-2) lib/lp/registry/templates/distributionsourcepackage-index.pt (+3/-29) lib/lp/registry/templates/distroseries-packaging.pt (+2/-37) lib/lp/registry/templates/product-packages.pt (+8/-19) lib/lp/registry/templates/sourcepackage-portlet-associations.pt (+1/-47) lib/lp/registry/templates/sourcepackage-remove-packaging.pt (+34/-0) lib/lp/registry/templates/sourcepackage-upstream-connections.pt (+63/-0) lib/lp/soyuz/stories/soyuz/xx-distroseries-sources.txt (+1/-3) |
To merge this branch: | bzr merge lp:~edwin-grubbs/launchpad/bug-525956-unlink-button |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Curtis Hovey (community) | code + ui | Approve | |
Eleanor Berger (community) | code ui* | Approve | |
Review via email: mp+20334@code.launchpad.net |
Commit message
Added ability to unlink sourcepackages and project series from the sourcepackage index page.
Description of the change
Edwin Grubbs (edwin-grubbs) wrote : | # |
Eleanor Berger (intellectronica) : | # |
Curtis Hovey (sinzui) wrote : | # |
Hi Edwin.
This this was a nice feature to use on the sp page. I think we should consider using it on the dsp page: https:/
I think we should remove the edit/remove links from the +packaging listing. There is not enough information on this page to make that decision.
Edwin Grubbs (edwin-grubbs) wrote : | # |
> Hi Edwin.
>
> This this was a nice feature to use on the sp page. I think we should consider
> using it on the dsp page: https:/
> have a post back that some people have expressed concern about how easy it is
> to make a mistake. I would not say this is change we must do because the post
> back always returns the user to the dsp page--using the sp as the next_url
> would be confusing.
>
> I think we should remove the edit/remove links from the +packaging listing.
> There is not enough information on this page to make that decision.
This was supposed to be a simple change for the UI review. It has grown
quite large, so I can create a new merge proposal if you would like.
I started off trying to use +remove-packaging page for the
$distrosourcepa
was also used by $product/+packages page, so I changed that page also.
After I got the +remove-packaging page to return to the previous page, I
discovered that the edit link on the $distrosourcepa
returning you to a different page.
All these changes broke a ton of tests.
Pages to check
--------------
The edit and remove buttons for each series are hidden now.
https:/
The remove button now takes you to the $sourcepackage/
and the edit button no
https:/
The remove button now takes you to the $sourcepackage/
https:/
This page shouldn't have changed, but if you want to check that the
show_edit_buttons annotation is passed correctly, you'll need to look at it.
https:/
Implementation details
-------
Removed trailing white-space.
lib/
Added Mixin to enable forms to return to their referring page.
lib/
lib/
Use the ReturnToReferre
Hide the edit/remove buttons by default, but show them in the
annotations portlet, because its view sets
request.
sourcepackage-
it can't share the view with annotations portlet or show_edit_buttons
would always be true.
lib/
lib/
lib/
lib/
Removed PackagingDeleteView and related code.
lib/
lib/
lib/
lib/
lib/
Added error message for when a user loads this page after the
upstream link has been deleted by someone else.
lib/
Tests:
lib/
lib/lp/...
Curtis Hovey (sinzui) wrote : | # |
Hi Edwin.
in retrospect, saying no to updating the DSP page would have been better. On the other hand, I and Adi have wanted a mixin as you have created for sometime. I think the pain was worth it, though it was untimely.
I have one question from the diff. What is "irumpy hotter" in lp/registry/
Edwin Grubbs (edwin-grubbs) wrote : | # |
> I have one question from the diff. What is "irumpy hotter" in
> lp/registry/
> I am not aware of a irumpty test distroseries in the test
Doh. "irumpy" is so nonsensical and undesirable that irumpy.com is available. Fixed.
Preview Diff
1 | === modified file 'lib/canonical/launchpad/icing/style-3-0.css.in' | |||
2 | --- lib/canonical/launchpad/icing/style-3-0.css.in 2010-02-17 00:43:19 +0000 | |||
3 | +++ lib/canonical/launchpad/icing/style-3-0.css.in 2010-03-06 06:27:33 +0000 | |||
4 | @@ -814,7 +814,7 @@ | |||
5 | 814 | } | 814 | } |
6 | 815 | input[type="submit"].icon-only { | 815 | input[type="submit"].icon-only { |
7 | 816 | vertical-align: middle; | 816 | vertical-align: middle; |
9 | 817 | border: 0; | 817 | border: 0; |
10 | 818 | padding: 0; | 818 | padding: 0; |
11 | 819 | height: 16px; | 819 | height: 16px; |
12 | 820 | width: 16px; | 820 | width: 16px; |
13 | 821 | 821 | ||
14 | === modified file 'lib/canonical/launchpad/templates/launchpad-form.pt' | |||
15 | --- lib/canonical/launchpad/templates/launchpad-form.pt 2009-11-26 09:18:22 +0000 | |||
16 | +++ lib/canonical/launchpad/templates/launchpad-form.pt 2010-03-06 06:27:33 +0000 | |||
17 | @@ -16,6 +16,13 @@ | |||
18 | 16 | accept-charset="UTF-8"> | 16 | accept-charset="UTF-8"> |
19 | 17 | 17 | ||
20 | 18 | <div metal:define-macro="formbody"> | 18 | <div metal:define-macro="formbody"> |
21 | 19 | <tal:comment condition="nothing"> | ||
22 | 20 | This field is used by the ReturnToReferrerMixin. | ||
23 | 21 | </tal:comment> | ||
24 | 22 | <input type="hidden" | ||
25 | 23 | name="_return_url" | ||
26 | 24 | tal:condition="view/_return_url | nothing" | ||
27 | 25 | tal:attributes="value view/_return_url" /> | ||
28 | 19 | 26 | ||
29 | 20 | <p metal:define-slot="extra_info" tal:replace="nothing"> | 27 | <p metal:define-slot="extra_info" tal:replace="nothing"> |
30 | 21 | This is the description of the form. | 28 | This is the description of the form. |
31 | 22 | 29 | ||
32 | === modified file 'lib/canonical/launchpad/webapp/launchpadform.py' | |||
33 | --- lib/canonical/launchpad/webapp/launchpadform.py 2010-02-19 01:50:36 +0000 | |||
34 | +++ lib/canonical/launchpad/webapp/launchpadform.py 2010-03-06 06:27:33 +0000 | |||
35 | @@ -7,10 +7,11 @@ | |||
36 | 7 | __metaclass__ = type | 7 | __metaclass__ = type |
37 | 8 | 8 | ||
38 | 9 | __all__ = [ | 9 | __all__ = [ |
39 | 10 | 'LaunchpadFormView', | ||
40 | 11 | 'LaunchpadEditFormView', | ||
41 | 12 | 'action', | 10 | 'action', |
42 | 13 | 'custom_widget', | 11 | 'custom_widget', |
43 | 12 | 'LaunchpadEditFormView', | ||
44 | 13 | 'LaunchpadFormView', | ||
45 | 14 | 'ReturnToReferrerMixin', | ||
46 | 14 | 'safe_action', | 15 | 'safe_action', |
47 | 15 | ] | 16 | ] |
48 | 16 | 17 | ||
49 | @@ -32,7 +33,7 @@ | |||
50 | 32 | IMultiLineWidgetLayout, ICheckBoxWidgetLayout, | 33 | IMultiLineWidgetLayout, ICheckBoxWidgetLayout, |
51 | 33 | IAlwaysSubmittedWidget, UnsafeFormGetSubmissionError) | 34 | IAlwaysSubmittedWidget, UnsafeFormGetSubmissionError) |
52 | 34 | from canonical.launchpad.webapp.menu import escape | 35 | from canonical.launchpad.webapp.menu import escape |
54 | 35 | from canonical.launchpad.webapp.publisher import LaunchpadView | 36 | from canonical.launchpad.webapp.publisher import canonical_url, LaunchpadView |
55 | 36 | 37 | ||
56 | 37 | 38 | ||
57 | 38 | classImplements(CheckBoxWidget, ICheckBoxWidgetLayout) | 39 | classImplements(CheckBoxWidget, ICheckBoxWidgetLayout) |
58 | @@ -434,3 +435,30 @@ | |||
59 | 434 | """ | 435 | """ |
60 | 435 | action.is_safe = True | 436 | action.is_safe = True |
61 | 436 | return action | 437 | return action |
62 | 438 | |||
63 | 439 | |||
64 | 440 | class ReturnToReferrerMixin: | ||
65 | 441 | """Return to the previous page after submitting the form. | ||
66 | 442 | |||
67 | 443 | The _return_url is stored in a hidden field in the launchpad-form.pt | ||
68 | 444 | between the request to view the form and submitting the form. | ||
69 | 445 | """ | ||
70 | 446 | |||
71 | 447 | @property | ||
72 | 448 | def _return_url(self): | ||
73 | 449 | """See `LaunchpadFormView`.""" | ||
74 | 450 | # The referer header we want is only available before the view's | ||
75 | 451 | # form submits to itself. This field is a hidden input in the form. | ||
76 | 452 | referrer = self.request.form.get('_return_url') | ||
77 | 453 | if referrer is None: | ||
78 | 454 | # "referer" is misspelled in the HTTP specification. | ||
79 | 455 | referrer = self.request.getHeader('referer') | ||
80 | 456 | |||
81 | 457 | if (referrer is not None | ||
82 | 458 | and referrer.startswith(self.request.getApplicationURL())): | ||
83 | 459 | return referrer | ||
84 | 460 | else: | ||
85 | 461 | return canonical_url(self.context) | ||
86 | 462 | |||
87 | 463 | next_url = _return_url | ||
88 | 464 | cancel_url = _return_url | ||
89 | 437 | 465 | ||
90 | === modified file 'lib/lp/registry/browser/configure.zcml' | |||
91 | --- lib/lp/registry/browser/configure.zcml 2010-03-05 14:18:18 +0000 | |||
92 | +++ lib/lp/registry/browser/configure.zcml 2010-03-06 06:27:33 +0000 | |||
93 | @@ -1946,6 +1946,14 @@ | |||
94 | 1946 | facet="overview" | 1946 | facet="overview" |
95 | 1947 | class="lp.registry.browser.sourcepackage.SourcePackageAssociationPortletView" | 1947 | class="lp.registry.browser.sourcepackage.SourcePackageAssociationPortletView" |
96 | 1948 | template="../templates/sourcepackage-portlet-associations.pt"/> | 1948 | template="../templates/sourcepackage-portlet-associations.pt"/> |
97 | 1949 | |||
98 | 1950 | <browser:page | ||
99 | 1951 | for="lp.registry.interfaces.sourcepackage.ISourcePackage" | ||
100 | 1952 | permission="zope.Public" | ||
101 | 1953 | name="+upstream-connections" | ||
102 | 1954 | facet="overview" | ||
103 | 1955 | class="lp.registry.browser.sourcepackage.SourcePackageUpstreamConnectionsView" | ||
104 | 1956 | template="../templates/sourcepackage-upstream-connections.pt"/> | ||
105 | 1949 | <browser:page | 1957 | <browser:page |
106 | 1950 | for="lp.registry.interfaces.sourcepackage.ISourcePackage" | 1958 | for="lp.registry.interfaces.sourcepackage.ISourcePackage" |
107 | 1951 | permission="zope.Public" | 1959 | permission="zope.Public" |
108 | @@ -2122,6 +2130,14 @@ | |||
109 | 2122 | facet="overview" | 2130 | facet="overview" |
110 | 2123 | template="../templates/sourcepackage-edit-packaging.pt" | 2131 | template="../templates/sourcepackage-edit-packaging.pt" |
111 | 2124 | /> | 2132 | /> |
112 | 2133 | <browser:page | ||
113 | 2134 | for="lp.registry.interfaces.sourcepackage.ISourcePackage" | ||
114 | 2135 | permission="launchpad.AnyPerson" | ||
115 | 2136 | class="lp.registry.browser.sourcepackage.SourcePackageRemoveUpstreamView" | ||
116 | 2137 | name="+remove-packaging" | ||
117 | 2138 | facet="overview" | ||
118 | 2139 | template="../templates/sourcepackage-remove-packaging.pt" | ||
119 | 2140 | /> | ||
120 | 2125 | 2141 | ||
121 | 2126 | <browser:page | 2142 | <browser:page |
122 | 2127 | for="lp.registry.interfaces.structuralsubscription.IStructuralSubscriptionTarget" | 2143 | for="lp.registry.interfaces.structuralsubscription.IStructuralSubscriptionTarget" |
123 | 2128 | 2144 | ||
124 | === modified file 'lib/lp/registry/browser/distributionsourcepackage.py' | |||
125 | --- lib/lp/registry/browser/distributionsourcepackage.py 2010-01-06 12:02:38 +0000 | |||
126 | +++ lib/lp/registry/browser/distributionsourcepackage.py 2010-03-06 06:27:33 +0000 | |||
127 | @@ -49,7 +49,6 @@ | |||
128 | 49 | from lp.soyuz.interfaces.distributionsourcepackagerelease import ( | 49 | from lp.soyuz.interfaces.distributionsourcepackagerelease import ( |
129 | 50 | IDistributionSourcePackageRelease) | 50 | IDistributionSourcePackageRelease) |
130 | 51 | from lp.soyuz.interfaces.packagediff import IPackageDiffSet | 51 | from lp.soyuz.interfaces.packagediff import IPackageDiffSet |
131 | 52 | from lp.registry.browser.packaging import PackagingDeleteView | ||
132 | 53 | from lp.registry.interfaces.pocket import pocketsuffix | 52 | from lp.registry.interfaces.pocket import pocketsuffix |
133 | 54 | from lp.translations.browser.customlanguagecode import ( | 53 | from lp.translations.browser.customlanguagecode import ( |
134 | 55 | HasCustomLanguageCodesTraversalMixin) | 54 | HasCustomLanguageCodesTraversalMixin) |
135 | @@ -243,7 +242,7 @@ | |||
136 | 243 | 242 | ||
137 | 244 | 243 | ||
138 | 245 | class DistributionSourcePackageView(DistributionSourcePackageBaseView, | 244 | class DistributionSourcePackageView(DistributionSourcePackageBaseView, |
140 | 246 | PackagingDeleteView): | 245 | LaunchpadView): |
141 | 247 | """View class for DistributionSourcePackage.""" | 246 | """View class for DistributionSourcePackage.""" |
142 | 248 | implements(IDistributionSourcePackageActionMenu) | 247 | implements(IDistributionSourcePackageActionMenu) |
143 | 249 | 248 | ||
144 | @@ -257,14 +256,6 @@ | |||
145 | 257 | return canonical_url(self.context) | 256 | return canonical_url(self.context) |
146 | 258 | 257 | ||
147 | 259 | @property | 258 | @property |
148 | 260 | def all_packaging(self): | ||
149 | 261 | """See `PackagingDeleteView`.""" | ||
150 | 262 | for sourcepackage in self.context.get_distroseries_packages(): | ||
151 | 263 | packaging = sourcepackage.direct_packaging | ||
152 | 264 | if packaging is not None: | ||
153 | 265 | yield packaging | ||
154 | 266 | |||
155 | 267 | @property | ||
156 | 268 | def all_published_in_active_distroseries(self): | 259 | def all_published_in_active_distroseries(self): |
157 | 269 | """Return a list of publishings in each active distroseries. | 260 | """Return a list of publishings in each active distroseries. |
158 | 270 | 261 | ||
159 | @@ -408,16 +399,6 @@ | |||
160 | 408 | for distroseries in self.active_series: | 399 | for distroseries in self.active_series: |
161 | 409 | # The first row for each series is the "title" row. | 400 | # The first row for each series is the "title" row. |
162 | 410 | packaging = packages_by_series[distroseries].direct_packaging | 401 | packaging = packages_by_series[distroseries].direct_packaging |
163 | 411 | if packaging is None: | ||
164 | 412 | delete_packaging_form_id = None | ||
165 | 413 | hidden_packaging_field = None | ||
166 | 414 | else: | ||
167 | 415 | delete_packaging_form_id = "delete_%s_%s_%s" % ( | ||
168 | 416 | packaging.distroseries.name, | ||
169 | 417 | packaging.productseries.product.name, | ||
170 | 418 | packaging.productseries.name) | ||
171 | 419 | hidden_packaging_field = self._renderHiddenPackagingField( | ||
172 | 420 | packaging) | ||
173 | 421 | package = packages_by_series[distroseries] | 402 | package = packages_by_series[distroseries] |
174 | 422 | title_row = { | 403 | title_row = { |
175 | 423 | 'blank_row': False, | 404 | 'blank_row': False, |
176 | @@ -426,8 +407,6 @@ | |||
177 | 426 | 'distroseries': distroseries, | 407 | 'distroseries': distroseries, |
178 | 427 | 'series_package': package, | 408 | 'series_package': package, |
179 | 428 | 'packaging': packaging, | 409 | 'packaging': packaging, |
180 | 429 | 'hidden_packaging_field': hidden_packaging_field, | ||
181 | 430 | 'delete_packaging_form_id': delete_packaging_form_id, | ||
182 | 431 | } | 410 | } |
183 | 432 | rows.append(title_row) | 411 | rows.append(title_row) |
184 | 433 | 412 | ||
185 | 434 | 413 | ||
186 | === removed file 'lib/lp/registry/browser/packaging.py' | |||
187 | --- lib/lp/registry/browser/packaging.py 2010-01-21 23:46:24 +0000 | |||
188 | +++ lib/lp/registry/browser/packaging.py 1970-01-01 00:00:00 +0000 | |||
189 | @@ -1,96 +0,0 @@ | |||
190 | 1 | # Copyright 2009 Canonical Ltd. This software is licensed under the | ||
191 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | ||
192 | 3 | |||
193 | 4 | __metaclass__ = type | ||
194 | 5 | |||
195 | 6 | __all__ = [ | ||
196 | 7 | 'PackagingDeleteView', | ||
197 | 8 | ] | ||
198 | 9 | |||
199 | 10 | from zope.component import getUtility | ||
200 | 11 | from zope.formlib import form | ||
201 | 12 | from zope.schema import Choice | ||
202 | 13 | from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary | ||
203 | 14 | |||
204 | 15 | from canonical.launchpad import _ | ||
205 | 16 | from lp.registry.interfaces.packaging import IPackagingUtil | ||
206 | 17 | from canonical.launchpad.webapp.launchpadform import action, LaunchpadFormView | ||
207 | 18 | |||
208 | 19 | |||
209 | 20 | class PackagingDeleteView(LaunchpadFormView): | ||
210 | 21 | """A base view that provides packaging link deletion.""" | ||
211 | 22 | |||
212 | 23 | @property | ||
213 | 24 | def all_packaging(self): | ||
214 | 25 | """An iterator of the context's packaging links.""" | ||
215 | 26 | raise NotImplementedError | ||
216 | 27 | |||
217 | 28 | def setUpFields(self): | ||
218 | 29 | """See `LaunchpadFormView`.""" | ||
219 | 30 | # No schema is set in this form, because all fields are created with | ||
220 | 31 | # custom vocabularies. So we must not call the inherited setUpField | ||
221 | 32 | # method. | ||
222 | 33 | self.form_fields = self._createPackagingField() | ||
223 | 34 | |||
224 | 35 | @property | ||
225 | 36 | def can_delete_packaging(self): | ||
226 | 37 | """Whether the user can delete existing packaging links.""" | ||
227 | 38 | return self.user is not None | ||
228 | 39 | |||
229 | 40 | def _createPackagingField(self): | ||
230 | 41 | """Create a field to specify a Packaging association. | ||
231 | 42 | |||
232 | 43 | Create a contextual vocabulary that can specify one of the Packaging | ||
233 | 44 | associated to this DistributionSourcePackage. | ||
234 | 45 | """ | ||
235 | 46 | terms = [] | ||
236 | 47 | for packaging in self.all_packaging: | ||
237 | 48 | terms.append(SimpleTerm(packaging, packaging.id)) | ||
238 | 49 | return form.Fields( | ||
239 | 50 | Choice(__name__='packaging', vocabulary=SimpleVocabulary(terms), | ||
240 | 51 | required=True)) | ||
241 | 52 | |||
242 | 53 | def _renderHiddenPackagingField(self, packaging): | ||
243 | 54 | """Render a hidden input that fills in the packaging field.""" | ||
244 | 55 | if not self.can_delete_packaging: | ||
245 | 56 | return None | ||
246 | 57 | vocabulary = self.form_fields['packaging'].field.vocabulary | ||
247 | 58 | return '<input type="hidden" name="field.packaging" value="%s" />' % ( | ||
248 | 59 | vocabulary.getTerm(packaging).token) | ||
249 | 60 | |||
250 | 61 | def renderDeletePackagingAction(self): | ||
251 | 62 | """Render a submit input for the delete_packaging_action.""" | ||
252 | 63 | assert self.can_delete_packaging, 'User cannot delete Packaging.' | ||
253 | 64 | return ('<input type="image" value="Delete Link" ' | ||
254 | 65 | 'src="/@@/remove" title="Delete upsteam link" ' | ||
255 | 66 | 'name="%s"/>' % self.delete_packaging_action.__name__) | ||
256 | 67 | |||
257 | 68 | def handleDeletePackagingError(self, action, data, errors): | ||
258 | 69 | """Handle errors on package link deletion. | ||
259 | 70 | |||
260 | 71 | If 'packaging' is not set in the form data, we assume that means the | ||
261 | 72 | provided Packaging id was not found, which should only happen if the | ||
262 | 73 | same Packaging object was concurrently deleted. In this case, we want | ||
263 | 74 | to display a more informative error message than the default 'Invalid | ||
264 | 75 | value'. | ||
265 | 76 | """ | ||
266 | 77 | if data.get('packaging') is None: | ||
267 | 78 | self.setFieldError( | ||
268 | 79 | 'packaging', | ||
269 | 80 | _("This upstream association was deleted already.")) | ||
270 | 81 | |||
271 | 82 | @action(_("Delete Link"), name='delete_packaging', | ||
272 | 83 | failure=handleDeletePackagingError) | ||
273 | 84 | def delete_packaging_action(self, action, data): | ||
274 | 85 | """Delete a Packaging association.""" | ||
275 | 86 | packaging = data['packaging'] | ||
276 | 87 | productseries = packaging.productseries | ||
277 | 88 | distroseries = packaging.distroseries | ||
278 | 89 | getUtility(IPackagingUtil).deletePackaging( | ||
279 | 90 | productseries, packaging.sourcepackagename, distroseries) | ||
280 | 91 | self.request.response.addNotification( | ||
281 | 92 | _("Removed upstream association between ${product} " | ||
282 | 93 | "${productseries} and ${distroseries}.", mapping=dict( | ||
283 | 94 | product=productseries.product.displayname, | ||
284 | 95 | productseries=productseries.displayname, | ||
285 | 96 | distroseries=distroseries.displayname))) | ||
286 | 97 | 0 | ||
287 | === modified file 'lib/lp/registry/browser/product.py' | |||
288 | --- lib/lp/registry/browser/product.py 2010-02-16 21:21:14 +0000 | |||
289 | +++ lib/lp/registry/browser/product.py 2010-03-06 06:27:33 +0000 | |||
290 | @@ -81,7 +81,6 @@ | |||
291 | 81 | from lp.registry.browser.distribution import UsesLaunchpadMixin | 81 | from lp.registry.browser.distribution import UsesLaunchpadMixin |
292 | 82 | from lp.registry.browser.menu import ( | 82 | from lp.registry.browser.menu import ( |
293 | 83 | IRegistryCollectionNavigationMenu, RegistryCollectionActionMenuBase) | 83 | IRegistryCollectionNavigationMenu, RegistryCollectionActionMenuBase) |
294 | 84 | from lp.registry.browser.packaging import PackagingDeleteView | ||
295 | 85 | from lp.answers.browser.faqtarget import FAQTargetNavigationMixin | 84 | from lp.answers.browser.faqtarget import FAQTargetNavigationMixin |
296 | 86 | from canonical.launchpad.browser.feeds import FeedsMixin | 85 | from canonical.launchpad.browser.feeds import FeedsMixin |
297 | 87 | from lp.registry.browser.productseries import get_series_branch_error | 86 | from lp.registry.browser.productseries import get_series_branch_error |
298 | @@ -95,13 +94,15 @@ | |||
299 | 95 | StructuralSubscriptionTargetTraversalMixin) | 94 | StructuralSubscriptionTargetTraversalMixin) |
300 | 96 | from canonical.launchpad.mail import format_address, simple_sendmail | 95 | from canonical.launchpad.mail import format_address, simple_sendmail |
301 | 97 | from canonical.launchpad.webapp import ( | 96 | from canonical.launchpad.webapp import ( |
305 | 98 | ApplicationMenu, LaunchpadEditFormView, LaunchpadFormView, LaunchpadView, | 97 | ApplicationMenu, canonical_url, enabled_with_permission, LaunchpadView, |
306 | 99 | Link, Navigation, StandardLaunchpadFacets, action, canonical_url, | 98 | Link, Navigation, sorted_version_numbers, StandardLaunchpadFacets, |
304 | 100 | custom_widget, enabled_with_permission, sorted_version_numbers, | ||
307 | 101 | stepthrough, stepto, structured) | 99 | stepthrough, stepto, structured) |
308 | 102 | from canonical.launchpad.webapp.authorization import check_permission | 100 | from canonical.launchpad.webapp.authorization import check_permission |
309 | 103 | from canonical.launchpad.webapp.batching import BatchNavigator | 101 | from canonical.launchpad.webapp.batching import BatchNavigator |
310 | 104 | from canonical.launchpad.webapp.breadcrumb import Breadcrumb | 102 | from canonical.launchpad.webapp.breadcrumb import Breadcrumb |
311 | 103 | from canonical.launchpad.webapp.launchpadform import ( | ||
312 | 104 | action, custom_widget, LaunchpadEditFormView, LaunchpadFormView, | ||
313 | 105 | ReturnToReferrerMixin) | ||
314 | 105 | from canonical.launchpad.webapp.menu import NavigationMenu | 106 | from canonical.launchpad.webapp.menu import NavigationMenu |
315 | 106 | from canonical.widgets.popup import PersonPickerWidget | 107 | from canonical.widgets.popup import PersonPickerWidget |
316 | 107 | from canonical.widgets.date import DateWidget | 108 | from canonical.widgets.date import DateWidget |
317 | @@ -897,17 +898,11 @@ | |||
318 | 897 | check_permission('launchpad.Commercial', self.context)) | 898 | check_permission('launchpad.Commercial', self.context)) |
319 | 898 | 899 | ||
320 | 899 | 900 | ||
322 | 900 | class ProductPackagesView(PackagingDeleteView): | 901 | class ProductPackagesView(LaunchpadView): |
323 | 901 | """View for displaying product packaging""" | 902 | """View for displaying product packaging""" |
324 | 902 | 903 | ||
325 | 903 | label = 'Linked packages' | 904 | label = 'Linked packages' |
333 | 904 | 905 | page_title = label | |
327 | 905 | @property | ||
328 | 906 | def all_packaging(self): | ||
329 | 907 | """See `PackagingDeleteView`.""" | ||
330 | 908 | for series in self.context.series: | ||
331 | 909 | for packaging in series.packagings: | ||
332 | 910 | yield packaging | ||
334 | 911 | 906 | ||
335 | 912 | @cachedproperty | 907 | @cachedproperty |
336 | 913 | def series_packages(self): | 908 | def series_packages(self): |
337 | @@ -921,23 +916,11 @@ | |||
338 | 921 | field: '<input type=''hidden' ...>}, | 916 | field: '<input type=''hidden' ...>}, |
339 | 922 | }] | 917 | }] |
340 | 923 | """ | 918 | """ |
341 | 924 | # This method is a superset of all_packaging. While all_packaging will | ||
342 | 925 | # be called several times as data is mutated, series_packages should | ||
343 | 926 | # only be called during render(). | ||
344 | 927 | packaged_series = [] | 919 | packaged_series = [] |
345 | 928 | for series in self.context.series: | 920 | for series in self.context.series: |
346 | 929 | packagings = [] | 921 | packagings = [] |
347 | 930 | for packaging in series.packagings: | 922 | for packaging in series.packagings: |
358 | 931 | form_id = 'delete-%s-%s-%s' % ( | 923 | packagings.append(packaging) |
349 | 932 | packaging.distroseries.name, | ||
350 | 933 | packaging.sourcepackagename.name, | ||
351 | 934 | packaging.productseries.name, | ||
352 | 935 | ) | ||
353 | 936 | packaging_field = dict( | ||
354 | 937 | packaging=packaging, | ||
355 | 938 | form_id=form_id, | ||
356 | 939 | field=self._renderHiddenPackagingField(packaging)) | ||
357 | 940 | packagings.append(packaging_field) | ||
359 | 941 | packaged_series.append(dict( | 924 | packaged_series.append(dict( |
360 | 942 | series=series, packagings=packagings)) | 925 | series=series, packagings=packagings)) |
361 | 943 | return packaged_series | 926 | return packaged_series |
362 | @@ -1262,7 +1245,8 @@ | |||
363 | 1262 | return canonical_url(self.context) | 1245 | return canonical_url(self.context) |
364 | 1263 | 1246 | ||
365 | 1264 | 1247 | ||
367 | 1265 | class ProductReviewLicenseView(ProductEditView, EditPrivateBugsMixin): | 1248 | class ProductReviewLicenseView(ReturnToReferrerMixin, |
368 | 1249 | ProductEditView, EditPrivateBugsMixin): | ||
369 | 1266 | """A view to review a project and change project privileges.""" | 1250 | """A view to review a project and change project privileges.""" |
370 | 1267 | label = "Review project" | 1251 | label = "Review project" |
371 | 1268 | field_names = [ | 1252 | field_names = [ |
372 | @@ -1302,27 +1286,6 @@ | |||
373 | 1302 | # supervisor. | 1286 | # supervisor. |
374 | 1303 | self.validate_private_bugs(data) | 1287 | self.validate_private_bugs(data) |
375 | 1304 | 1288 | ||
376 | 1305 | @property | ||
377 | 1306 | def next_url(self): | ||
378 | 1307 | """See `LaunchpadFormView`.""" | ||
379 | 1308 | # The referer header we want is only available before the view's | ||
380 | 1309 | # form submits to itself. This field is a hidden input in the form. | ||
381 | 1310 | referrer = self.request.form.get('next_url') | ||
382 | 1311 | if referrer is None: | ||
383 | 1312 | referrer = self.request.getHeader('referer') | ||
384 | 1313 | |||
385 | 1314 | if (referrer is not None | ||
386 | 1315 | and referrer.startswith(self.request.getApplicationURL())): | ||
387 | 1316 | return referrer | ||
388 | 1317 | else: | ||
389 | 1318 | return canonical_url(self.context) | ||
390 | 1319 | |||
391 | 1320 | @property | ||
392 | 1321 | def cancel_url(self): | ||
393 | 1322 | """See `LaunchpadFormView`.""" | ||
394 | 1323 | return self.next_url | ||
395 | 1324 | |||
396 | 1325 | |||
397 | 1326 | class ProductAddSeriesView(LaunchpadFormView): | 1289 | class ProductAddSeriesView(LaunchpadFormView): |
398 | 1327 | """A form to add new product series""" | 1290 | """A form to add new product series""" |
399 | 1328 | 1291 | ||
400 | @@ -1613,7 +1576,7 @@ | |||
401 | 1613 | self.request.form['summary'] = data['summary'] | 1576 | self.request.form['summary'] = data['summary'] |
402 | 1614 | 1577 | ||
403 | 1615 | 1578 | ||
405 | 1616 | class ProjectAddStepTwo(StepView, ProductLicenseMixin): | 1579 | class ProjectAddStepTwo(StepView, ProductLicenseMixin, ReturnToReferrerMixin): |
406 | 1617 | """Step 2 (of 2) in the +new project add wizard.""" | 1580 | """Step 2 (of 2) in the +new project add wizard.""" |
407 | 1618 | 1581 | ||
408 | 1619 | _field_names = ['displayname', 'name', 'title', 'summary', | 1582 | _field_names = ['displayname', 'name', 'title', 'summary', |
409 | 1620 | 1583 | ||
410 | === modified file 'lib/lp/registry/browser/sourcepackage.py' | |||
411 | --- lib/lp/registry/browser/sourcepackage.py 2010-02-23 19:43:58 +0000 | |||
412 | +++ lib/lp/registry/browser/sourcepackage.py 2010-03-06 06:27:33 +0000 | |||
413 | @@ -12,7 +12,8 @@ | |||
414 | 12 | 'SourcePackageFacets', | 12 | 'SourcePackageFacets', |
415 | 13 | 'SourcePackageHelpView', | 13 | 'SourcePackageHelpView', |
416 | 14 | 'SourcePackageNavigation', | 14 | 'SourcePackageNavigation', |
418 | 15 | 'SourcePackagePackaging', | 15 | 'SourcePackageRemoveUpstreamView', |
419 | 16 | 'SourcePackageUpstreamConnectionsView', | ||
420 | 16 | 'SourcePackageView', | 17 | 'SourcePackageView', |
421 | 17 | ] | 18 | ] |
422 | 18 | 19 | ||
423 | @@ -40,7 +41,7 @@ | |||
424 | 40 | from lp.answers.browser.questiontarget import ( | 41 | from lp.answers.browser.questiontarget import ( |
425 | 41 | QuestionTargetFacetMixin, QuestionTargetAnswersMenu) | 42 | QuestionTargetFacetMixin, QuestionTargetAnswersMenu) |
426 | 42 | from lp.services.worlddata.interfaces.country import ICountry | 43 | from lp.services.worlddata.interfaces.country import ICountry |
428 | 43 | from lp.registry.interfaces.packaging import IPackaging | 44 | from lp.registry.interfaces.packaging import IPackaging, IPackagingUtil |
429 | 44 | from lp.registry.interfaces.pocket import PackagePublishingPocket | 45 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
430 | 45 | from lp.registry.interfaces.product import IProductSet | 46 | from lp.registry.interfaces.product import IProductSet |
431 | 46 | from lp.registry.interfaces.productseries import IProductSeries | 47 | from lp.registry.interfaces.productseries import IProductSeries |
432 | @@ -49,12 +50,15 @@ | |||
433 | 49 | from lp.translations.interfaces.potemplate import IPOTemplateSet | 50 | from lp.translations.interfaces.potemplate import IPOTemplateSet |
434 | 50 | from canonical.launchpad import _ | 51 | from canonical.launchpad import _ |
435 | 51 | from canonical.launchpad.webapp import ( | 52 | from canonical.launchpad.webapp import ( |
438 | 52 | action, ApplicationMenu, custom_widget, GetitemNavigation, | 53 | ApplicationMenu, GetitemNavigation, Link, redirection, |
439 | 53 | LaunchpadFormView, Link, redirection, StandardLaunchpadFacets, stepto) | 54 | StandardLaunchpadFacets, stepto) |
440 | 55 | from canonical.launchpad.webapp.launchpadform import ( | ||
441 | 56 | action, custom_widget, LaunchpadFormView, ReturnToReferrerMixin) | ||
442 | 54 | from canonical.launchpad.webapp import canonical_url | 57 | from canonical.launchpad.webapp import canonical_url |
443 | 55 | from canonical.launchpad.webapp.authorization import check_permission | 58 | from canonical.launchpad.webapp.authorization import check_permission |
444 | 56 | from canonical.launchpad.webapp.breadcrumb import Breadcrumb | 59 | from canonical.launchpad.webapp.breadcrumb import Breadcrumb |
445 | 57 | from canonical.launchpad.webapp.menu import structured | 60 | from canonical.launchpad.webapp.menu import structured |
446 | 61 | from canonical.launchpad.webapp.publisher import LaunchpadView | ||
447 | 58 | 62 | ||
448 | 59 | from canonical.lazr.utils import smartquote | 63 | from canonical.lazr.utils import smartquote |
449 | 60 | 64 | ||
450 | @@ -108,7 +112,7 @@ | |||
451 | 108 | usedfor = ISourcePackage | 112 | usedfor = ISourcePackage |
452 | 109 | facet = 'overview' | 113 | facet = 'overview' |
453 | 110 | links = [ | 114 | links = [ |
455 | 111 | 'distribution_source_package', 'edit_packaging', | 115 | 'distribution_source_package', 'edit_packaging', 'remove_packaging', |
456 | 112 | 'changelog', 'builds', 'set_upstream', | 116 | 'changelog', 'builds', 'set_upstream', |
457 | 113 | ] | 117 | ] |
458 | 114 | 118 | ||
459 | @@ -124,6 +128,10 @@ | |||
460 | 124 | def edit_packaging(self): | 128 | def edit_packaging(self): |
461 | 125 | return Link('+edit-packaging', 'Change upstream link', icon='edit') | 129 | return Link('+edit-packaging', 'Change upstream link', icon='edit') |
462 | 126 | 130 | ||
463 | 131 | def remove_packaging(self): | ||
464 | 132 | return Link( | ||
465 | 133 | '+remove-packaging', 'Remove upstream link', icon='remove') | ||
466 | 134 | |||
467 | 127 | def set_upstream(self): | 135 | def set_upstream(self): |
468 | 128 | return Link("+edit-packaging", "Set upstream link", icon="add") | 136 | return Link("+edit-packaging", "Set upstream link", icon="add") |
469 | 129 | 137 | ||
470 | @@ -143,7 +151,7 @@ | |||
471 | 143 | return Link('+gethelp', 'Help and support options', icon='info') | 151 | return Link('+gethelp', 'Help and support options', icon='info') |
472 | 144 | 152 | ||
473 | 145 | 153 | ||
475 | 146 | class SourcePackageChangeUpstreamStepOne(StepView): | 154 | class SourcePackageChangeUpstreamStepOne(ReturnToReferrerMixin, StepView): |
476 | 147 | """A view to set the `IProductSeries` of a sourcepackage.""" | 155 | """A view to set the `IProductSeries` of a sourcepackage.""" |
477 | 148 | schema = Interface | 156 | schema = Interface |
478 | 149 | _field_names = [] | 157 | _field_names = [] |
479 | @@ -167,9 +175,8 @@ | |||
480 | 167 | IProductSeries['product'], default=default) | 175 | IProductSeries['product'], default=default) |
481 | 168 | self.form_fields += Fields(product_field) | 176 | self.form_fields += Fields(product_field) |
482 | 169 | 177 | ||
486 | 170 | @property | 178 | # Override ReturnToReferrerMixin.next_url. |
487 | 171 | def cancel_url(self): | 179 | next_url = None |
485 | 172 | return canonical_url(self.context) | ||
488 | 173 | 180 | ||
489 | 174 | def main_action(self, data): | 181 | def main_action(self, data): |
490 | 175 | """See `MultiStepView`.""" | 182 | """See `MultiStepView`.""" |
491 | @@ -177,7 +184,7 @@ | |||
492 | 177 | self.request.form['product'] = data['product'] | 184 | self.request.form['product'] = data['product'] |
493 | 178 | 185 | ||
494 | 179 | 186 | ||
496 | 180 | class SourcePackageChangeUpstreamStepTwo(StepView): | 187 | class SourcePackageChangeUpstreamStepTwo(ReturnToReferrerMixin, StepView): |
497 | 181 | """A view to set the `IProductSeries` of a sourcepackage.""" | 188 | """A view to set the `IProductSeries` of a sourcepackage.""" |
498 | 182 | schema = IProductSeries | 189 | schema = IProductSeries |
499 | 183 | _field_names = ['product'] | 190 | _field_names = ['product'] |
500 | @@ -196,10 +203,6 @@ | |||
501 | 196 | custom_widget('product', DropdownWidget, visible=False) | 203 | custom_widget('product', DropdownWidget, visible=False) |
502 | 197 | custom_widget('productseries', LaunchpadRadioWidget) | 204 | custom_widget('productseries', LaunchpadRadioWidget) |
503 | 198 | 205 | ||
504 | 199 | @property | ||
505 | 200 | def cancel_url(self): | ||
506 | 201 | return canonical_url(self.context) | ||
507 | 202 | |||
508 | 203 | def setUpFields(self): | 206 | def setUpFields(self): |
509 | 204 | super(SourcePackageChangeUpstreamStepTwo, self).setUpFields() | 207 | super(SourcePackageChangeUpstreamStepTwo, self).setUpFields() |
510 | 205 | 208 | ||
511 | @@ -261,12 +264,16 @@ | |||
512 | 261 | Fields(display_product_field, productseries_choice) | 264 | Fields(display_product_field, productseries_choice) |
513 | 262 | + self.form_fields) | 265 | + self.form_fields) |
514 | 263 | 266 | ||
515 | 267 | # Override ReturnToReferrerMixin.next_url until the main_action() | ||
516 | 268 | # is called. | ||
517 | 269 | next_url = None | ||
518 | 270 | |||
519 | 264 | main_action_label = u'Change' | 271 | main_action_label = u'Change' |
520 | 265 | def main_action(self, data): | 272 | def main_action(self, data): |
521 | 266 | productseries = data['productseries'] | 273 | productseries = data['productseries'] |
522 | 267 | # Because it is part of a multistep view, the next_url can't | 274 | # Because it is part of a multistep view, the next_url can't |
523 | 268 | # be set until the action is called, or it will skip the step. | 275 | # be set until the action is called, or it will skip the step. |
525 | 269 | self.next_url = canonical_url(self.context) | 276 | self.next_url = self._return_url |
526 | 270 | if self.context.productseries == productseries: | 277 | if self.context.productseries == productseries: |
527 | 271 | # There is nothing to do. | 278 | # There is nothing to do. |
528 | 272 | return | 279 | return |
529 | @@ -282,6 +289,27 @@ | |||
530 | 282 | first_step = SourcePackageChangeUpstreamStepOne | 289 | first_step = SourcePackageChangeUpstreamStepOne |
531 | 283 | 290 | ||
532 | 284 | 291 | ||
533 | 292 | class SourcePackageRemoveUpstreamView(ReturnToReferrerMixin, | ||
534 | 293 | LaunchpadFormView): | ||
535 | 294 | """A view for removing the link to an upstream package.""" | ||
536 | 295 | |||
537 | 296 | schema = Interface | ||
538 | 297 | field_names = [] | ||
539 | 298 | label = 'Unlink an upstream project' | ||
540 | 299 | page_title = label | ||
541 | 300 | |||
542 | 301 | @action('Unlink') | ||
543 | 302 | def unlink(self, action, data): | ||
544 | 303 | old_series = self.context.productseries | ||
545 | 304 | getUtility(IPackagingUtil).deletePackaging( | ||
546 | 305 | self.context.productseries, | ||
547 | 306 | self.context.sourcepackagename, | ||
548 | 307 | self.context.distroseries) | ||
549 | 308 | self.request.response.addInfoNotification( | ||
550 | 309 | 'Removed upstream association between %s and %s.' % ( | ||
551 | 310 | old_series.title, self.context.distroseries.displayname)) | ||
552 | 311 | |||
553 | 312 | |||
554 | 285 | class SourcePackageView: | 313 | class SourcePackageView: |
555 | 286 | """A view for (distro series) source packages.""" | 314 | """A view for (distro series) source packages.""" |
556 | 287 | 315 | ||
557 | @@ -411,6 +439,7 @@ | |||
558 | 411 | def setUpFields(self): | 439 | def setUpFields(self): |
559 | 412 | """See `LaunchpadFormView`.""" | 440 | """See `LaunchpadFormView`.""" |
560 | 413 | super(SourcePackageAssociationPortletView, self).setUpFields() | 441 | super(SourcePackageAssociationPortletView, self).setUpFields() |
561 | 442 | self.request.annotations['show_edit_buttons'] = True | ||
562 | 414 | # Find registered products that are similarly named to the source | 443 | # Find registered products that are similarly named to the source |
563 | 415 | # package. | 444 | # package. |
564 | 416 | product_vocab = getVocabularyRegistry().get(None, 'Product') | 445 | product_vocab = getVocabularyRegistry().get(None, 'Product') |
565 | @@ -444,6 +473,10 @@ | |||
566 | 444 | upstream.displayname) | 473 | upstream.displayname) |
567 | 445 | self.next_url = self.request.getURL() | 474 | self.next_url = self.request.getURL() |
568 | 446 | 475 | ||
569 | 476 | |||
570 | 477 | class SourcePackageUpstreamConnectionsView(LaunchpadView): | ||
571 | 478 | """A shared view with upstream connection info.""" | ||
572 | 479 | |||
573 | 447 | @property | 480 | @property |
574 | 448 | def has_bugtracker(self): | 481 | def has_bugtracker(self): |
575 | 449 | """Does the product have a bugtracker set?""" | 482 | """Does the product have a bugtracker set?""" |
576 | 450 | 483 | ||
577 | === modified file 'lib/lp/registry/browser/tests/packaging-views.txt' | |||
578 | --- lib/lp/registry/browser/tests/packaging-views.txt 2010-02-18 18:58:26 +0000 | |||
579 | +++ lib/lp/registry/browser/tests/packaging-views.txt 2010-03-06 06:27:33 +0000 | |||
580 | @@ -273,32 +273,19 @@ | |||
581 | 273 | >>> print view.label | 273 | >>> print view.label |
582 | 274 | Linked packages | 274 | Linked packages |
583 | 275 | 275 | ||
584 | 276 | The view defines the all_packages property used by the PackagingDeleteView | ||
585 | 277 | to create a vocabulary. | ||
586 | 278 | |||
587 | 279 | >>> for package in view.all_packaging: | ||
588 | 280 | ... print package.distroseries.name, package.productseries.name | ||
589 | 281 | grumpy hotter | ||
590 | 282 | hoary hotter | ||
591 | 283 | |||
592 | 284 | The view provides the series_packages property that returns a list of | 276 | The view provides the series_packages property that returns a list of |
595 | 285 | dicts. Each dict as a series and a list of package dicts. The package dict | 277 | dicts. Each dict as a series and a list of packages. |
594 | 286 | contains the package and field for form actions. | ||
596 | 287 | 278 | ||
603 | 288 | >>> for series_dict in view.series_packages: | 279 | >>> def print_packages(view): |
604 | 289 | ... print series_dict['series'].name | 280 | ... for series_dict in view.series_packages: |
605 | 290 | ... for package_dict in series_dict['packagings']: | 281 | ... print series_dict['series'].name |
606 | 291 | ... print package_dict['packaging'].distroseries.name | 282 | ... for package in series_dict['packagings']: |
607 | 292 | ... print package_dict['form_id'] | 283 | ... print package.distroseries.name |
608 | 293 | ... print package_dict['field'] | 284 | >>> print_packages(view) |
609 | 294 | cold | 285 | cold |
610 | 295 | hotter | 286 | hotter |
611 | 296 | grumpy | 287 | grumpy |
612 | 297 | delete-grumpy-hot-hotter | ||
613 | 298 | <input type="hidden" name="field.packaging" .../> | ||
614 | 299 | hoary | 288 | hoary |
615 | 300 | delete-hoary-thunderbird-hotter | ||
616 | 301 | <input type="hidden" name="field.packaging" .../> | ||
617 | 302 | trunk | 289 | trunk |
618 | 303 | 290 | ||
619 | 304 | The view provides the distro_packaging property that is a list of | 291 | The view provides the distro_packaging property that is a list of |
620 | @@ -306,40 +293,48 @@ | |||
621 | 306 | sorted by distribution with Ubuntu first and the rest in alphabetic | 293 | sorted by distribution with Ubuntu first and the rest in alphabetic |
622 | 307 | order. | 294 | order. |
623 | 308 | 295 | ||
624 | 309 | >>> view = create_initialized_view(product, name='+packages') | ||
625 | 310 | >>> for distro_dict in view.distro_packaging: | 296 | >>> for distro_dict in view.distro_packaging: |
626 | 311 | ... print distro_dict['distribution'].name | 297 | ... print distro_dict['distribution'].name |
627 | 312 | ubuntu | 298 | ubuntu |
628 | 313 | 299 | ||
629 | 314 | The +packages named view descends from PackagingDeleteView to provide remove | ||
630 | 315 | link actions for the product's linked packages. | ||
631 | 316 | |||
632 | 317 | >>> from lp.registry.browser.packaging import PackagingDeleteView | ||
633 | 318 | |||
634 | 319 | >>> isinstance(view, PackagingDeleteView) | ||
635 | 320 | True | ||
636 | 321 | |||
637 | 322 | A packaging link can be deleted if the owner believes it is an error. The | 300 | A packaging link can be deleted if the owner believes it is an error. The |
638 | 323 | package linked to hoary is wrong; thunderbird is the wrong sourcepackage. | 301 | package linked to hoary is wrong; thunderbird is the wrong sourcepackage. |
639 | 324 | 302 | ||
640 | 303 | >>> from canonical.launchpad.testing.pages import find_tag_by_id | ||
641 | 304 | >>> view = create_initialized_view( | ||
642 | 305 | ... product, name='+packages', principal=a_user) | ||
643 | 306 | >>> print_packages(view) | ||
644 | 307 | cold | ||
645 | 308 | hotter | ||
646 | 309 | grumpy | ||
647 | 310 | hoary | ||
648 | 311 | trunk | ||
649 | 312 | |||
650 | 313 | # There are links to the +remove-packaging page. | ||
651 | 314 | >>> table = find_tag_by_id(view.render(), 'packages-hotter') | ||
652 | 315 | >>> for link in table.findAll('a'): | ||
653 | 316 | ... if '+remove-packaging' in link['href']: | ||
654 | 317 | ... print link['href'] | ||
655 | 318 | http://launchpad.dev/ubuntu/grumpy/+source/hot/+remove-packaging | ||
656 | 319 | http://launchpad.dev/ubuntu/hoary/+source/thunderbird/+remove-packaging | ||
657 | 320 | |||
658 | 321 | >>> [hoary_package] = [ | ||
659 | 322 | ... package for series_dict in view.series_packages | ||
660 | 323 | ... for package in series_dict['packagings'] | ||
661 | 324 | ... if package.distroseries.name == 'hoary'] | ||
662 | 325 | >>> form = {'field.actions.unlink': 'Unlink'} | ||
663 | 326 | >>> unlink_view = create_initialized_view( | ||
664 | 327 | ... hoary_package.sourcepackage, name='+remove-packaging', form=form) | ||
665 | 328 | >>> unlink_view.errors | ||
666 | 329 | [] | ||
667 | 330 | |||
668 | 331 | # The view has to be reloaded since view.series_packages is cached. | ||
669 | 325 | >>> view = create_initialized_view(product, name='+packages') | 332 | >>> view = create_initialized_view(product, name='+packages') |
687 | 326 | >>> for package in view.all_packaging: | 333 | >>> print_packages(view) |
688 | 327 | ... print package.distroseries.name, package.productseries.name | 334 | cold |
689 | 328 | grumpy hotter | 335 | hotter |
690 | 329 | hoary hotter | 336 | grumpy |
691 | 330 | 337 | trunk | |
675 | 331 | >>> [hoary_package] = [package for package in view.all_packaging | ||
676 | 332 | ... if package.distroseries.name == 'hoary'] | ||
677 | 333 | >>> form = { | ||
678 | 334 | ... 'field.packaging': '%s' % hoary_package.id, | ||
679 | 335 | ... 'field.actions.delete_packaging': 'Delete upstream link', | ||
680 | 336 | ... } | ||
681 | 337 | >>> view = create_initialized_view(product, name='+packages', form=form) | ||
682 | 338 | >>> view.errors | ||
683 | 339 | [] | ||
684 | 340 | >>> for package in view.all_packaging: | ||
685 | 341 | ... print package.distroseries.name, package.productseries.name | ||
686 | 342 | grumpy hotter | ||
692 | 343 | 338 | ||
693 | 344 | 339 | ||
694 | 345 | Distro series +packaging view | 340 | Distro series +packaging view |
695 | 346 | 341 | ||
696 | === modified file 'lib/lp/registry/browser/tests/sourcepackage-views.txt' | |||
697 | --- lib/lp/registry/browser/tests/sourcepackage-views.txt 2010-02-18 20:39:01 +0000 | |||
698 | +++ lib/lp/registry/browser/tests/sourcepackage-views.txt 2010-03-06 06:27:33 +0000 | |||
699 | @@ -145,6 +145,7 @@ | |||
700 | 145 | >>> print view.request.response.notifications | 145 | >>> print view.request.response.notifications |
701 | 146 | [] | 146 | [] |
702 | 147 | 147 | ||
703 | 148 | |||
704 | 148 | Upstream associations portlet | 149 | Upstream associations portlet |
705 | 149 | ----------------------------- | 150 | ----------------------------- |
706 | 150 | 151 | ||
707 | @@ -163,12 +164,18 @@ | |||
708 | 163 | 164 | ||
709 | 164 | >>> from canonical.launchpad.testing.pages import ( | 165 | >>> from canonical.launchpad.testing.pages import ( |
710 | 165 | ... extract_text, find_tag_by_id) | 166 | ... extract_text, find_tag_by_id) |
714 | 166 | >>> content = extract_text(find_tag_by_id(view.render(), 'upstreams')) | 167 | >>> content = find_tag_by_id(view.render(), 'upstreams') |
715 | 167 | >>> print content | 168 | >>> for link in content.findAll('a'): |
716 | 168 | Bonkers project | 169 | ... print link['href'] |
717 | 170 | /bonkers | ||
718 | 171 | /bonkers/crazy | ||
719 | 172 | .../+source/bonkers/+edit-packaging | ||
720 | 173 | .../+source/bonkers/+remove-packaging | ||
721 | 174 | |||
722 | 175 | >>> print extract_text(content) | ||
723 | 176 | Bonkers...crazy... | ||
724 | 169 | Bug supervisor: no | 177 | Bug supervisor: no |
725 | 170 | Bug tracker: no | 178 | Bug tracker: no |
726 | 171 | Bonkers crazy series | ||
727 | 172 | Branch: no | 179 | Branch: no |
728 | 173 | 180 | ||
729 | 174 | A new source project that is not linked to an upstream will result in | 181 | A new source project that is not linked to an upstream will result in |
730 | @@ -211,6 +218,9 @@ | |||
731 | 211 | Lernid Dev... | 218 | Lernid Dev... |
732 | 212 | 219 | ||
733 | 213 | 220 | ||
734 | 221 | Upstream connections view | ||
735 | 222 | ------------------------- | ||
736 | 223 | |||
737 | 214 | The view includes a property for determining if the project has a bug | 224 | The view includes a property for determining if the project has a bug |
738 | 215 | tracker, though the rules are somewhat complicated. | 225 | tracker, though the rules are somewhat complicated. |
739 | 216 | 226 | ||
740 | @@ -226,7 +236,8 @@ | |||
741 | 226 | >>> package = factory.makeSourcePackage( | 236 | >>> package = factory.makeSourcePackage( |
742 | 227 | ... sourcepackagename=sourcepackagename, distroseries=distroseries) | 237 | ... sourcepackagename=sourcepackagename, distroseries=distroseries) |
743 | 228 | 238 | ||
745 | 229 | >>> view = create_initialized_view(package, name='+portlet-associations') | 239 | >>> view = create_initialized_view( |
746 | 240 | ... package, name='+upstream-connections') | ||
747 | 230 | 241 | ||
748 | 231 | >>> print package.productseries | 242 | >>> print package.productseries |
749 | 232 | None | 243 | None |
750 | @@ -242,7 +253,8 @@ | |||
751 | 242 | If a product is not part of a project group and its bug tracker is not | 253 | If a product is not part of a project group and its bug tracker is not |
752 | 243 | set then the view property is false. | 254 | set then the view property is false. |
753 | 244 | 255 | ||
755 | 245 | >>> view = create_initialized_view(package, name='+portlet-associations') | 256 | >>> view = create_initialized_view( |
756 | 257 | ... package, name='+upstream-connections') | ||
757 | 246 | 258 | ||
758 | 247 | >>> print product.official_malone | 259 | >>> print product.official_malone |
759 | 248 | False | 260 | False |
760 | @@ -285,3 +297,37 @@ | |||
761 | 285 | >>> project.bugtracker = bugtracker | 297 | >>> project.bugtracker = bugtracker |
762 | 286 | >>> print view.has_bugtracker | 298 | >>> print view.has_bugtracker |
763 | 287 | True | 299 | True |
764 | 300 | |||
765 | 301 | |||
766 | 302 | Remove packaging view | ||
767 | 303 | --------------------- | ||
768 | 304 | |||
769 | 305 | This view allows removal of the packaging link from the sourcepackage | ||
770 | 306 | to the project series. | ||
771 | 307 | |||
772 | 308 | >>> view = create_initialized_view(package, name='+remove-packaging') | ||
773 | 309 | >>> print view.label | ||
774 | 310 | Unlink an upstream project | ||
775 | 311 | |||
776 | 312 | >>> print view.page_title | ||
777 | 313 | Unlink an upstream project | ||
778 | 314 | |||
779 | 315 | >>> print view.cancel_url | ||
780 | 316 | http://launchpad.dev/youbuntu/wonky/+source/stinkypackage | ||
781 | 317 | |||
782 | 318 | >>> form = {'field.actions.unlink': 'Unlink'} | ||
783 | 319 | >>> view = create_initialized_view( | ||
784 | 320 | ... package, name='+remove-packaging', form=form, | ||
785 | 321 | ... principal=product.owner) | ||
786 | 322 | >>> view.errors | ||
787 | 323 | [] | ||
788 | 324 | |||
789 | 325 | >>> for notification in view.request.response.notifications: | ||
790 | 326 | ... print notification.message | ||
791 | 327 | Removed upstream association between Stinky stinkyseries series and Wonky. | ||
792 | 328 | |||
793 | 329 | >>> view = create_initialized_view(package, name='+portlet-associations') | ||
794 | 330 | >>> print extract_text(find_tag_by_id(view.render(), 'no-upstreams')) | ||
795 | 331 | There are no projects registered in Launchpad that are a potential | ||
796 | 332 | match for this source package. Can you help us find one? | ||
797 | 333 | Set upstream link | ||
798 | 288 | 334 | ||
799 | === modified file 'lib/lp/registry/browser/tests/test_packaging.py' | |||
800 | --- lib/lp/registry/browser/tests/test_packaging.py 2009-10-23 12:53:21 +0000 | |||
801 | +++ lib/lp/registry/browser/tests/test_packaging.py 2010-03-06 06:27:33 +0000 | |||
802 | @@ -55,8 +55,10 @@ | |||
803 | 55 | # Delete the packaging | 55 | # Delete the packaging |
804 | 56 | user_browser = self.user_browser | 56 | user_browser = self.user_browser |
805 | 57 | user_browser.open('http://launchpad.dev/ubuntu/+source/alsa-utils') | 57 | user_browser.open('http://launchpad.dev/ubuntu/+source/alsa-utils') |
808 | 58 | form = user_browser.getForm("delete_warty_alsa-utils_trunk") | 58 | link = user_browser.getLink( |
809 | 59 | form.getControl(name="field.actions.delete_packaging").click() | 59 | url='/ubuntu/warty/+source/alsa-utils/+remove-packaging') |
810 | 60 | link.click() | ||
811 | 61 | user_browser.getControl('Unlink').click() | ||
812 | 60 | # Check that the change was committed. | 62 | # Check that the change was committed. |
813 | 61 | login('no-priv@canonical.com') | 63 | login('no-priv@canonical.com') |
814 | 62 | self.assertFalse(packaging_util.packagingEntryExists( | 64 | self.assertFalse(packaging_util.packagingEntryExists( |
815 | 63 | 65 | ||
816 | === modified file 'lib/lp/registry/model/productseries.py' | |||
817 | --- lib/lp/registry/model/productseries.py 2010-02-25 21:37:02 +0000 | |||
818 | +++ lib/lp/registry/model/productseries.py 2010-03-06 06:27:33 +0000 | |||
819 | @@ -412,8 +412,10 @@ | |||
820 | 412 | 412 | ||
821 | 413 | # ok, we didn't find a packaging record that matches, let's go ahead | 413 | # ok, we didn't find a packaging record that matches, let's go ahead |
822 | 414 | # and create one | 414 | # and create one |
825 | 415 | pkg = Packaging(distroseries=distroseries, | 415 | pkg = Packaging( |
826 | 416 | sourcepackagename=sourcepackagename, productseries=self, | 416 | distroseries=distroseries, |
827 | 417 | sourcepackagename=sourcepackagename, | ||
828 | 418 | productseries=self, | ||
829 | 417 | packaging=PackagingType.PRIME, | 419 | packaging=PackagingType.PRIME, |
830 | 418 | owner=owner) | 420 | owner=owner) |
831 | 419 | pkg.sync() # convert UTC_NOW to actual datetime | 421 | pkg.sync() # convert UTC_NOW to actual datetime |
832 | 420 | 422 | ||
833 | === modified file 'lib/lp/registry/model/sourcepackage.py' | |||
834 | --- lib/lp/registry/model/sourcepackage.py 2010-02-25 21:37:02 +0000 | |||
835 | +++ lib/lp/registry/model/sourcepackage.py 2010-03-06 06:27:33 +0000 | |||
836 | @@ -477,10 +477,11 @@ | |||
837 | 477 | target.datecreated = UTC_NOW | 477 | target.datecreated = UTC_NOW |
838 | 478 | else: | 478 | else: |
839 | 479 | # ok, we need to create a new one | 479 | # ok, we need to create a new one |
844 | 480 | Packaging(distroseries=self.distroseries, | 480 | Packaging( |
845 | 481 | sourcepackagename=self.sourcepackagename, | 481 | distroseries=self.distroseries, |
846 | 482 | productseries=productseries, owner=user, | 482 | sourcepackagename=self.sourcepackagename, |
847 | 483 | packaging=PackagingType.PRIME) | 483 | productseries=productseries, owner=user, |
848 | 484 | packaging=PackagingType.PRIME) | ||
849 | 484 | # and make sure this change is immediately available | 485 | # and make sure this change is immediately available |
850 | 485 | flush_database_updates() | 486 | flush_database_updates() |
851 | 486 | 487 | ||
852 | 487 | 488 | ||
853 | === modified file 'lib/lp/registry/stories/distroseries/xx-show-distroseries-packaging.txt' | |||
854 | --- lib/lp/registry/stories/distroseries/xx-show-distroseries-packaging.txt 2010-02-25 16:36:02 +0000 | |||
855 | +++ lib/lp/registry/stories/distroseries/xx-show-distroseries-packaging.txt 2010-03-06 06:27:33 +0000 | |||
856 | @@ -17,12 +17,13 @@ | |||
857 | 17 | Source Package Upstream Project Upstream Contributor Connections | 17 | Source Package Upstream Project Upstream Contributor Connections |
858 | 18 | netapplet | 18 | netapplet |
859 | 19 | NetApplet ... The Novell Network Applet | 19 | NetApplet ... The Novell Network Applet |
862 | 20 | NetApplet ... project: Bug supervisor: no Bug tracker: yes | 20 | GNOME...NetApplet...trunk |
863 | 21 | NetApplet trunk series: Branch: no | 21 | ...Bug supervisor: no Bug tracker: yes Branch: no |
864 | 22 | evolution | 22 | evolution |
865 | 23 | Evolution ... Evolution is an email client, addressbook ... | 23 | Evolution ... Evolution is an email client, addressbook ... |
868 | 24 | Evolution ... project: Bug supervisor: no Bug tracker: yes | 24 | GNOME...Evolution...trunk |
869 | 25 | Evolution trunk series: Branch: yes Translations: no | 25 | ...Bug supervisor: no Bug tracker: yes |
870 | 26 | Branch: yes Translations: no | ||
871 | 26 | 27 | ||
872 | 27 | Any use can see that this page is related to the needs packaging report. It | 28 | Any use can see that this page is related to the needs packaging report. It |
873 | 28 | is linked, but the link to this page is not enabled. | 29 | is linked, but the link to this page is not enabled. |
874 | 29 | 30 | ||
875 | === modified file 'lib/lp/registry/stories/packaging/xx-distributionsourcepackage-packaging-concurrent-deletion.txt' | |||
876 | --- lib/lp/registry/stories/packaging/xx-distributionsourcepackage-packaging-concurrent-deletion.txt 2009-10-23 12:53:21 +0000 | |||
877 | +++ lib/lp/registry/stories/packaging/xx-distributionsourcepackage-packaging-concurrent-deletion.txt 2010-03-06 06:27:33 +0000 | |||
878 | @@ -16,33 +16,28 @@ | |||
879 | 16 | Then the user click the "Delete Link" button in the first tab. The | 16 | Then the user click the "Delete Link" button in the first tab. The |
880 | 17 | deletion succeeds and the usual informational message is displayed. | 17 | deletion succeeds and the usual informational message is displayed. |
881 | 18 | 18 | ||
884 | 19 | >>> form = first_browser.getForm("delete_warty_alsa-utils_trunk") | 19 | >>> link = first_browser.getLink( |
885 | 20 | >>> form.getControl(name="field.actions.delete_packaging").click() | 20 | ... url='/ubuntu/warty/+source/alsa-utils/+remove-packaging') |
886 | 21 | >>> link.click() | ||
887 | 22 | >>> first_browser.getControl('Unlink').click() | ||
888 | 21 | >>> content = first_browser.contents | 23 | >>> content = first_browser.contents |
889 | 22 | >>> for tag in find_tags_by_class(content, 'error'): | 24 | >>> for tag in find_tags_by_class(content, 'error'): |
890 | 23 | ... print extract_text(tag) | 25 | ... print extract_text(tag) |
891 | 24 | >>> for tag in find_tags_by_class(content, 'informational'): | 26 | >>> for tag in find_tags_by_class(content, 'informational'): |
892 | 25 | ... print extract_text(tag) | 27 | ... print extract_text(tag) |
894 | 26 | Removed upstream association between alsa-utils trunk and Warty. | 28 | Removed upstream association between alsa-utils trunk series and Warty. |
895 | 27 | 29 | ||
896 | 28 | A few minutes later, the user sees the same packaging association in the | 30 | A few minutes later, the user sees the same packaging association in the |
897 | 29 | second tab, and clicks the "Delete Link" button again. | 31 | second tab, and clicks the "Delete Link" button again. |
898 | 30 | 32 | ||
899 | 31 | The packaging object has been deleted already, so this action cannot | 33 | The packaging object has been deleted already, so this action cannot |
910 | 32 | succeed. We yield a more useful error message than the mysterious | 34 | succeed. |
911 | 33 | "Invalid value" displayed by default. | 35 | |
912 | 34 | 36 | >>> second_browser.getLink( | |
913 | 35 | XXX: We would like to display an informational message and no error | 37 | ... url='/ubuntu/warty/+source/alsa-utils/+remove-packaging').click() |
904 | 36 | message, but it would be too much trouble for a corner case like this. | ||
905 | 37 | So we resort to just displaying a helpful error message. | ||
906 | 38 | -- David Allouche 2007-12-07 | ||
907 | 39 | |||
908 | 40 | >>> form = second_browser.getForm("delete_warty_alsa-utils_trunk") | ||
909 | 41 | >>> form.getControl(name="field.actions.delete_packaging").click() | ||
914 | 42 | >>> content = second_browser.contents | 38 | >>> content = second_browser.contents |
915 | 43 | >>> for tag in find_tags_by_class(content, 'informational'): | 39 | >>> for tag in find_tags_by_class(content, 'informational'): |
916 | 44 | ... print extract_text(tag) | 40 | ... print extract_text(tag) |
917 | 45 | >>> for tag in find_tags_by_class(content, 'error'): | 41 | >>> for tag in find_tags_by_class(content, 'error'): |
918 | 46 | ... print extract_text(tag) | 42 | ... print extract_text(tag) |
919 | 47 | There is 1 error. | ||
920 | 48 | This upstream association was deleted already. | 43 | This upstream association was deleted already. |
921 | 49 | 44 | ||
922 | === modified file 'lib/lp/registry/stories/packaging/xx-distributionsourcepackage-packaging.txt' | |||
923 | --- lib/lp/registry/stories/packaging/xx-distributionsourcepackage-packaging.txt 2009-10-23 12:53:21 +0000 | |||
924 | +++ lib/lp/registry/stories/packaging/xx-distributionsourcepackage-packaging.txt 2010-03-06 06:27:33 +0000 | |||
925 | @@ -15,6 +15,7 @@ | |||
926 | 15 | The Hoary Hedgehog Release (active development) Set upstream link | 15 | The Hoary Hedgehog Release (active development) Set upstream link |
927 | 16 | 1.0.9a-4ubuntu1 release (main) ... weeks ago | 16 | 1.0.9a-4ubuntu1 release (main) ... weeks ago |
928 | 17 | The Warty Warthog Release (current stable release) alsa-utils trunk series | 17 | The Warty Warthog Release (current stable release) alsa-utils trunk series |
929 | 18 | ... | ||
930 | 18 | 1.0.8-1ubuntu1 release (main) ... weeks ago | 19 | 1.0.8-1ubuntu1 release (main) ... weeks ago |
931 | 19 | 1.0.9a-4 release (main) ... weeks ago | 20 | 1.0.9a-4 release (main) ... weeks ago |
932 | 20 | 21 | ||
933 | @@ -26,9 +27,10 @@ | |||
934 | 26 | packaging links. | 27 | packaging links. |
935 | 27 | 28 | ||
936 | 28 | >>> user_browser.open('http://launchpad.dev/ubuntu/+source/alsa-utils') | 29 | >>> user_browser.open('http://launchpad.dev/ubuntu/+source/alsa-utils') |
940 | 29 | >>> form = user_browser.getForm("delete_warty_alsa-utils_trunk") | 30 | >>> link = user_browser.getLink( |
941 | 30 | >>> print form.getControl(name="field.actions.delete_packaging") | 31 | ... url='/ubuntu/warty/+source/alsa-utils/+remove-packaging') |
942 | 31 | <ImageControl name='field.actions.delete_packaging' type='image'> | 32 | >>> print link |
943 | 33 | <Link text='Remove upstream link'... | ||
944 | 32 | 34 | ||
945 | 33 | This button is not displayed to anonymous users. | 35 | This button is not displayed to anonymous users. |
946 | 34 | 36 | ||
947 | @@ -40,14 +42,16 @@ | |||
948 | 40 | 42 | ||
949 | 41 | Clicking this button deletes the corresponding packaging association. | 43 | Clicking this button deletes the corresponding packaging association. |
950 | 42 | 44 | ||
953 | 43 | >>> form = user_browser.getForm("delete_warty_alsa-utils_trunk") | 45 | >>> link = user_browser.getLink( |
954 | 44 | >>> form.getControl(name="field.actions.delete_packaging").click() | 46 | ... url='/ubuntu/warty/+source/alsa-utils/+remove-packaging') |
955 | 47 | >>> link.click() | ||
956 | 48 | >>> user_browser.getControl('Unlink').click() | ||
957 | 45 | >>> content = user_browser.contents | 49 | >>> content = user_browser.contents |
958 | 46 | >>> for tag in find_tags_by_class(content, 'error'): | 50 | >>> for tag in find_tags_by_class(content, 'error'): |
959 | 47 | ... print extract_text(tag) | 51 | ... print extract_text(tag) |
960 | 48 | >>> for tag in find_tags_by_class(content, 'informational'): | 52 | >>> for tag in find_tags_by_class(content, 'informational'): |
961 | 49 | ... print extract_text(tag) | 53 | ... print extract_text(tag) |
963 | 50 | Removed upstream association between alsa-utils trunk and Warty. | 54 | Removed upstream association between alsa-utils trunk series and Warty. |
964 | 51 | >>> print extract_text(find_tag_by_id(content, 'packages_list')) | 55 | >>> print extract_text(find_tag_by_id(content, 'packages_list')) |
965 | 52 | The Hoary Hedgehog Release (active development) Set upstream link | 56 | The Hoary Hedgehog Release (active development) Set upstream link |
966 | 53 | 1.0.9a-4ubuntu1 release (main) ... weeks ago | 57 | 1.0.9a-4ubuntu1 release (main) ... weeks ago |
967 | 54 | 58 | ||
968 | === modified file 'lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt' | |||
969 | --- lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt 2010-02-18 20:41:01 +0000 | |||
970 | +++ lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt 2010-03-06 06:27:33 +0000 | |||
971 | @@ -29,11 +29,9 @@ | |||
972 | 29 | >>> user_browser.getControl("Change").click() | 29 | >>> user_browser.getControl("Change").click() |
973 | 30 | >>> print extract_text(find_tag_by_id( | 30 | >>> print extract_text(find_tag_by_id( |
974 | 31 | ... user_browser.contents, 'upstreams')) | 31 | ... user_browser.contents, 'upstreams')) |
977 | 32 | Mozilla Thunderbird ... project | 32 | the Mozilla Project...Mozilla Thunderbird...trunk... |
976 | 33 | Project Group: the Mozilla Project | ||
978 | 34 | Bug supervisor: no | 33 | Bug supervisor: no |
979 | 35 | Bug tracker: no | 34 | Bug tracker: no |
980 | 36 | Mozilla Thunderbird trunk series | ||
981 | 37 | Branch: no | 35 | Branch: no |
982 | 38 | Translations: no | 36 | Translations: no |
983 | 39 | 37 | ||
984 | 40 | 38 | ||
985 | === modified file 'lib/lp/registry/stories/product/xx-product-package-pages.txt' | |||
986 | --- lib/lp/registry/stories/product/xx-product-package-pages.txt 2010-01-12 22:34:51 +0000 | |||
987 | +++ lib/lp/registry/stories/product/xx-product-package-pages.txt 2010-03-06 06:27:33 +0000 | |||
988 | @@ -30,8 +30,8 @@ | |||
989 | 30 | >>> print extract_text(find_tag_by_id( | 30 | >>> print extract_text(find_tag_by_id( |
990 | 31 | ... evo_owner.contents, 'packages-trunk')) | 31 | ... evo_owner.contents, 'packages-trunk')) |
991 | 32 | Distribution Distribution series Source package Version | 32 | Distribution Distribution series Source package Version |
994 | 33 | Ubuntu Warty (4.10) evolution | 33 | Ubuntu Warty (4.10) evolution Remove... |
995 | 34 | Ubuntu Hoary (5.04) evolution 1.0 | 34 | Ubuntu Hoary (5.04) evolution 1.0 Remove... |
996 | 35 | 35 | ||
997 | 36 | >>> evo_owner.getLink(url='/ubuntu/hoary/+source/evolution') is not None | 36 | >>> evo_owner.getLink(url='/ubuntu/hoary/+source/evolution') is not None |
998 | 37 | True | 37 | True |
999 | @@ -54,16 +54,19 @@ | |||
1000 | 54 | 54 | ||
1001 | 55 | Packaging links can be deleted if they were created in error. | 55 | Packaging links can be deleted if they were created in error. |
1002 | 56 | 56 | ||
1007 | 57 | >>> form = evo_owner.getForm("delete-warty-evolution-trunk") | 57 | >>> evo_owner.getLink( |
1008 | 58 | >>> form.getControl(name="field.actions.delete_packaging").click() | 58 | ... url='/ubuntu/warty/+source/evolution/+remove-packaging').click() |
1009 | 59 | >>> print evo_owner.title | 59 | >>> print evo_owner.title |
1010 | 60 | Linked packages ... | 60 | Unlink an upstream project... |
1011 | 61 | >>> evo_owner.getControl('Unlink').click() | ||
1012 | 62 | >>> print evo_owner.title | ||
1013 | 63 | Linked packages... | ||
1014 | 61 | 64 | ||
1015 | 62 | >>> for message in get_feedback_messages(evo_owner.contents): | 65 | >>> for message in get_feedback_messages(evo_owner.contents): |
1016 | 63 | ... print message | 66 | ... print message |
1018 | 64 | Removed upstream association between Evolution trunk and Warty. | 67 | Removed upstream association between Evolution trunk series and Warty. |
1019 | 65 | 68 | ||
1020 | 66 | >>> print extract_text(find_tag_by_id( | 69 | >>> print extract_text(find_tag_by_id( |
1021 | 67 | ... evo_owner.contents, 'packages-trunk')) | 70 | ... evo_owner.contents, 'packages-trunk')) |
1022 | 68 | Distribution Distribution series Source package Version | 71 | Distribution Distribution series Source package Version |
1024 | 69 | Ubuntu Hoary (5.04) evolution 1.0 | 72 | Ubuntu Hoary (5.04) evolution 1.0 Remove... |
1025 | 70 | 73 | ||
1026 | === modified file 'lib/lp/registry/stories/productseries/xx-productseries-delete.txt' | |||
1027 | --- lib/lp/registry/stories/productseries/xx-productseries-delete.txt 2009-12-14 13:49:03 +0000 | |||
1028 | +++ lib/lp/registry/stories/productseries/xx-productseries-delete.txt 2010-03-06 06:27:33 +0000 | |||
1029 | @@ -46,8 +46,10 @@ | |||
1030 | 46 | Mozilla Firefox in Launchpad | 46 | Mozilla Firefox in Launchpad |
1031 | 47 | 47 | ||
1032 | 48 | >>> owner_browser.getLink('All packages').click() | 48 | >>> owner_browser.getLink('All packages').click() |
1035 | 49 | >>> owner_browser.getControl( | 49 | >>> link = owner_browser.getLink( |
1036 | 50 | ... name='field.actions.delete_packaging', index=1).click() | 50 | ... url='/ubuntu/warty/+source/mozilla-firefox/+remove-packaging') |
1037 | 51 | >>> link.click() | ||
1038 | 52 | >>> owner_browser.getControl('Unlink').click() | ||
1039 | 51 | 53 | ||
1040 | 52 | Then he returns to delete trunk. He is informed that deletion is permanent, | 54 | Then he returns to delete trunk. He is informed that deletion is permanent, |
1041 | 53 | and that the milestones, releases, and files will also be deleted. The | 55 | and that the milestones, releases, and files will also be deleted. The |
1042 | 54 | 56 | ||
1043 | === modified file 'lib/lp/registry/templates/distributionsourcepackage-index.pt' | |||
1044 | --- lib/lp/registry/templates/distributionsourcepackage-index.pt 2010-02-09 15:38:13 +0000 | |||
1045 | +++ lib/lp/registry/templates/distributionsourcepackage-index.pt 2010-03-06 06:27:33 +0000 | |||
1046 | @@ -28,21 +28,6 @@ | |||
1047 | 28 | </tal:side> | 28 | </tal:side> |
1048 | 29 | 29 | ||
1049 | 30 | <tal:main metal:fill-slot="main"> | 30 | <tal:main metal:fill-slot="main"> |
1050 | 31 | <p class="error message" | ||
1051 | 32 | tal:condition="view/errors" | ||
1052 | 33 | tal:content="view/error_count" /> | ||
1053 | 34 | <p class="error message" | ||
1054 | 35 | tal:repeat="form_wide_error view/form_wide_errors" | ||
1055 | 36 | tal:content="structure form_wide_error"> | ||
1056 | 37 | Schema validation errors. | ||
1057 | 38 | </p> | ||
1058 | 39 | <p class="error message" | ||
1059 | 40 | tal:define="error python:view.getFieldError('packaging')" | ||
1060 | 41 | tal:condition="error" | ||
1061 | 42 | tal:content="structure error"> | ||
1062 | 43 | Field specific error for the hidden packaging field. | ||
1063 | 44 | </p> | ||
1064 | 45 | |||
1065 | 46 | <div class="top-portlet" id="bugs-and-questions-summary" | 31 | <div class="top-portlet" id="bugs-and-questions-summary" |
1066 | 47 | tal:define="newbugs context/new_bugtasks/count; | 32 | tal:define="newbugs context/new_bugtasks/count; |
1067 | 48 | open_questions view/open_questions/count"> | 33 | open_questions view/open_questions/count"> |
1068 | @@ -141,25 +126,14 @@ | |||
1069 | 141 | <a tal:attributes="href row/series_package/fmt:url" | 126 | <a tal:attributes="href row/series_package/fmt:url" |
1070 | 142 | tal:content="row/distroseries/title"/> | 127 | tal:content="row/distroseries/title"/> |
1071 | 143 | (<span tal:replace="row/distroseries/status/title/lower"/>) | 128 | (<span tal:replace="row/distroseries/status/title/lower"/>) |
1073 | 144 | <div style="float:right;"> | 129 | <div style="float:right; white-space: nowrap"> |
1074 | 145 | <a tal:condition="not: row/packaging" | 130 | <a tal:condition="not: row/packaging" |
1075 | 146 | tal:replace="structure row/series_package/menu:overview/set_upstream/fmt:link"/> | 131 | tal:replace="structure row/series_package/menu:overview/set_upstream/fmt:link"/> |
1076 | 147 | <tal:has_packaging condition="row/packaging"> | 132 | <tal:has_packaging condition="row/packaging"> |
1077 | 148 | <img tal:replace="structure row/packaging/productseries/image:icon"/> | 133 | <img tal:replace="structure row/packaging/productseries/image:icon"/> |
1078 | 149 | <a tal:replace="structure row/packaging/productseries/fmt:link"/> | 134 | <a tal:replace="structure row/packaging/productseries/fmt:link"/> |
1092 | 150 | <form style="display: inline" | 135 | <a tal:replace="structure row/series_package/menu:overview/edit_packaging/fmt:icon"/> |
1093 | 151 | method="POST" | 136 | <a tal:replace="structure row/series_package/menu:overview/remove_packaging/fmt:icon" /> |
1081 | 152 | tal:condition="row/hidden_packaging_field" | ||
1082 | 153 | tal:attributes="action request/URL; | ||
1083 | 154 | id row/delete_packaging_form_id"> | ||
1084 | 155 | <tal:hidden replace="structure row/hidden_packaging_field" /> | ||
1085 | 156 | <tal:action replace="structure view/renderDeletePackagingAction" /> | ||
1086 | 157 | </form> | ||
1087 | 158 | <a tal:attributes=" | ||
1088 | 159 | href row/series_package/menu:overview/edit_packaging/url; | ||
1089 | 160 | title string:Edit upsteam link"> | ||
1090 | 161 | <img src="/@@/edit"/> | ||
1091 | 162 | </a> | ||
1094 | 163 | </tal:has_packaging> | 137 | </tal:has_packaging> |
1095 | 164 | </div><!--float right--> | 138 | </div><!--float right--> |
1096 | 165 | </td> | 139 | </td> |
1097 | 166 | 140 | ||
1098 | === modified file 'lib/lp/registry/templates/distroseries-packaging.pt' | |||
1099 | --- lib/lp/registry/templates/distroseries-packaging.pt 2010-02-16 19:07:42 +0000 | |||
1100 | +++ lib/lp/registry/templates/distroseries-packaging.pt 2010-03-06 06:27:33 +0000 | |||
1101 | @@ -18,7 +18,7 @@ | |||
1102 | 18 | <p> | 18 | <p> |
1103 | 19 | The packages are listed by priority based on the greatest need to | 19 | The packages are listed by priority based on the greatest need to |
1104 | 20 | forward bugs, sync translations, or specify the latest | 20 | forward bugs, sync translations, or specify the latest |
1106 | 21 | development branch. | 21 | development branch. |
1107 | 22 | </p> | 22 | </p> |
1108 | 23 | 23 | ||
1109 | 24 | <ul id="related-pages" class="horizontal"> | 24 | <ul id="related-pages" class="horizontal"> |
1110 | @@ -72,42 +72,7 @@ | |||
1111 | 72 | tal:condition="product/summary" | 72 | tal:condition="product/summary" |
1112 | 73 | tal:content="product/summary"/> | 73 | tal:content="product/summary"/> |
1113 | 74 | </td> | 74 | </td> |
1150 | 75 | 75 | <td tal:content="structure package/@@+upstream-connections"/> | |
1115 | 76 | <td> | ||
1116 | 77 | <dl> | ||
1117 | 78 | <dt> | ||
1118 | 79 | <a tal:replace="structure product/fmt:link" /> project: | ||
1119 | 80 | </dt> | ||
1120 | 81 | <dd title="Project bug supervisor"> | ||
1121 | 82 | Bug supervisor: | ||
1122 | 83 | <tal:yes-no | ||
1123 | 84 | replace="structure product/bug_supervisor/image:boolean" /> | ||
1124 | 85 | </dd> | ||
1125 | 86 | <dd title="Project bug tracker" | ||
1126 | 87 | tal:define="bool product/project|bugtracker|product/bugtracker|product/official_malone"> | ||
1127 | 88 | Bug tracker: | ||
1128 | 89 | <tal:yes-no replace="structure bool/image:boolean"/> | ||
1129 | 90 | </dd> | ||
1130 | 91 | </dl> | ||
1131 | 92 | </td> | ||
1132 | 93 | |||
1133 | 94 | <td> | ||
1134 | 95 | <dl> | ||
1135 | 96 | <dt style="margin-bottom: 6px;"> | ||
1136 | 97 | <a tal:replace="structure series/fmt:link" />: | ||
1137 | 98 | </dt> | ||
1138 | 99 | <dd title="Series branch"> | ||
1139 | 100 | Branch: | ||
1140 | 101 | <tal:yes-no replace="structure series/branch/image:boolean"/> | ||
1141 | 102 | </dd> | ||
1142 | 103 | <dd title="Series translations auto import" | ||
1143 | 104 | tal:condition="translations" | ||
1144 | 105 | tal:define="bool not:series/translations_autoimport_mode/enumvalue:NO_IMPORT"> | ||
1145 | 106 | Translations: | ||
1146 | 107 | <tal:yes-no replace="structure bool/image:boolean"/> | ||
1147 | 108 | </dd> | ||
1148 | 109 | </dl> | ||
1149 | 110 | </td> | ||
1151 | 111 | </tr> | 76 | </tr> |
1152 | 112 | </tal:packaging> | 77 | </tal:packaging> |
1153 | 113 | </tbody> | 78 | </tbody> |
1154 | 114 | 79 | ||
1155 | === modified file 'lib/lp/registry/templates/product-packages.pt' | |||
1156 | --- lib/lp/registry/templates/product-packages.pt 2010-01-11 20:58:42 +0000 | |||
1157 | +++ lib/lp/registry/templates/product-packages.pt 2010-03-06 06:27:33 +0000 | |||
1158 | @@ -40,16 +40,11 @@ | |||
1159 | 40 | <th>Distribution series</th> | 40 | <th>Distribution series</th> |
1160 | 41 | <th>Source package</th> | 41 | <th>Source package</th> |
1161 | 42 | <th>Version</th> | 42 | <th>Version</th> |
1164 | 43 | <th style="width: 1em;" | 43 | <th> </th> |
1163 | 44 | tal:condition="view/can_delete_packaging"> </th> | ||
1165 | 45 | </tr> | 44 | </tr> |
1166 | 46 | </thead> | 45 | </thead> |
1167 | 47 | <tbody> | 46 | <tbody> |
1173 | 48 | <tr tal:repeat="packaging_dict packagings"> | 47 | <tr tal:repeat="packaging packagings"> |
1169 | 49 | <tal:packaging_field | ||
1170 | 50 | define="packaging packaging_dict/packaging; | ||
1171 | 51 | form_id packaging_dict/form_id; | ||
1172 | 52 | field packaging_dict/field"> | ||
1174 | 53 | <td> | 48 | <td> |
1175 | 54 | <a tal:replace="structure packaging/distroseries/distribution/fmt:link" /> | 49 | <a tal:replace="structure packaging/distroseries/distribution/fmt:link" /> |
1176 | 55 | </td> | 50 | </td> |
1177 | @@ -69,17 +64,11 @@ | |||
1178 | 69 | <tal:currentrelease | 64 | <tal:currentrelease |
1179 | 70 | replace="packaging/sourcepackage/currentrelease/version|nothing"> | 65 | replace="packaging/sourcepackage/currentrelease/version|nothing"> |
1180 | 71 | 2.3.4-1 | 66 | 2.3.4-1 |
1192 | 72 | </tal:currentrelease> | 67 | </tal:currentrelease> |
1193 | 73 | </td> | 68 | </td> |
1194 | 74 | <td tal:condition="view/can_delete_packaging"> | 69 | <td> |
1195 | 75 | <form style="display: inline" method="post" | 70 | <a tal:replace="structure packaging/sourcepackage/menu:overview/remove_packaging/fmt:icon" /> |
1196 | 76 | tal:attributes="action request/URL; | 71 | </td> |
1186 | 77 | id form_id"> | ||
1187 | 78 | <tal:hidden replace="structure field" /> | ||
1188 | 79 | <tal:action replace="structure view/renderDeletePackagingAction" /> | ||
1189 | 80 | </form> | ||
1190 | 81 | </td> | ||
1191 | 82 | </tal:packaging_field> | ||
1197 | 83 | </tr> | 72 | </tr> |
1198 | 84 | </tbody> | 73 | </tbody> |
1199 | 85 | </table> | 74 | </table> |
1200 | @@ -99,7 +88,7 @@ | |||
1201 | 99 | <h2>Packages by distribution</h2> | 88 | <h2>Packages by distribution</h2> |
1202 | 100 | 89 | ||
1203 | 101 | <tal:distribution repeat="distro view/distro_packaging"> | 90 | <tal:distribution repeat="distro view/distro_packaging"> |
1205 | 102 | 91 | ||
1206 | 103 | <h3> | 92 | <h3> |
1207 | 104 | <a tal:attributes="href distro/distribution/fmt:url" | 93 | <a tal:attributes="href distro/distribution/fmt:url" |
1208 | 105 | tal:content="distro/distribution/title">Ubuntu Linux</a> | 94 | tal:content="distro/distribution/title">Ubuntu Linux</a> |
1209 | 106 | 95 | ||
1210 | === modified file 'lib/lp/registry/templates/sourcepackage-portlet-associations.pt' | |||
1211 | --- lib/lp/registry/templates/sourcepackage-portlet-associations.pt 2010-02-16 19:13:31 +0000 | |||
1212 | +++ lib/lp/registry/templates/sourcepackage-portlet-associations.pt 2010-03-06 06:27:33 +0000 | |||
1213 | @@ -10,47 +10,7 @@ | |||
1214 | 10 | <div class="portletBody portletContent" | 10 | <div class="portletBody portletContent" |
1215 | 11 | tal:define="series context/productseries"> | 11 | tal:define="series context/productseries"> |
1216 | 12 | <tal:has_series condition="series"> | 12 | <tal:has_series condition="series"> |
1258 | 13 | <div id="upstreams" class="two-column-list"> | 13 | <div tal:content="structure context/@@+upstream-connections"/> |
1218 | 14 | <dl> | ||
1219 | 15 | <dt> | ||
1220 | 16 | <a tal:replace="structure series/product/fmt:link" /> project | ||
1221 | 17 | </dt> | ||
1222 | 18 | |||
1223 | 19 | <tal:has_pg define="project series/product/project" | ||
1224 | 20 | condition="project"> | ||
1225 | 21 | <dd title="Project group"> | ||
1226 | 22 | Project Group: | ||
1227 | 23 | <a tal:replace="structure project/fmt:link" /> | ||
1228 | 24 | </dd> | ||
1229 | 25 | </tal:has_pg> | ||
1230 | 26 | |||
1231 | 27 | <dd title="Bug supervisor"> | ||
1232 | 28 | Bug supervisor: | ||
1233 | 29 | <tal:yes-no replace="structure series/product/bug_supervisor/image:boolean"/> | ||
1234 | 30 | </dd> | ||
1235 | 31 | |||
1236 | 32 | <dd title="Bug tracker"> | ||
1237 | 33 | Bug tracker: | ||
1238 | 34 | <tal:yes-no replace="structure view/has_bugtracker/image:boolean"/> | ||
1239 | 35 | </dd> | ||
1240 | 36 | </dl> | ||
1241 | 37 | <dl> | ||
1242 | 38 | <dt> | ||
1243 | 39 | <a tal:replace="structure series/fmt:link" /> | ||
1244 | 40 | </dt> | ||
1245 | 41 | <dd title="Series branch"> | ||
1246 | 42 | Branch: | ||
1247 | 43 | <tal:yes-no replace="structure series/branch/image:boolean"/> | ||
1248 | 44 | </dd> | ||
1249 | 45 | <dd title="Series translations auto import" | ||
1250 | 46 | tal:condition="context/getTranslationTemplates" | ||
1251 | 47 | tal:define="bool not:series/translations_autoimport_mode/enumvalue:NO_IMPORT"> | ||
1252 | 48 | Translations: | ||
1253 | 49 | <tal:yes-no replace="structure bool/image:boolean"/> | ||
1254 | 50 | </dd> | ||
1255 | 51 | </dl> | ||
1256 | 52 | |||
1257 | 53 | </div> | ||
1259 | 54 | 14 | ||
1260 | 55 | <ul class="horizontal"> | 15 | <ul class="horizontal"> |
1261 | 56 | <li> | 16 | <li> |
1262 | @@ -58,12 +18,6 @@ | |||
1263 | 58 | tal:attributes="href series/product/menu:overview/packages/fmt:url" | 18 | tal:attributes="href series/product/menu:overview/packages/fmt:url" |
1264 | 59 | >Show upstream links</a> | 19 | >Show upstream links</a> |
1265 | 60 | </li> | 20 | </li> |
1266 | 61 | <li> | ||
1267 | 62 | <a class="sprite edit" | ||
1268 | 63 | tal:attributes=" | ||
1269 | 64 | href context/menu:overview/edit_packaging/fmt:url" | ||
1270 | 65 | >Change upstream project and series</a> | ||
1271 | 66 | </li> | ||
1272 | 67 | </ul> | 21 | </ul> |
1273 | 68 | </tal:has_series> | 22 | </tal:has_series> |
1274 | 69 | 23 | ||
1275 | 70 | 24 | ||
1276 | === added file 'lib/lp/registry/templates/sourcepackage-remove-packaging.pt' | |||
1277 | --- lib/lp/registry/templates/sourcepackage-remove-packaging.pt 1970-01-01 00:00:00 +0000 | |||
1278 | +++ lib/lp/registry/templates/sourcepackage-remove-packaging.pt 2010-03-06 06:27:33 +0000 | |||
1279 | @@ -0,0 +1,34 @@ | |||
1280 | 1 | <html | ||
1281 | 2 | xmlns="http://www.w3.org/1999/xhtml" | ||
1282 | 3 | xmlns:tal="http://xml.zope.org/namespaces/tal" | ||
1283 | 4 | xmlns:metal="http://xml.zope.org/namespaces/metal" | ||
1284 | 5 | metal:use-macro="view/macro:page/main_only" | ||
1285 | 6 | > | ||
1286 | 7 | |||
1287 | 8 | <body> | ||
1288 | 9 | |||
1289 | 10 | <div metal:fill-slot="main"> | ||
1290 | 11 | |||
1291 | 12 | <div tal:condition="not: context/productseries" | ||
1292 | 13 | class="error"> | ||
1293 | 14 | This upstream association was deleted already. | ||
1294 | 15 | </div> | ||
1295 | 16 | <div tal:condition="context/productseries"> | ||
1296 | 17 | <div metal:use-macro="context/@@launchpad_form/form"> | ||
1297 | 18 | <div metal:fill-slot="extra_info"> | ||
1298 | 19 | <p> | ||
1299 | 20 | Do you want to remove the upstream link to | ||
1300 | 21 | <a tal:replace="structure context/productseries/fmt:link"/>? | ||
1301 | 22 | </p> | ||
1302 | 23 | <p> | ||
1303 | 24 | Links from distribution packages to upstream project series let | ||
1304 | 25 | distribution and upstream maintainers share bugs, patches, and | ||
1305 | 26 | translations efficiently. | ||
1306 | 27 | </p> | ||
1307 | 28 | </div> | ||
1308 | 29 | </div> | ||
1309 | 30 | </div> | ||
1310 | 31 | |||
1311 | 32 | </div> | ||
1312 | 33 | </body> | ||
1313 | 34 | </html> | ||
1314 | 0 | 35 | ||
1315 | === added file 'lib/lp/registry/templates/sourcepackage-upstream-connections.pt' | |||
1316 | --- lib/lp/registry/templates/sourcepackage-upstream-connections.pt 1970-01-01 00:00:00 +0000 | |||
1317 | +++ lib/lp/registry/templates/sourcepackage-upstream-connections.pt 2010-03-06 06:27:33 +0000 | |||
1318 | @@ -0,0 +1,63 @@ | |||
1319 | 1 | <tal:root | ||
1320 | 2 | xmlns:tal="http://xml.zope.org/namespaces/tal" | ||
1321 | 3 | xmlns:metal="http://xml.zope.org/namespaces/metal" | ||
1322 | 4 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" | ||
1323 | 5 | omit-tag=""> | ||
1324 | 6 | |||
1325 | 7 | <tal:comment condition="nothing"> | ||
1326 | 8 | view.request.annotations['show_edit_buttons'] can be set in views | ||
1327 | 9 | that include this page to display the edit and remove buttons. | ||
1328 | 10 | </tal:comment> | ||
1329 | 11 | <div id="upstreams" tal:define="series context/productseries"> | ||
1330 | 12 | <dl> | ||
1331 | 13 | <dd> | ||
1332 | 14 | <tal:has_pg condition="series/product/project"> | ||
1333 | 15 | <a tal:replace="structure series/product/project/fmt:link" /> ⇒ | ||
1334 | 16 | </tal:has_pg> | ||
1335 | 17 | <a tal:replace="structure series/product/fmt:link" /> ⇒ | ||
1336 | 18 | <a tal:content="series/name" | ||
1337 | 19 | tal:attributes="href series/fmt:url" /> | ||
1338 | 20 | <span tal:condition="request/annotations/show_edit_buttons | nothing"> | ||
1339 | 21 | <a tal:replace=" | ||
1340 | 22 | structure context/menu:overview/edit_packaging/fmt:icon" /> | ||
1341 | 23 | <a tal:replace=" | ||
1342 | 24 | structure context/menu:overview/remove_packaging/fmt:icon " /> | ||
1343 | 25 | </span> | ||
1344 | 26 | </dd> | ||
1345 | 27 | </dl> | ||
1346 | 28 | |||
1347 | 29 | <style> | ||
1348 | 30 | #upstream-fields dd { | ||
1349 | 31 | margin: 0; | ||
1350 | 32 | padding: 0; | ||
1351 | 33 | } | ||
1352 | 34 | </style> | ||
1353 | 35 | <div id="upstream-fields" class="two-column-list"> | ||
1354 | 36 | <dl> | ||
1355 | 37 | <dd title="Bug supervisor"> | ||
1356 | 38 | Bug supervisor: | ||
1357 | 39 | <tal:yes-no replace="structure series/product/bug_supervisor/image:boolean"/> | ||
1358 | 40 | </dd> | ||
1359 | 41 | |||
1360 | 42 | <dd title="Bug tracker"> | ||
1361 | 43 | Bug tracker: | ||
1362 | 44 | <tal:yes-no replace="structure view/has_bugtracker/image:boolean"/> | ||
1363 | 45 | </dd> | ||
1364 | 46 | </dl> | ||
1365 | 47 | <dl> | ||
1366 | 48 | <dd title="Series branch"> | ||
1367 | 49 | Branch: | ||
1368 | 50 | <tal:yes-no replace="structure series/branch/image:boolean"/> | ||
1369 | 51 | </dd> | ||
1370 | 52 | <dd title="Series translations auto import" | ||
1371 | 53 | tal:condition="context/getTranslationTemplates" | ||
1372 | 54 | tal:define="bool not:series/translations_autoimport_mode/enumvalue:NO_IMPORT"> | ||
1373 | 55 | Translations: | ||
1374 | 56 | <tal:yes-no replace="structure bool/image:boolean"/> | ||
1375 | 57 | </dd> | ||
1376 | 58 | </dl> | ||
1377 | 59 | |||
1378 | 60 | </div> | ||
1379 | 61 | </div> | ||
1380 | 62 | |||
1381 | 63 | </tal:root> | ||
1382 | 0 | 64 | ||
1383 | === modified file 'lib/lp/soyuz/stories/soyuz/xx-distroseries-sources.txt' | |||
1384 | --- lib/lp/soyuz/stories/soyuz/xx-distroseries-sources.txt 2010-02-15 10:40:56 +0000 | |||
1385 | +++ lib/lp/soyuz/stories/soyuz/xx-distroseries-sources.txt 2010-03-06 06:27:33 +0000 | |||
1386 | @@ -72,11 +72,9 @@ | |||
1387 | 72 | Product, Branches, and Bugs: | 72 | Product, Branches, and Bugs: |
1388 | 73 | 73 | ||
1389 | 74 | >>> print extract_text(find_tag_by_id(browser.contents, 'upstreams')) | 74 | >>> print extract_text(find_tag_by_id(browser.contents, 'upstreams')) |
1392 | 75 | Mozilla Firefox ... project | 75 | the Mozilla Project...Mozilla Firefox...trunk... |
1391 | 76 | Project Group: the Mozilla Project | ||
1393 | 77 | Bug supervisor: no | 76 | Bug supervisor: no |
1394 | 78 | Bug tracker: yes | 77 | Bug tracker: yes |
1395 | 79 | Mozilla Firefox trunk series | ||
1396 | 80 | Branch: no | 78 | Branch: no |
1397 | 81 | 79 | ||
1398 | 82 | The user can also download the files for the "currentrelease" (last | 80 | The user can also download the files for the "currentrelease" (last |
Summary
-------
The sourcepackage index page had an edit button but no way to remove
a link to the upstream via the project series.
The $distroseries/ +packaging page also displayed identical info,
so I moved that into a template that could be shared.
Implementation details ------- ------- -
-------
Moved identical formatting of upstream connection info from packaging. pt and sourcepackage- portlet- associations. pt upstream- connections. pt. Added the (-) removal link project/ series info. lp/registry/ browser/ configure. zcml lp/registry/ templates/ distroseries- packaging. pt lp/registry/ templates/ sourcepackage- portlet- associations. pt lp/registry/ templates/ sourcepackage- upstream- connections. pt
distroseries-
into sourcepackage-
and moved the edit link next to the projectgroup/
lib/
lib/
lib/
lib/
Added $sourcepackage/ +remove- packaging and $sourcepackage/ upstream- connections. lp/registry/ browser/ sourcepackage. py lp/registry/ browser/ tests/sourcepac kage-views. txt lp/registry/ stories/ distroseries/ xx-show- distroseries- packaging. txt lp/registry/ templates/ sourcepackage- remove- packaging. pt
lib/
lib/
lib/
lib/
Drive-by improvement of formatting. lp/registry/ model/productse ries.py lp/registry/ model/sourcepac kage.py
lib/
lib/
Tests
-----
./bin/test -vv -t 'sourcepackage- views.txt| xx-show- distroseries- packaging. txt'
Demo and Q/A
------------
* Open https:/ /launchpad. dev/ubuntu/ hoary/+ source/ evolution /launchpad. dev/ubuntu/ hoary/+ packaging project/ series like so:
* If there is a "Link to Upstream Project" button, use that
since the removal button won't show up without an existing link.
* The Upstream Connections portlet should show:
GNOME ⇒ Evolution ⇒ trunk (E) (-)
where (E) is the edit button, and (-) is the remove button.
* Click on the (-) button.
* Click on the Unlink button.
* The Upstream Connections portlet should now show the
"Link to Upstream Project" button again.
* Open https:/
* The table should now show the projectgroup/
GNOME ⇒ Evolution ⇒ trunk (E) (-)