Merge lp:~cjwatson/launchpad/singleton-listing-no-redirect into lp:launchpad
- singleton-listing-no-redirect
- Merge into devel
Proposed by
Colin Watson
Status: | Merged |
---|---|
Merged at revision: | 17802 |
Proposed branch: | lp:~cjwatson/launchpad/singleton-listing-no-redirect |
Merge into: | lp:launchpad |
Diff against target: |
476 lines (+173/-88) 11 files modified
lib/lp/code/browser/branch.py (+12/-4) lib/lp/code/browser/sourcepackagerecipelisting.py (+0/-8) lib/lp/code/browser/tests/test_branch.py (+26/-0) lib/lp/code/browser/tests/test_sourcepackagerecipelisting.py (+2/-6) lib/lp/code/templates/branch-recipes.pt (+1/-9) lib/lp/registry/browser/person.py (+2/-6) lib/lp/snappy/browser/hassnaps.py (+29/-11) lib/lp/snappy/browser/snaplisting.py (+1/-7) lib/lp/snappy/browser/tests/test_hassnaps.py (+86/-0) lib/lp/snappy/browser/tests/test_snaplisting.py (+13/-30) lib/lp/snappy/templates/snap-macros.pt (+1/-7) |
To merge this branch: | bzr merge lp:~cjwatson/launchpad/singleton-listing-no-redirect |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+273405@code.launchpad.net |
Commit message
Link directly to the recipe/snap in the one-recipe/snap case, rather than redirecting from +recipes/+snaps listing views.
Description of the change
Link directly to the recipe/snap in the one-recipe/snap case, rather than redirecting from +recipes/+snaps listing views. Listing views should show listings even if they have only one item.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/code/browser/branch.py' |
2 | --- lib/lp/code/browser/branch.py 2015-09-29 18:02:29 +0000 |
3 | +++ lib/lp/code/browser/branch.py 2015-10-05 13:41:26 +0000 |
4 | @@ -523,14 +523,22 @@ |
5 | if check_permission('launchpad.View', proposal)] |
6 | |
7 | @property |
8 | - def recipe_count_text(self): |
9 | + def recipes_link(self): |
10 | + """A link to recipes for this branch.""" |
11 | count = self.context.recipes.count() |
12 | if count == 0: |
13 | - return 'No recipes' |
14 | + # Nothing to link to. |
15 | + return 'No recipes using this branch.' |
16 | elif count == 1: |
17 | - return '1 recipe' |
18 | + # Link to the single recipe. |
19 | + return structured( |
20 | + '<a href="%s">1 recipe</a> using this branch.', |
21 | + canonical_url(self.context.recipes.one())).escapedtext |
22 | else: |
23 | - return '%s recipes' % count |
24 | + # Link to a recipe listing. |
25 | + return structured( |
26 | + '<a href="+recipes">%s recipes</a> using this branch.', |
27 | + count).escapedtext |
28 | |
29 | @property |
30 | def is_import_branch_with_no_landing_candidates(self): |
31 | |
32 | === modified file 'lib/lp/code/browser/sourcepackagerecipelisting.py' |
33 | --- lib/lp/code/browser/sourcepackagerecipelisting.py 2015-02-24 13:46:46 +0000 |
34 | +++ lib/lp/code/browser/sourcepackagerecipelisting.py 2015-10-05 13:41:26 +0000 |
35 | @@ -16,7 +16,6 @@ |
36 | from lp.code.browser.decorations import DecoratedBranch |
37 | from lp.services.feeds.browser import FeedsMixin |
38 | from lp.services.webapp import ( |
39 | - canonical_url, |
40 | LaunchpadView, |
41 | Link, |
42 | ) |
43 | @@ -46,13 +45,6 @@ |
44 | return 'Source Package Recipes for %(displayname)s' % { |
45 | 'displayname': self.context.displayname} |
46 | |
47 | - def initialize(self): |
48 | - super(RecipeListingView, self).initialize() |
49 | - recipes = self.context.recipes |
50 | - if recipes.count() == 1: |
51 | - recipe = recipes.one() |
52 | - self.request.response.redirect(canonical_url(recipe)) |
53 | - |
54 | |
55 | class BranchRecipeListingView(RecipeListingView): |
56 | |
57 | |
58 | === modified file 'lib/lp/code/browser/tests/test_branch.py' |
59 | --- lib/lp/code/browser/tests/test_branch.py 2015-09-18 10:15:54 +0000 |
60 | +++ lib/lp/code/browser/tests/test_branch.py 2015-10-05 13:41:26 +0000 |
61 | @@ -266,6 +266,32 @@ |
62 | login_person(branch.owner) |
63 | self.assertFalse(view.user_can_upload) |
64 | |
65 | + def test_recipes_link_no_recipes(self): |
66 | + # A branch with no recipes does not show a recipes link. |
67 | + branch = self.factory.makeAnyBranch() |
68 | + view = create_initialized_view(branch, '+index') |
69 | + self.assertEqual('No recipes using this branch.', view.recipes_link) |
70 | + |
71 | + def test_recipes_link_one_recipe(self): |
72 | + # A branch with one recipe shows a link to that recipe. |
73 | + branch = self.factory.makeAnyBranch() |
74 | + recipe = self.factory.makeSourcePackageRecipe(branches=[branch]) |
75 | + view = create_initialized_view(branch, '+index') |
76 | + expected_link = ( |
77 | + '<a href="%s">1 recipe</a> using this branch.' % |
78 | + canonical_url(recipe)) |
79 | + self.assertEqual(expected_link, view.recipes_link) |
80 | + |
81 | + def test_recipes_link_more_recipes(self): |
82 | + # A branch with more than one recipe shows a link to a listing. |
83 | + branch = self.factory.makeAnyBranch() |
84 | + self.factory.makeSourcePackageRecipe(branches=[branch]) |
85 | + self.factory.makeSourcePackageRecipe(branches=[branch]) |
86 | + view = create_initialized_view(branch, '+index') |
87 | + self.assertEqual( |
88 | + '<a href="+recipes">2 recipes</a> using this branch.', |
89 | + view.recipes_link) |
90 | + |
91 | def _addBugLinks(self, branch): |
92 | for status in BugTaskStatus.items: |
93 | bug = self.factory.makeBug(status=status) |
94 | |
95 | === modified file 'lib/lp/code/browser/tests/test_sourcepackagerecipelisting.py' |
96 | --- lib/lp/code/browser/tests/test_sourcepackagerecipelisting.py 2015-02-24 13:46:46 +0000 |
97 | +++ lib/lp/code/browser/tests/test_sourcepackagerecipelisting.py 2015-10-05 13:41:26 +0000 |
98 | @@ -22,11 +22,9 @@ |
99 | layer = DatabaseFunctionalLayer |
100 | |
101 | def test_project_branch_recipe_listing(self): |
102 | - # We can see recipes for the project. We need to create two, since |
103 | - # only one will redirect to that recipe. |
104 | + # We can see recipes for the project. |
105 | branch = self.factory.makeProductBranch() |
106 | recipe = self.factory.makeSourcePackageRecipe(branches=[branch]) |
107 | - self.factory.makeSourcePackageRecipe(branches=[branch]) |
108 | text = self.getMainText(recipe.base_branch, '+recipes') |
109 | self.assertTextMatchesExpressionIgnoreWhitespace(""" |
110 | Source Package Recipes for lp:.* |
111 | @@ -34,11 +32,9 @@ |
112 | spr-name.* Person-name""", text) |
113 | |
114 | def test_package_branch_recipe_listing(self): |
115 | - # We can see recipes for the package. We need to create two, since |
116 | - # only one will redirect to that recipe. |
117 | + # We can see recipes for the package. |
118 | branch = self.factory.makePackageBranch() |
119 | recipe = self.factory.makeSourcePackageRecipe(branches=[branch]) |
120 | - self.factory.makeSourcePackageRecipe(branches=[branch]) |
121 | text = self.getMainText(recipe.base_branch, '+recipes') |
122 | self.assertTextMatchesExpressionIgnoreWhitespace(""" |
123 | Source Package Recipes for lp:.* |
124 | |
125 | === modified file 'lib/lp/code/templates/branch-recipes.pt' |
126 | --- lib/lp/code/templates/branch-recipes.pt 2012-06-15 16:23:50 +0000 |
127 | +++ lib/lp/code/templates/branch-recipes.pt 2015-10-05 13:41:26 +0000 |
128 | @@ -10,15 +10,7 @@ |
129 | <div id="recipe-links" class="actions"> |
130 | <div id="recipe-summary"> |
131 | <img src="/@@/source-package-recipe" /> |
132 | - <tal:no-recipes condition="not: view/context/recipes/count"> |
133 | - No recipes |
134 | - </tal:no-recipes> |
135 | - <tal:recipes condition="view/context/recipes/count"> |
136 | - <a href="+recipes" tal:content="structure view/recipe_count_text"> |
137 | - 1 branch |
138 | - </a> |
139 | - </tal:recipes> |
140 | - using this branch. |
141 | + <tal:recipes replace="structure view/recipes_link" /> |
142 | |
143 | <a href="/+help-code/related-recipes.html" target="help" |
144 | class="sprite maybe action-icon">(?)</a> |
145 | |
146 | === modified file 'lib/lp/registry/browser/person.py' |
147 | --- lib/lp/registry/browser/person.py 2015-10-01 10:25:19 +0000 |
148 | +++ lib/lp/registry/browser/person.py 2015-10-05 13:41:26 +0000 |
149 | @@ -274,10 +274,7 @@ |
150 | from lp.services.webapp.publisher import LaunchpadView |
151 | from lp.services.worlddata.interfaces.country import ICountry |
152 | from lp.services.worlddata.interfaces.language import ILanguageSet |
153 | -from lp.snappy.browser.hassnaps import ( |
154 | - HasSnapsMenuMixin, |
155 | - HasSnapsViewMixin, |
156 | - ) |
157 | +from lp.snappy.browser.hassnaps import HasSnapsMenuMixin |
158 | from lp.snappy.interfaces.snap import ISnapSet |
159 | from lp.soyuz.browser.archivesubscription import ( |
160 | traverse_archive_subscription_for_subscriber, |
161 | @@ -1653,8 +1650,7 @@ |
162 | raise AssertionError('Unknown group to contact.') |
163 | |
164 | |
165 | -class PersonView(LaunchpadView, FeedsMixin, ContactViaWebLinksMixin, |
166 | - HasSnapsViewMixin): |
167 | +class PersonView(LaunchpadView, FeedsMixin, ContactViaWebLinksMixin): |
168 | """A View class used in almost all Person's pages.""" |
169 | |
170 | @property |
171 | |
172 | === modified file 'lib/lp/snappy/browser/hassnaps.py' |
173 | --- lib/lp/snappy/browser/hassnaps.py 2015-09-18 10:38:27 +0000 |
174 | +++ lib/lp/snappy/browser/hassnaps.py 2015-10-05 13:41:26 +0000 |
175 | @@ -12,9 +12,13 @@ |
176 | from zope.component import getUtility |
177 | |
178 | from lp.code.browser.decorations import DecoratedBranch |
179 | +from lp.code.interfaces.gitrepository import IGitRepository |
180 | from lp.services.features import getFeatureFlag |
181 | -from lp.services.propertycache import cachedproperty |
182 | -from lp.services.webapp import Link |
183 | +from lp.services.webapp import ( |
184 | + canonical_url, |
185 | + Link, |
186 | + ) |
187 | +from lp.services.webapp.escaping import structured |
188 | from lp.snappy.interfaces.snap import ( |
189 | ISnapSet, |
190 | SNAP_FEATURE_FLAG, |
191 | @@ -45,24 +49,38 @@ |
192 | class HasSnapsViewMixin: |
193 | """A view mixin for objects that implement IHasSnaps.""" |
194 | |
195 | - @cachedproperty |
196 | - def snap_count(self): |
197 | + @property |
198 | + def snaps(self): |
199 | context = self.context |
200 | if isinstance(context, DecoratedBranch): |
201 | context = context.branch |
202 | return getUtility(ISnapSet).findByContext( |
203 | - context, visible_by_user=self.user).count() |
204 | + context, visible_by_user=self.user) |
205 | |
206 | @property |
207 | def show_snap_information(self): |
208 | - return bool(getFeatureFlag(SNAP_FEATURE_FLAG)) or self.snap_count != 0 |
209 | + return ( |
210 | + bool(getFeatureFlag(SNAP_FEATURE_FLAG)) or |
211 | + not self.snaps.is_empty()) |
212 | |
213 | @property |
214 | - def snap_count_text(self): |
215 | - count = self.snap_count |
216 | + def snaps_link(self): |
217 | + """A link to snap packages for this object.""" |
218 | + count = self.snaps.count() |
219 | + if IGitRepository.providedBy(self.context): |
220 | + context_type = 'repository' |
221 | + else: |
222 | + context_type = 'branch' |
223 | if count == 0: |
224 | - return 'No snap packages' |
225 | + # Nothing to link to. |
226 | + return 'No snap packages using this %s.' % context_type |
227 | elif count == 1: |
228 | - return '1 snap package' |
229 | + # Link to the single snap package. |
230 | + return structured( |
231 | + '<a href="%s">1 snap package</a> using this %s.', |
232 | + canonical_url(self.snaps.one()), context_type).escapedtext |
233 | else: |
234 | - return '%s snap packages' % count |
235 | + # Link to a snap package listing. |
236 | + return structured( |
237 | + '<a href="+snaps">%s snap packages</a> using this %s.', |
238 | + count, context_type).escapedtext |
239 | |
240 | === modified file 'lib/lp/snappy/browser/snaplisting.py' |
241 | --- lib/lp/snappy/browser/snaplisting.py 2015-09-17 08:52:02 +0000 |
242 | +++ lib/lp/snappy/browser/snaplisting.py 2015-10-05 13:41:26 +0000 |
243 | @@ -18,10 +18,7 @@ |
244 | from lp.code.browser.decorations import DecoratedBranch |
245 | from lp.services.database.decoratedresultset import DecoratedResultSet |
246 | from lp.services.feeds.browser import FeedsMixin |
247 | -from lp.services.webapp import ( |
248 | - canonical_url, |
249 | - LaunchpadView, |
250 | - ) |
251 | +from lp.services.webapp import LaunchpadView |
252 | from lp.snappy.interfaces.snap import ISnapSet |
253 | |
254 | |
255 | @@ -48,9 +45,6 @@ |
256 | loader = partial( |
257 | getUtility(ISnapSet).preloadDataForSnaps, user=self.user) |
258 | self.snaps = DecoratedResultSet(snaps, pre_iter_hook=loader) |
259 | - if self.snaps.count() == 1: |
260 | - snap = self.snaps.one() |
261 | - self.request.response.redirect(canonical_url(snap)) |
262 | |
263 | |
264 | class BranchSnapListingView(SnapListingView): |
265 | |
266 | === added file 'lib/lp/snappy/browser/tests/test_hassnaps.py' |
267 | --- lib/lp/snappy/browser/tests/test_hassnaps.py 1970-01-01 00:00:00 +0000 |
268 | +++ lib/lp/snappy/browser/tests/test_hassnaps.py 2015-10-05 13:41:26 +0000 |
269 | @@ -0,0 +1,86 @@ |
270 | +# Copyright 2015 Canonical Ltd. This software is licensed under the |
271 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
272 | + |
273 | +"""Test views for objects that have snap packages.""" |
274 | + |
275 | +__metaclass__ = type |
276 | + |
277 | +from lp.services.features.testing import FeatureFixture |
278 | +from lp.services.webapp import canonical_url |
279 | +from lp.snappy.interfaces.snap import SNAP_FEATURE_FLAG |
280 | +from lp.testing import TestCaseWithFactory |
281 | +from lp.testing.layers import DatabaseFunctionalLayer |
282 | +from lp.testing.views import create_initialized_view |
283 | + |
284 | + |
285 | +class TestRelatedSnapsMixin: |
286 | + |
287 | + layer = DatabaseFunctionalLayer |
288 | + |
289 | + def setUp(self): |
290 | + super(TestRelatedSnapsMixin, self).setUp() |
291 | + self.useFixture(FeatureFixture({SNAP_FEATURE_FLAG: u"on"})) |
292 | + |
293 | + def test_snaps_link_no_snaps(self): |
294 | + # An object with no snap packages does not show a snap packages link. |
295 | + context = self.makeContext() |
296 | + view = create_initialized_view(context, "+index") |
297 | + self.assertEqual( |
298 | + "No snap packages using this %s." % self.context_type, |
299 | + view.snaps_link) |
300 | + |
301 | + def test_snaps_link_one_snap(self): |
302 | + # An object with one snap package shows a link to that snap package. |
303 | + context = self.makeContext() |
304 | + snap = self.makeSnap(context) |
305 | + view = create_initialized_view(context, "+index") |
306 | + expected_link = ( |
307 | + '<a href="%s">1 snap package</a> using this %s.' % |
308 | + (canonical_url(snap), self.context_type)) |
309 | + self.assertEqual(expected_link, view.snaps_link) |
310 | + |
311 | + def test_snaps_link_more_snaps(self): |
312 | + # An object with more than one snap package shows a link to a listing. |
313 | + context = self.makeContext() |
314 | + self.makeSnap(context) |
315 | + self.makeSnap(context) |
316 | + view = create_initialized_view(context, "+index") |
317 | + expected_link = ( |
318 | + '<a href="+snaps">2 snap packages</a> using this %s.' % |
319 | + self.context_type) |
320 | + self.assertEqual(expected_link, view.snaps_link) |
321 | + |
322 | + |
323 | +class TestRelatedSnapsBranch(TestRelatedSnapsMixin, TestCaseWithFactory): |
324 | + |
325 | + context_type = "branch" |
326 | + |
327 | + def makeContext(self): |
328 | + return self.factory.makeAnyBranch() |
329 | + |
330 | + def makeSnap(self, context): |
331 | + return self.factory.makeSnap(branch=context) |
332 | + |
333 | + |
334 | +class TestRelatedSnapsGitRepository( |
335 | + TestRelatedSnapsMixin, TestCaseWithFactory): |
336 | + |
337 | + context_type = "repository" |
338 | + |
339 | + def makeContext(self): |
340 | + return self.factory.makeGitRepository() |
341 | + |
342 | + def makeSnap(self, context): |
343 | + [ref] = self.factory.makeGitRefs(repository=context) |
344 | + return self.factory.makeSnap(git_ref=ref) |
345 | + |
346 | + |
347 | +class TestRelatedSnapsGitRef(TestRelatedSnapsMixin, TestCaseWithFactory): |
348 | + |
349 | + context_type = "branch" |
350 | + |
351 | + def makeContext(self): |
352 | + return self.factory.makeGitRefs()[0] |
353 | + |
354 | + def makeSnap(self, context): |
355 | + return self.factory.makeSnap(git_ref=context) |
356 | |
357 | === modified file 'lib/lp/snappy/browser/tests/test_snaplisting.py' |
358 | --- lib/lp/snappy/browser/tests/test_snaplisting.py 2015-09-16 13:30:33 +0000 |
359 | +++ lib/lp/snappy/browser/tests/test_snaplisting.py 2015-10-05 13:41:26 +0000 |
360 | @@ -55,20 +55,21 @@ |
361 | self.assertThat(self.getViewBrowser(context).contents, Not(matcher)) |
362 | login(ANONYMOUS) |
363 | self.makeSnap(**kwargs) |
364 | + self.makeSnap(**kwargs) |
365 | self.assertThat(self.getViewBrowser(context).contents, matcher) |
366 | |
367 | def test_branch_links_to_snaps(self): |
368 | branch = self.factory.makeAnyBranch() |
369 | - self.assertSnapsLink(branch, "1 snap package", branch=branch) |
370 | + self.assertSnapsLink(branch, "2 snap packages", branch=branch) |
371 | |
372 | def test_git_repository_links_to_snaps(self): |
373 | repository = self.factory.makeGitRepository() |
374 | [ref] = self.factory.makeGitRefs(repository=repository) |
375 | - self.assertSnapsLink(repository, "1 snap package", git_ref=ref) |
376 | + self.assertSnapsLink(repository, "2 snap packages", git_ref=ref) |
377 | |
378 | def test_git_ref_links_to_snaps(self): |
379 | [ref] = self.factory.makeGitRefs() |
380 | - self.assertSnapsLink(ref, "1 snap package", git_ref=ref) |
381 | + self.assertSnapsLink(ref, "2 snap packages", git_ref=ref) |
382 | |
383 | def test_person_links_to_snaps(self): |
384 | person = self.factory.makePerson() |
385 | @@ -83,54 +84,38 @@ |
386 | project, "View snap packages", link_has_context=True, git_ref=ref) |
387 | |
388 | def test_branch_snap_listing(self): |
389 | - # We can see snap packages for a Bazaar branch. We need to create |
390 | - # two, since if there's only one then +snaps will redirect to that |
391 | - # package. |
392 | + # We can see snap packages for a Bazaar branch. |
393 | branch = self.factory.makeAnyBranch() |
394 | - for _ in range(2): |
395 | - self.makeSnap(branch=branch) |
396 | + self.makeSnap(branch=branch) |
397 | text = self.getMainText(branch, "+snaps") |
398 | self.assertTextMatchesExpressionIgnoreWhitespace(""" |
399 | Snap packages for lp:.* |
400 | Name Owner Registered |
401 | - snap-name.* Team Name.* .* |
402 | snap-name.* Team Name.* .*""", text) |
403 | |
404 | def test_git_repository_snap_listing(self): |
405 | - # We can see snap packages for a Git repository. We need to create |
406 | - # two, since if there's only one then +snaps will redirect to that |
407 | - # package. |
408 | + # We can see snap packages for a Git repository. |
409 | repository = self.factory.makeGitRepository() |
410 | - ref1, ref2 = self.factory.makeGitRefs( |
411 | - repository=repository, |
412 | - paths=[u"refs/heads/branch-1", u"refs/heads/branch-2"]) |
413 | - for ref in ref1, ref2: |
414 | - self.makeSnap(git_ref=ref) |
415 | + [ref] = self.factory.makeGitRefs(repository=repository) |
416 | + self.makeSnap(git_ref=ref) |
417 | text = self.getMainText(repository, "+snaps") |
418 | self.assertTextMatchesExpressionIgnoreWhitespace(""" |
419 | Snap packages for lp:~.* |
420 | Name Owner Registered |
421 | - snap-name.* Team Name.* .* |
422 | snap-name.* Team Name.* .*""", text) |
423 | |
424 | def test_git_ref_snap_listing(self): |
425 | - # We can see snap packages for a Git reference. We need to create |
426 | - # two, since if there's only one then +snaps will redirect to that |
427 | - # package. |
428 | + # We can see snap packages for a Git reference. |
429 | [ref] = self.factory.makeGitRefs() |
430 | - for _ in range(2): |
431 | - self.makeSnap(git_ref=ref) |
432 | + self.makeSnap(git_ref=ref) |
433 | text = self.getMainText(ref, "+snaps") |
434 | self.assertTextMatchesExpressionIgnoreWhitespace(""" |
435 | Snap packages for ~.*:.* |
436 | Name Owner Registered |
437 | - snap-name.* Team Name.* .* |
438 | snap-name.* Team Name.* .*""", text) |
439 | |
440 | def test_person_snap_listing(self): |
441 | - # We can see snap packages for a person. We need to create two, |
442 | - # since if there's only one then +snaps will redirect to that |
443 | - # package. |
444 | + # We can see snap packages for a person. |
445 | owner = self.factory.makePerson(displayname="Snap Owner") |
446 | self.makeSnap( |
447 | registrant=owner, owner=owner, branch=self.factory.makeAnyBranch(), |
448 | @@ -146,9 +131,7 @@ |
449 | snap-name.* lp:.* .*""", text) |
450 | |
451 | def test_project_snap_listing(self): |
452 | - # We can see snap packages for a project. We need to create two, |
453 | - # since if there's only one then +snaps will redirect to that |
454 | - # package. |
455 | + # We can see snap packages for a project. |
456 | project = self.factory.makeProduct(displayname="Snappable") |
457 | self.makeSnap( |
458 | branch=self.factory.makeProductBranch(product=project), |
459 | |
460 | === modified file 'lib/lp/snappy/templates/snap-macros.pt' |
461 | --- lib/lp/snappy/templates/snap-macros.pt 2015-09-18 10:15:54 +0000 |
462 | +++ lib/lp/snappy/templates/snap-macros.pt 2015-10-05 13:41:26 +0000 |
463 | @@ -14,13 +14,7 @@ |
464 | |
465 | <div id="snap-links" class="actions"> |
466 | <div id="snap-summary"> |
467 | - <tal:no-snaps condition="not: view/snap_count"> |
468 | - No snap packages |
469 | - </tal:no-snaps> |
470 | - <tal:snaps condition="view/snap_count"> |
471 | - <a href="+snaps" tal:content="view/snap_count_text">1 snap package</a> |
472 | - </tal:snaps> |
473 | - using this <metal:slot define-slot="context_type">branch</metal:slot>. |
474 | + <tal:snaps replace="structure view/snaps_link" /> |
475 | </div> |
476 | </div> |
477 |
Yes please.