Merge lp:~elachuni/ubuntu-webcatalog/navigation into lp:ubuntu-webcatalog
- navigation
- Merge into trunk
Proposed by
Anthony Lenton
Status: | Merged |
---|---|
Approved by: | Danny Tamez |
Approved revision: | 42 |
Merged at revision: | 32 |
Proposed branch: | lp:~elachuni/ubuntu-webcatalog/navigation |
Merge into: | lp:ubuntu-webcatalog |
Diff against target: |
432 lines (+176/-24) 9 files modified
src/webcatalog/admin.py (+2/-0) src/webcatalog/models/applications.py (+5/-0) src/webcatalog/static/css/webcatalog.css (+53/-2) src/webcatalog/templates/webcatalog/application_detail.html (+16/-2) src/webcatalog/templates/webcatalog/application_overview_snippet.html (+9/-5) src/webcatalog/templates/webcatalog/department_overview.html (+18/-0) src/webcatalog/tests/test_views.py (+45/-10) src/webcatalog/urls.py (+3/-1) src/webcatalog/views.py (+25/-4) |
To merge this branch: | bzr merge lp:~elachuni/ubuntu-webcatalog/navigation |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Danny Tamez (community) | Approve | ||
Review via email: mp+66636@code.launchpad.net |
Commit message
Add a right sidebar navigation portlet to switch between distroseries
Description of the change
Overview
========
Add a right sidebar navigation portlet to switch between distroseries
Details
=======
The portlet was added both on the application details and the department overview screens. For that we needed to provide a distroseries-
For consistency, I made the distroseries-
While I was there, I
- Fixed the breadcrumbs background to work with apps with extra-long names (like "A tool for the blackbox/fluxbox window managers that runs commands" -- package bbrun)
- Registered DistroSeries with the admin
To post a comment you must log in.
- 41. By Anthony Lenton
-
Test fix.
- 42. By Anthony Lenton
-
Just bumping rev.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/webcatalog/admin.py' | |||
2 | --- src/webcatalog/admin.py 2011-06-17 16:21:59 +0000 | |||
3 | +++ src/webcatalog/admin.py 2011-07-01 17:17:27 +0000 | |||
4 | @@ -25,6 +25,7 @@ | |||
5 | 25 | from webcatalog.models import ( | 25 | from webcatalog.models import ( |
6 | 26 | Application, | 26 | Application, |
7 | 27 | Department, | 27 | Department, |
8 | 28 | DistroSeries, | ||
9 | 28 | ) | 29 | ) |
10 | 29 | 30 | ||
11 | 30 | __metaclass__ = type | 31 | __metaclass__ = type |
12 | @@ -41,3 +42,4 @@ | |||
13 | 41 | 42 | ||
14 | 42 | admin.site.register(Application, ApplicationAdmin) | 43 | admin.site.register(Application, ApplicationAdmin) |
15 | 43 | admin.site.register(Department) | 44 | admin.site.register(Department) |
16 | 45 | admin.site.register(DistroSeries) | ||
17 | 44 | 46 | ||
18 | === modified file 'src/webcatalog/models/applications.py' | |||
19 | --- src/webcatalog/models/applications.py 2011-06-29 14:42:24 +0000 | |||
20 | +++ src/webcatalog/models/applications.py 2011-07-01 17:17:27 +0000 | |||
21 | @@ -99,6 +99,11 @@ | |||
22 | 99 | stripped = [x.strip() for x in self.categories.split(';')] | 99 | stripped = [x.strip() for x in self.categories.split(';')] |
23 | 100 | return set(x for x in stripped if x) | 100 | return set(x for x in stripped if x) |
24 | 101 | 101 | ||
25 | 102 | def available_distroseries(self): | ||
26 | 103 | """Return the set of distroseries for which this app is available""" | ||
27 | 104 | return DistroSeries.objects.filter( | ||
28 | 105 | application__package_name=self.package_name).order_by('version') | ||
29 | 106 | |||
30 | 102 | @classmethod | 107 | @classmethod |
31 | 103 | def from_json(cls, data): | 108 | def from_json(cls, data): |
32 | 104 | app = Application() | 109 | app = Application() |
33 | 105 | 110 | ||
34 | === modified file 'src/webcatalog/static/css/webcatalog.css' | |||
35 | --- src/webcatalog/static/css/webcatalog.css 2011-06-23 14:49:53 +0000 | |||
36 | +++ src/webcatalog/static/css/webcatalog.css 2011-07-01 17:17:27 +0000 | |||
37 | @@ -16,6 +16,8 @@ | |||
38 | 16 | -webkit-box-shadow: #bbb 2px 2px 5px 1px; | 16 | -webkit-box-shadow: #bbb 2px 2px 5px 1px; |
39 | 17 | margin: 12px 0 20px; | 17 | margin: 12px 0 20px; |
40 | 18 | font-size: 14px; | 18 | font-size: 14px; |
41 | 19 | width: 684px; | ||
42 | 20 | float: left; | ||
43 | 19 | } | 21 | } |
44 | 20 | 22 | ||
45 | 21 | #sc-mockup h2 { | 23 | #sc-mockup h2 { |
46 | @@ -44,7 +46,7 @@ | |||
47 | 44 | } | 46 | } |
48 | 45 | .screenshot { | 47 | .screenshot { |
49 | 46 | float: right; | 48 | float: right; |
51 | 47 | margin-right: 16px; | 49 | margin: 0 16px; |
52 | 48 | } | 50 | } |
53 | 49 | 51 | ||
54 | 50 | .noscreenshot { | 52 | .noscreenshot { |
55 | @@ -73,14 +75,63 @@ | |||
56 | 73 | 75 | ||
57 | 74 | /* End software centre mockup */ | 76 | /* End software centre mockup */ |
58 | 75 | 77 | ||
59 | 78 | /* Right sidebar */ | ||
60 | 79 | #rightbar { | ||
61 | 80 | float: right; | ||
62 | 81 | width: 206px; | ||
63 | 82 | margin-top: 28px; | ||
64 | 83 | } | ||
65 | 84 | |||
66 | 85 | .portletheader { | ||
67 | 86 | padding: 10px 8px; | ||
68 | 87 | font-size: 14px; | ||
69 | 88 | background: #DD4814; | ||
70 | 89 | color: white; | ||
71 | 90 | -moz-border-radius: 4px 4px 0 0; | ||
72 | 91 | -webkit-border-radius: 4px 4px 0 0; | ||
73 | 92 | -khtml-border-radius: 4px 4px 0 0; | ||
74 | 93 | border-radius: 4px 4px 0 0; | ||
75 | 94 | } | ||
76 | 95 | |||
77 | 96 | ul.portletactions { | ||
78 | 97 | font-size: 12px; | ||
79 | 98 | list-style-image: none; | ||
80 | 99 | } | ||
81 | 100 | |||
82 | 101 | ul.portletactions li { | ||
83 | 102 | border-bottom: 1px dotted gray; | ||
84 | 103 | margin: 0; | ||
85 | 104 | } | ||
86 | 105 | |||
87 | 106 | ul.portletactions li a, ul.portletactions li span { | ||
88 | 107 | padding: 8px; | ||
89 | 108 | display: block; | ||
90 | 109 | color: black; | ||
91 | 110 | } | ||
92 | 111 | |||
93 | 112 | ul.portletactions li.active span, ul.portletactions a:hover { | ||
94 | 113 | background: transparent url("/assets/images/subnav_active_bg.png"); | ||
95 | 114 | color: #E24912; | ||
96 | 115 | text-decoration: none; | ||
97 | 116 | } | ||
98 | 117 | /* End right sidebar */ | ||
99 | 118 | |||
100 | 119 | .main-column { | ||
101 | 120 | width: 684px; | ||
102 | 121 | float: left; | ||
103 | 122 | } | ||
104 | 76 | .app-overview-row { | 123 | .app-overview-row { |
106 | 77 | height: 36px; | 124 | min-height: 36px; |
107 | 78 | padding: 2px; | 125 | padding: 2px; |
108 | 79 | } | 126 | } |
109 | 80 | .app-overview-row img { | 127 | .app-overview-row img { |
110 | 81 | float: left; | 128 | float: left; |
111 | 82 | margin-right: 10px; | 129 | margin-right: 10px; |
112 | 83 | } | 130 | } |
113 | 131 | .app-overview-text { | ||
114 | 132 | float: left; | ||
115 | 133 | width: 634px; | ||
116 | 134 | } | ||
117 | 84 | .app-overview-row h3 { | 135 | .app-overview-row h3 { |
118 | 85 | padding: 0; | 136 | padding: 0; |
119 | 86 | margin: 0; | 137 | margin: 0; |
120 | 87 | 138 | ||
121 | === added file 'src/webcatalog/static/images/applications-other-64.png' | |||
122 | 88 | Binary files src/webcatalog/static/images/applications-other-64.png 1970-01-01 00:00:00 +0000 and src/webcatalog/static/images/applications-other-64.png 2011-07-01 17:17:27 +0000 differ | 139 | Binary files src/webcatalog/static/images/applications-other-64.png 1970-01-01 00:00:00 +0000 and src/webcatalog/static/images/applications-other-64.png 2011-07-01 17:17:27 +0000 differ |
123 | === added file 'src/webcatalog/static/images/applications-other.png' | |||
124 | 89 | Binary files src/webcatalog/static/images/applications-other.png 1970-01-01 00:00:00 +0000 and src/webcatalog/static/images/applications-other.png 2011-07-01 17:17:27 +0000 differ | 140 | Binary files src/webcatalog/static/images/applications-other.png 1970-01-01 00:00:00 +0000 and src/webcatalog/static/images/applications-other.png 2011-07-01 17:17:27 +0000 differ |
125 | === modified file 'src/webcatalog/static/images/breadcrumbs_bg.png' | |||
126 | 90 | Binary files src/webcatalog/static/images/breadcrumbs_bg.png 2011-06-23 14:20:52 +0000 and src/webcatalog/static/images/breadcrumbs_bg.png 2011-07-01 17:17:27 +0000 differ | 141 | Binary files src/webcatalog/static/images/breadcrumbs_bg.png 2011-06-23 14:20:52 +0000 and src/webcatalog/static/images/breadcrumbs_bg.png 2011-07-01 17:17:27 +0000 differ |
127 | === added file 'src/webcatalog/static/images/subnav_active_bg.png' | |||
128 | 91 | Binary files src/webcatalog/static/images/subnav_active_bg.png 1970-01-01 00:00:00 +0000 and src/webcatalog/static/images/subnav_active_bg.png 2011-07-01 17:17:27 +0000 differ | 142 | Binary files src/webcatalog/static/images/subnav_active_bg.png 1970-01-01 00:00:00 +0000 and src/webcatalog/static/images/subnav_active_bg.png 2011-07-01 17:17:27 +0000 differ |
129 | === modified file 'src/webcatalog/templates/webcatalog/application_detail.html' | |||
130 | --- src/webcatalog/templates/webcatalog/application_detail.html 2011-06-29 09:24:48 +0000 | |||
131 | +++ src/webcatalog/templates/webcatalog/application_detail.html 2011-07-01 17:17:27 +0000 | |||
132 | @@ -7,13 +7,27 @@ | |||
133 | 7 | 7 | ||
134 | 8 | {% block content %} | 8 | {% block content %} |
135 | 9 | {% include "webcatalog/breadcrumbs_snippet.html" %} | 9 | {% include "webcatalog/breadcrumbs_snippet.html" %} |
137 | 10 | 10 | <div id="rightbar"> | |
138 | 11 | <div class="portlet"> | ||
139 | 12 | <div class="portletheader">Available versions</div> | ||
140 | 13 | <ul class="portletactions"> | ||
141 | 14 | {% for ds in available_distroseries %} | ||
142 | 15 | <li class="item{% ifequal ds.code_name distroseries %} active{% endifequal %}{% if forloop.last %} last{% endif %}"> | ||
143 | 16 | {% ifequal ds.code_name distroseries %} | ||
144 | 17 | <span>Ubuntu {{ ds.version }} ({{ ds.code_name }})</span> | ||
145 | 18 | {% else %} | ||
146 | 19 | <a href="{% url wc-package-detail ds.code_name application.package_name %}">Ubuntu {{ ds.version }} ({{ ds.code_name }})</a> | ||
147 | 20 | {% endifequal %}</li> | ||
148 | 21 | {% endfor %} | ||
149 | 22 | </ul> | ||
150 | 23 | </div> | ||
151 | 24 | </div> | ||
152 | 11 | <div id="sc-mockup"> | 25 | <div id="sc-mockup"> |
153 | 12 | <div class="header"> | 26 | <div class="header"> |
154 | 13 | {% if application.icon %} | 27 | {% if application.icon %} |
155 | 14 | <img class="icon64" src="{{ application.icon.url }}"/> | 28 | <img class="icon64" src="{{ application.icon.url }}"/> |
156 | 15 | {% else %} | 29 | {% else %} |
158 | 16 | <img class="icon64" src="{{ STATIC_URL }}images/noicon_32.png"/> | 30 | <img class="icon64" src="{{ STATIC_URL }}images/applications-other-64.png"/> |
159 | 17 | {% endif %} | 31 | {% endif %} |
160 | 18 | 32 | ||
161 | 19 | <h2>{{ application.name }}</h2> | 33 | <h2>{{ application.name }}</h2> |
162 | 20 | 34 | ||
163 | === modified file 'src/webcatalog/templates/webcatalog/application_overview_snippet.html' | |||
164 | --- src/webcatalog/templates/webcatalog/application_overview_snippet.html 2011-06-28 15:03:12 +0000 | |||
165 | +++ src/webcatalog/templates/webcatalog/application_overview_snippet.html 2011-07-01 17:17:27 +0000 | |||
166 | @@ -1,11 +1,15 @@ | |||
167 | 1 | <div class="app-overview-row"> | 1 | <div class="app-overview-row"> |
168 | 2 | <div> | ||
169 | 2 | {% if app.icon %} | 3 | {% if app.icon %} |
170 | 3 | <img src="{{ app.icon.url }}" width="32" height="32" /> | 4 | <img src="{{ app.icon.url }}" width="32" height="32" /> |
171 | 4 | {% else %} | 5 | {% else %} |
173 | 5 | <img src="{{ STATIC_URL }}images/noicon_32.png"/> | 6 | <img src="{{ STATIC_URL }}images/applications-other.png"/> |
174 | 6 | {% endif %} | 7 | {% endif %} |
179 | 7 | <h3> | 8 | </div> |
180 | 8 | <a href="{% url wc-package-detail app.distroseries.code_name app.package_name %}">{{ app.name }}</a> | 9 | <div class="app-overview-text"> |
181 | 9 | </h3> | 10 | <h3> |
182 | 10 | <p>{{ app.comment }}</p> | 11 | <a href="{% url wc-package-detail app.distroseries.code_name app.package_name %}">{{ app.name }}</a> |
183 | 12 | </h3> | ||
184 | 13 | <p>{{ app.comment }}</p> | ||
185 | 14 | </div> | ||
186 | 11 | </div> | 15 | </div> |
187 | 12 | 16 | ||
188 | === modified file 'src/webcatalog/templates/webcatalog/department_overview.html' | |||
189 | --- src/webcatalog/templates/webcatalog/department_overview.html 2011-06-28 15:03:12 +0000 | |||
190 | +++ src/webcatalog/templates/webcatalog/department_overview.html 2011-07-01 17:17:27 +0000 | |||
191 | @@ -7,6 +7,23 @@ | |||
192 | 7 | {% block content %} | 7 | {% block content %} |
193 | 8 | {% include "webcatalog/breadcrumbs_snippet.html" %} | 8 | {% include "webcatalog/breadcrumbs_snippet.html" %} |
194 | 9 | 9 | ||
195 | 10 | <div id="rightbar"> | ||
196 | 11 | <div class="portlet"> | ||
197 | 12 | <div class="portletheader">Available versions</div> | ||
198 | 13 | <ul class="portletactions"> | ||
199 | 14 | {% for ds in available_distroseries %} | ||
200 | 15 | <li class="item{% ifequal ds.code_name distroseries %} active{% endifequal %}{% if forloop.last %} last{% endif %}"> | ||
201 | 16 | {% ifequal ds.code_name distroseries %} | ||
202 | 17 | <span>Ubuntu {{ ds.version }} ({{ ds.code_name }})</span> | ||
203 | 18 | {% else %} | ||
204 | 19 | <a href="{% url wc-department ds.code_name dept.id %}">Ubuntu {{ ds.version }} ({{ ds.code_name }})</a> | ||
205 | 20 | {% endifequal %}</li> | ||
206 | 21 | {% endfor %} | ||
207 | 22 | </ul> | ||
208 | 23 | </div> | ||
209 | 24 | </div> | ||
210 | 25 | |||
211 | 26 | <div class="main-column"> | ||
212 | 10 | {% if subdepts %} | 27 | {% if subdepts %} |
213 | 11 | <h3>{% trans "Subsections" %}:</h3> | 28 | <h3>{% trans "Subsections" %}:</h3> |
214 | 12 | 29 | ||
215 | @@ -26,5 +43,6 @@ | |||
216 | 26 | {% else %} | 43 | {% else %} |
217 | 27 | <p>{% trans "No applications found." %}</p> | 44 | <p>{% trans "No applications found." %}</p> |
218 | 28 | {% endif %} | 45 | {% endif %} |
219 | 46 | </div> | ||
220 | 29 | 47 | ||
221 | 30 | {% endblock %} | 48 | {% endblock %} |
222 | 31 | 49 | ||
223 | === modified file 'src/webcatalog/tests/test_views.py' | |||
224 | --- src/webcatalog/tests/test_views.py 2011-06-29 15:24:23 +0000 | |||
225 | +++ src/webcatalog/tests/test_views.py 2011-07-01 17:17:27 +0000 | |||
226 | @@ -68,7 +68,8 @@ | |||
227 | 68 | if not detail_package: | 68 | if not detail_package: |
228 | 69 | detail_package = app.package_name | 69 | detail_package = app.package_name |
229 | 70 | 70 | ||
231 | 71 | url = reverse('wc-package-detail', args=[detail_package, detail_distro]) | 71 | url = reverse('wc-package-detail', args=[detail_distro, |
232 | 72 | detail_package]) | ||
233 | 72 | 73 | ||
234 | 73 | if useragent: | 74 | if useragent: |
235 | 74 | response = self.client.get(url, HTTP_USER_AGENT=useragent) | 75 | response = self.client.get(url, HTTP_USER_AGENT=useragent) |
236 | @@ -134,6 +135,22 @@ | |||
237 | 134 | '<a href="{lucid_app_url}">your version of Ubuntu</a>.'.format( | 135 | '<a href="{lucid_app_url}">your version of Ubuntu</a>.'.format( |
238 | 135 | lucid_app_url=lucid_app_url)) | 136 | lucid_app_url=lucid_app_url)) |
239 | 136 | 137 | ||
240 | 138 | def test_includes_right_navigation(self): | ||
241 | 139 | lucid = self.factory.make_distroseries(code_name='lucid', | ||
242 | 140 | version='10.04') | ||
243 | 141 | maverick = self.factory.make_distroseries(code_name='maverick', | ||
244 | 142 | version='10.10') | ||
245 | 143 | lucid_app = self.factory.make_application(package_name='pkgfoo', | ||
246 | 144 | distroseries=lucid) | ||
247 | 145 | maverick_app = self.factory.make_application(package_name='pkgfoo', | ||
248 | 146 | distroseries=maverick) | ||
249 | 147 | |||
250 | 148 | response, app = self.get_app_and_response(name="Foobar") | ||
251 | 149 | |||
252 | 150 | for ds in ['lucid', 'maverick']: | ||
253 | 151 | url = reverse('wc-package-detail', args=[ds, 'pkgfoo']) | ||
254 | 152 | self.assertContains(response, '<a href="{0}">Ubuntu'.format(url)) | ||
255 | 153 | |||
256 | 137 | 154 | ||
257 | 138 | class ApplicationDetailNoSeriesTestCase(TestCaseWithFactory): | 155 | class ApplicationDetailNoSeriesTestCase(TestCaseWithFactory): |
258 | 139 | 156 | ||
259 | @@ -155,7 +172,7 @@ | |||
260 | 155 | 172 | ||
261 | 156 | self.assertRedirects( | 173 | self.assertRedirects( |
262 | 157 | response, reverse( | 174 | response, reverse( |
264 | 158 | 'wc-package-detail', args=['pkgfoo', default_distro])) | 175 | 'wc-package-detail', args=[default_distro, 'pkgfoo'])) |
265 | 159 | 176 | ||
266 | 160 | def test_redirects_to_ua_distroseries(self): | 177 | def test_redirects_to_ua_distroseries(self): |
267 | 161 | # If a distroseries is not included in the url, but we | 178 | # If a distroseries is not included in the url, but we |
268 | @@ -175,7 +192,7 @@ | |||
269 | 175 | 192 | ||
270 | 176 | self.assertRedirects( | 193 | self.assertRedirects( |
271 | 177 | response, reverse( | 194 | response, reverse( |
273 | 178 | 'wc-package-detail', args=['pkgfoo', 'lucid'])) | 195 | 'wc-package-detail', args=['lucid', 'pkgfoo'])) |
274 | 179 | 196 | ||
275 | 180 | 197 | ||
276 | 181 | class SearchTestCase(TestCaseWithFactory): | 198 | class SearchTestCase(TestCaseWithFactory): |
277 | @@ -297,7 +314,8 @@ | |||
278 | 297 | dept = self.factory.make_department('foo') | 314 | dept = self.factory.make_department('foo') |
279 | 298 | subdept = self.factory.make_department('bar', parent=dept) | 315 | subdept = self.factory.make_department('bar', parent=dept) |
280 | 299 | 316 | ||
282 | 300 | response = self.client.get(reverse('wc-department', args=[dept.id])) | 317 | response = self.client.get(reverse('wc-department', args=[ |
283 | 318 | settings.DEFAULT_DISTRO, dept.id])) | ||
284 | 301 | 319 | ||
285 | 302 | self.assertContains(response, reverse('wc-department', | 320 | self.assertContains(response, reverse('wc-department', |
286 | 303 | args=[subdept.id])) | 321 | args=[subdept.id])) |
287 | @@ -307,7 +325,8 @@ | |||
288 | 307 | dept = self.factory.make_department('bar') | 325 | dept = self.factory.make_department('bar') |
289 | 308 | app.departments.add(dept) | 326 | app.departments.add(dept) |
290 | 309 | 327 | ||
292 | 310 | response = self.client.get(reverse('wc-department', args=[dept.id])) | 328 | response = self.client.get(reverse('wc-department', args=[ |
293 | 329 | app.distroseries.code_name, dept.id])) | ||
294 | 311 | 330 | ||
295 | 312 | self.assertContains(response, reverse('wc-package-detail', | 331 | self.assertContains(response, reverse('wc-package-detail', |
296 | 313 | args=[app.distroseries.code_name, app.package_name])) | 332 | args=[app.distroseries.code_name, app.package_name])) |
297 | @@ -315,17 +334,19 @@ | |||
298 | 315 | def test_department_with_no_subdepts_doesnt_contain_header(self): | 334 | def test_department_with_no_subdepts_doesnt_contain_header(self): |
299 | 316 | dept = self.factory.make_department('bar') | 335 | dept = self.factory.make_department('bar') |
300 | 317 | 336 | ||
302 | 318 | response = self.client.get(reverse('wc-department', args=[dept.id])) | 337 | response = self.client.get(reverse('wc-department', args=[ |
303 | 338 | settings.DEFAULT_DISTRO, dept.id])) | ||
304 | 319 | 339 | ||
305 | 320 | self.assertNotContains(response, 'Subsections') | 340 | self.assertNotContains(response, 'Subsections') |
306 | 321 | 341 | ||
307 | 322 | def test_department_shows_paginated_results(self): | 342 | def test_department_shows_paginated_results(self): |
308 | 323 | dept = self.factory.make_department('bar') | 343 | dept = self.factory.make_department('bar') |
309 | 344 | lucid = self.factory.make_distroseries(code_name='lucid') | ||
310 | 324 | for count in range(3): | 345 | for count in range(3): |
312 | 325 | app = self.factory.make_application() | 346 | app = self.factory.make_application(distroseries=lucid) |
313 | 326 | app.departments.add(dept) | 347 | app.departments.add(dept) |
314 | 327 | 348 | ||
316 | 328 | url = reverse('wc-department', args=[dept.id]) | 349 | url = reverse('wc-department', args=['lucid', dept.id]) |
317 | 329 | with patch_settings(PAGE_BATCH_SIZE=2): | 350 | with patch_settings(PAGE_BATCH_SIZE=2): |
318 | 330 | response = self.client.get(url) | 351 | response = self.client.get(url) |
319 | 331 | 352 | ||
320 | @@ -340,8 +361,7 @@ | |||
321 | 340 | 361 | ||
322 | 341 | def test_invalid_page_doesnt_error(self): | 362 | def test_invalid_page_doesnt_error(self): |
323 | 342 | dept = self.factory.make_department('bar') | 363 | dept = self.factory.make_department('bar') |
326 | 343 | url = reverse('wc-department', args=[dept.id]) | 364 | url = reverse('wc-department', args=[settings.DEFAULT_DISTRO, dept.id]) |
325 | 344 | |||
327 | 345 | response = self.client.get(url, data={'page': 'aef8'}) | 365 | response = self.client.get(url, data={'page': 'aef8'}) |
328 | 346 | page = response.context['page'] | 366 | page = response.context['page'] |
329 | 347 | self.assertEqual(1, page.number) | 367 | self.assertEqual(1, page.number) |
330 | @@ -353,3 +373,18 @@ | |||
331 | 353 | response = self.client.get(url, data={'page': '999'}) | 373 | response = self.client.get(url, data={'page': '999'}) |
332 | 354 | page = response.context['page'] | 374 | page = response.context['page'] |
333 | 355 | self.assertEqual(1, page.number) | 375 | self.assertEqual(1, page.number) |
334 | 376 | |||
335 | 377 | def test_department_includes_right_navigation(self): | ||
336 | 378 | dept = self.factory.make_department('bar') | ||
337 | 379 | lucid = self.factory.make_distroseries(code_name='lucid', | ||
338 | 380 | version='10.04') | ||
339 | 381 | maverick = self.factory.make_distroseries(code_name='maverick', | ||
340 | 382 | version='10.10') | ||
341 | 383 | |||
342 | 384 | response = self.client.get(reverse('wc-department', args=[ | ||
343 | 385 | settings.DEFAULT_DISTRO, dept.id])) | ||
344 | 386 | |||
345 | 387 | for ds in ['lucid', 'maverick']: | ||
346 | 388 | url = reverse('wc-department', args=[ds, dept.id]) | ||
347 | 389 | self.assertContains(response, '<a href="{0}">Ubuntu'.format(url)) | ||
348 | 390 | |||
349 | 356 | 391 | ||
350 | === modified file 'src/webcatalog/urls.py' | |||
351 | --- src/webcatalog/urls.py 2011-06-29 12:47:09 +0000 | |||
352 | +++ src/webcatalog/urls.py 2011-07-01 17:17:27 +0000 | |||
353 | @@ -31,9 +31,11 @@ | |||
354 | 31 | 31 | ||
355 | 32 | urlpatterns = patterns('webcatalog.views', | 32 | urlpatterns = patterns('webcatalog.views', |
356 | 33 | url(r'^$', 'index', name='wc-index'), | 33 | url(r'^$', 'index', name='wc-index'), |
357 | 34 | url(r'^department/(?P<distro>[-.+\w]+)/(?P<dept_id>\d+)/$', | ||
358 | 35 | 'department_overview', name='wc-department'), | ||
359 | 34 | url(r'^department/(?P<dept_id>\d+)/$', 'department_overview', | 36 | url(r'^department/(?P<dept_id>\d+)/$', 'department_overview', |
360 | 35 | name='wc-department'), | 37 | name='wc-department'), |
362 | 36 | url(r'^applications/(?P<package_name>[-.+\w]+)/(?P<distro>[-.+\w]+)/$', | 38 | url(r'^applications/(?P<distro>[-.+\w]+)/(?P<package_name>[-.+\w]+)/$', |
363 | 37 | 'application_detail', name="wc-package-detail"), | 39 | 'application_detail', name="wc-package-detail"), |
364 | 38 | url(r'^applications/(?P<package_name>[-.+\w]+)/$', 'application_detail', | 40 | url(r'^applications/(?P<package_name>[-.+\w]+)/$', 'application_detail', |
365 | 39 | name="wc-package-detail"), | 41 | name="wc-package-detail"), |
366 | 40 | 42 | ||
367 | === modified file 'src/webcatalog/views.py' | |||
368 | --- src/webcatalog/views.py 2011-06-30 16:38:56 +0000 | |||
369 | +++ src/webcatalog/views.py 2011-07-01 17:17:27 +0000 | |||
370 | @@ -39,6 +39,7 @@ | |||
371 | 39 | from webcatalog.models import ( | 39 | from webcatalog.models import ( |
372 | 40 | Application, | 40 | Application, |
373 | 41 | Department, | 41 | Department, |
374 | 42 | DistroSeries, | ||
375 | 42 | ) | 43 | ) |
376 | 43 | from webcatalog.utilities import UserAgentString | 44 | from webcatalog.utilities import UserAgentString |
377 | 44 | 45 | ||
378 | @@ -95,11 +96,24 @@ | |||
379 | 95 | context_instance=context) | 96 | context_instance=context) |
380 | 96 | 97 | ||
381 | 97 | 98 | ||
383 | 98 | def department_overview(request, dept_id): | 99 | def department_overview(request, dept_id, distro=None): |
384 | 100 | if distro is None: | ||
385 | 101 | useragent = UserAgentString(request.META.get('HTTP_USER_AGENT', '')) | ||
386 | 102 | # Check for the distroseries in the useragent, if we have it, | ||
387 | 103 | # redirect there. | ||
388 | 104 | if useragent.distroseries: | ||
389 | 105 | distro = useragent.distroseries | ||
390 | 106 | else: | ||
391 | 107 | distro = settings.DEFAULT_DISTRO | ||
392 | 108 | return HttpResponseRedirect( | ||
393 | 109 | reverse('wc-department', args=[distro, dept_id])) | ||
394 | 110 | |||
395 | 99 | dept = get_object_or_404(Department, pk=dept_id) | 111 | dept = get_object_or_404(Department, pk=dept_id) |
396 | 100 | subdepts = Department.objects.filter(parent=dept) | 112 | subdepts = Department.objects.filter(parent=dept) |
397 | 101 | subdepts = subdepts.order_by('name') | 113 | subdepts = subdepts.order_by('name') |
399 | 102 | apps = Application.objects.filter(departments=dept) | 114 | |
400 | 115 | apps = Application.objects.filter(departments=dept, | ||
401 | 116 | distroseries__code_name=distro) | ||
402 | 103 | apps = apps.order_by('name') | 117 | apps = apps.order_by('name') |
403 | 104 | paginator = Paginator(apps, settings.PAGE_BATCH_SIZE) | 118 | paginator = Paginator(apps, settings.PAGE_BATCH_SIZE) |
404 | 105 | page_num = _get_page_num_from_request(request, paginator) | 119 | page_num = _get_page_num_from_request(request, paginator) |
405 | @@ -108,6 +122,8 @@ | |||
406 | 108 | 'subdepts': subdepts, | 122 | 'subdepts': subdepts, |
407 | 109 | 'page': paginator.page(page_num), | 123 | 'page': paginator.page(page_num), |
408 | 110 | 'breadcrumbs': dept.crumbs(), | 124 | 'breadcrumbs': dept.crumbs(), |
409 | 125 | 'available_distroseries': DistroSeries.objects.all(), | ||
410 | 126 | 'distroseries': distro, | ||
411 | 111 | }) | 127 | }) |
412 | 112 | return render_to_response('webcatalog/department_overview.html', | 128 | return render_to_response('webcatalog/department_overview.html', |
413 | 113 | context_instance=context) | 129 | context_instance=context) |
414 | @@ -125,11 +141,16 @@ | |||
415 | 125 | distro = settings.DEFAULT_DISTRO | 141 | distro = settings.DEFAULT_DISTRO |
416 | 126 | return HttpResponseRedirect( | 142 | return HttpResponseRedirect( |
417 | 127 | reverse('wc-package-detail', | 143 | reverse('wc-package-detail', |
419 | 128 | args=[package_name, distro])) | 144 | args=[distro, package_name])) |
420 | 129 | 145 | ||
421 | 130 | app = get_object_or_404(Application, package_name=package_name, | 146 | app = get_object_or_404(Application, package_name=package_name, |
422 | 131 | distroseries__code_name=distro) | 147 | distroseries__code_name=distro) |
423 | 148 | atts = {'application': app, | ||
424 | 149 | 'available_distroseries': app.available_distroseries(), | ||
425 | 150 | 'breadcrumbs': app.crumbs(), | ||
426 | 151 | 'distroseries': distro, | ||
427 | 152 | } | ||
428 | 132 | 153 | ||
429 | 133 | return render_to_response( | 154 | return render_to_response( |
430 | 134 | 'webcatalog/application_detail.html', RequestContext( | 155 | 'webcatalog/application_detail.html', RequestContext( |
432 | 135 | request, dict(application=app, breadcrumbs=app.crumbs()))) | 156 | request, atts)) |
Looks fine.