Merge lp:~elachuni/ubuntu-webcatalog/carousel into lp:ubuntu-webcatalog
- carousel
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Anthony Lenton |
Approved revision: | 69 |
Merged at revision: | 67 |
Proposed branch: | lp:~elachuni/ubuntu-webcatalog/carousel |
Merge into: | lp:ubuntu-webcatalog |
Prerequisite: | lp:~elachuni/ubuntu-webcatalog/convoy |
Diff against target: |
491 lines (+323/-57) 9 files modified
django_project/config/main.cfg (+2/-1) src/webcatalog/schema.py (+1/-0) src/webcatalog/static/css/carousel.css (+96/-0) src/webcatalog/static/js/carousel.js (+181/-0) src/webcatalog/templates/webcatalog/application_detail.html (+1/-1) src/webcatalog/templates/webcatalog/exhibits_widget.html (+30/-39) src/webcatalog/templates/webcatalog/index.html (+6/-0) src/webcatalog/tests/test_views.py (+1/-11) src/webcatalog/views.py (+5/-5) |
To merge this branch: | bzr merge lp:~elachuni/ubuntu-webcatalog/carousel |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Nelson (community) | Approve | ||
Review via email: mp+96023@code.launchpad.net |
Commit message
Added a YUI carousel widget for the front page exhibits display.
Description of the change
Overview
========
This branch adds a YUI carousel widget for the front page exhibits display.
Details
=======
Instead of using YUI3's carousel control, I reused the controls and stripped down the code from the carousel widget on the Ubuntu One homepage.
If Javascript is disabled, the first exhibit in the list will just remain displayed, with no controls available. The list is shuffled before rendering on the template, so (ignoring cache expirations) a different exhibit will be rendered on the front page each time.
If Javascript is enabled, the exhibits will be displayed in a random order, and cycle every 5 seconds.
Thanks to the combo loader the front page uses only 20 requests, 12 of which are for the different department icons. Without the combo loader it would take up 41 extra requests.
Anthony Lenton (elachuni) wrote : | # |
Michael Nelson (michael.nelson) wrote : | # |
On Tue, Mar 6, 2012 at 12:34 AM, Anthony Lenton
<email address hidden> wrote:
> Anthony Lenton has proposed merging lp:~elachuni/ubuntu-webcatalog/carousel into lp:ubuntu-webcatalog with lp:~elachuni/ubuntu-webcatalog/convoy as a prerequisite.
>
> Requested reviews:
> Canonical Consumer Applications Hackers (canonical-
>
> For more details, see:
> https:/
>
> Overview
> ========
> This branch adds a YUI carousel widget for the front page exhibits display.
>
> Details
> =======
> Instead of using YUI3's carousel control, I reused the controls and stripped down the code from the carousel widget on the Ubuntu One homepage.
Cool!
>
> If Javascript is disabled, the first exhibit in the list will just remain displayed, with no controls available. The list is shuffled before rendering on the template, so (ignoring cache expirations) a different exhibit will be rendered on the front page each time.
>
> If Javascript is enabled, the exhibits will be displayed in a random order, and cycle every 5 seconds.
>
> Thanks to the combo loader the front page uses only 20 requests, 12 of which are for the different department icons. Without the combo loader it would take up 41 extra requests.
That's excellent! Do we have a bug for doing the department icons as a
single sprite? Would it be worth doing that?
Thanks for the screencast too... looks very nice!
> === added file 'src/webcatalog
> --- src/webcatalog/
> +++ src/webcatalog/
> @@ -0,0 +1,96 @@
> +.carousel-wrapper {
> + position: relative;
> + height: 200px;
> + overflow: hidden;
> +}
> +.container {
Should that class be more specific? carouselcontainer or even
ccontainer? I remember a time where every site had a <div
class="container"> wrapping the page. Ah, it's probably just inherited
from u1?
> === added file 'src/webcatalog
> Binary files src/webcatalog/
> === added directory 'src/webcatalog
> === added file 'src/webcatalog
> --- src/webcatalog/
> +++ src/webcatalog/
> @@ -0,0 +1,181 @@
> +YUI.add(
> + Y.namespace('uwc');
> + function Carousel(config){
> + Carousel.
> + }
> + Y.extend(Carousel, Y.Base, {
Why are we creating our own Carousel module here? Can we ask U1 to
publish theirs on the yui gallery? It'd be great to not be maintaining
this code (or, on the other side, improving code that others can reuse
too). Did you try even just pointing YUI at U1's carousel module, if
that's possible?
> + initializer: function(cfg) {
> + var nodeListSlides,
> + nodeCarousel,
> + nodeContainer = this.get(
Michael Nelson (michael.nelson) : | # |
- 68. By Anthony Lenton
-
A couple of minor fixes per code review.
- 69. By Anthony Lenton
-
Removed unnecessary container class.
Preview Diff
1 | === modified file 'django_project/config/main.cfg' |
2 | --- django_project/config/main.cfg 2012-03-05 17:41:06 +0000 |
3 | +++ django_project/config/main.cfg 2012-03-06 17:02:19 +0000 |
4 | @@ -50,7 +50,7 @@ |
5 | webcatalog.context_processors.google_analytics_id |
6 | webcatalog.context_processors.user_agent |
7 | |
8 | -static_root = ./src/webcatalog/static/ |
9 | +static_root = ./django_project/static/ |
10 | static_url = /assets/ |
11 | admin_media_prefix = /assets/admin/ |
12 | |
13 | @@ -93,6 +93,7 @@ |
14 | sca_api_url = https://sc.staging.ubuntu.com/api/2.0/ |
15 | disk_apt_cache_location = /tmp/webcat_cache |
16 | default_distro = natty |
17 | +convoy_root = ./src/webcatalog/static/ |
18 | |
19 | [google] |
20 | google_analytics_id = UA-1018242-36 |
21 | |
22 | === modified file 'src/webcatalog/schema.py' |
23 | --- src/webcatalog/schema.py 2012-01-06 18:36:08 +0000 |
24 | +++ src/webcatalog/schema.py 2012-03-06 17:02:19 +0000 |
25 | @@ -62,6 +62,7 @@ |
26 | webcatalog.preload_api_service_roots = BoolConfigOption() |
27 | webcatalog.oauth_data_store = StringConfigOption( |
28 | default='webcatalog.models.oauthtoken.DataStore') |
29 | + webcatalog.convoy_root = StringConfigOption() |
30 | |
31 | google = ConfigSection() |
32 | google.google_analytics_id = StringConfigOption() |
33 | |
34 | === added file 'src/webcatalog/static/css/carousel.css' |
35 | --- src/webcatalog/static/css/carousel.css 1970-01-01 00:00:00 +0000 |
36 | +++ src/webcatalog/static/css/carousel.css 2012-03-06 17:02:19 +0000 |
37 | @@ -0,0 +1,96 @@ |
38 | +.carousel-wrapper { |
39 | + position: relative; |
40 | + height: 200px; |
41 | + overflow: hidden; |
42 | +} |
43 | +#carousel { |
44 | + width: 100%; |
45 | + height: 100%; |
46 | + top: 0; |
47 | + left: 0; |
48 | + position: absolute; |
49 | + background: #333; |
50 | + display: block; |
51 | +} |
52 | +#carousel .next, #carousel .prev { |
53 | + background: url(/assets/images/arrow-sprite.png) no-repeat 0 0; |
54 | + position: absolute; |
55 | + z-index: 20; |
56 | + width: 33px; |
57 | + height: 66px; |
58 | + margin-top: -33px; |
59 | +} |
60 | +#carousel .next:active, #carousel .prev:active { |
61 | + margin-top: -32px; |
62 | + outline: none; |
63 | +} |
64 | +#carousel .next span, #carousel .prev span { |
65 | + position:absolute; |
66 | + left: -9999em; |
67 | + height: 0; |
68 | + width: 0; |
69 | +} |
70 | +#carousel .prev { |
71 | + left: 0; |
72 | + top: 50%; |
73 | + background-position:0 0; |
74 | +} |
75 | +#carousel .prev:hover, #carousel .prev:focus { |
76 | + outline: none; |
77 | + background-position: 0 -116px; |
78 | +} |
79 | +#carousel .next { |
80 | + right: 0; |
81 | + top: 50%; |
82 | + background-position: 0 -232px; |
83 | +} |
84 | +#carousel .next:hover, #carousel .next:focus { |
85 | + outline: none; |
86 | + background-position: 0 -348px; |
87 | +} |
88 | +#carousel .pagination { |
89 | + position: absolute; |
90 | + z-index: 20; |
91 | + left: 50%; |
92 | + top: 87%; |
93 | + margin-left: -35px; |
94 | +} |
95 | +#carousel .pagination li { |
96 | + float: left; |
97 | + margin-right: 10px; |
98 | +} |
99 | +#carousel .pagination li a { |
100 | + display: block; |
101 | + height: 10px; |
102 | + width: 10px; |
103 | + background: #aea79f; |
104 | + border-radius: 20px; |
105 | +} |
106 | +#carousel .pagination li a:hover, #carousel .pagination li a:focus, |
107 | +#carousel .pagination li a.active:hover, #carousel .pagination li a.active:focus { |
108 | + background-color: #dd4814; |
109 | +} |
110 | +#carousel .pagination li a.active { |
111 | + background-color: #fff; |
112 | +} |
113 | +#carousel .pagination li a span { |
114 | + position: absolute; |
115 | + left: -999em; |
116 | +} |
117 | +#carousel .carousel { |
118 | + width: 10000px; |
119 | + overflow: hidden; |
120 | + position: relative; |
121 | +} |
122 | +#carousel .carousel li { |
123 | + position: relative; |
124 | + display: block; |
125 | + background: #333; |
126 | + float: left; |
127 | +} |
128 | +#carousel .carousel a { |
129 | + cursor: hand; |
130 | +} |
131 | +#carousel .carousel .disabled { |
132 | + display: none; |
133 | +} |
134 | |
135 | === added file 'src/webcatalog/static/images/arrow-sprite.png' |
136 | Binary files src/webcatalog/static/images/arrow-sprite.png 1970-01-01 00:00:00 +0000 and src/webcatalog/static/images/arrow-sprite.png 2012-03-06 17:02:19 +0000 differ |
137 | === added directory 'src/webcatalog/static/js' |
138 | === added file 'src/webcatalog/static/js/carousel.js' |
139 | --- src/webcatalog/static/js/carousel.js 1970-01-01 00:00:00 +0000 |
140 | +++ src/webcatalog/static/js/carousel.js 2012-03-06 17:02:19 +0000 |
141 | @@ -0,0 +1,181 @@ |
142 | +YUI.add('uwc-carousel', function(Y) { |
143 | + Y.namespace('uwc'); |
144 | + function Carousel(config){ |
145 | + Carousel.superclass.constructor.apply(this, arguments); |
146 | + } |
147 | + Y.extend(Carousel, Y.Base, { |
148 | + initializer: function(cfg) { |
149 | + var nodeListSlides, |
150 | + nodeCarousel, |
151 | + nodeContainer = this.get("nodeContainer"), |
152 | + carouselClassName = this.get("carouselClassName"); |
153 | + this.interval = null; |
154 | + this.curSlide = 0; |
155 | + nodeListSlides = this.getCarouselNodeList(); |
156 | + this.nodeCarousel = nodeContainer.one("."+ carouselClassName); |
157 | + // Ensure Carousel is position: relative |
158 | + this.nodeCarousel.setStyle("position", "relative"); |
159 | + this.numSlides = nodeListSlides.size(); |
160 | + // init animation |
161 | + this.caroAnim = new Y.Anim({ |
162 | + node: this.nodeCarousel |
163 | + }); |
164 | + this.caroAnim.set("duration", this.get("slideAnimDuration")); |
165 | + this.caroAnim.set("easing", this.get("slideEasing")); |
166 | + this.caroAnim.on("end", function(){ |
167 | + this.updatePagination(); |
168 | + }, this); |
169 | + |
170 | + // Create next/prev |
171 | + this.generateControls(); |
172 | + // Create Paging |
173 | + this.generatePagination(); |
174 | + this.updatePagination(); |
175 | + // We are ready display everything. |
176 | + this.nodeCarousel.removeClass("hidden"); |
177 | + if (this.get("autoPlay")) { |
178 | + this.autoPlay(); |
179 | + } |
180 | + }, |
181 | + getCarouselNodeList: function() { |
182 | + var nodeContainer = this.get("nodeContainer"), |
183 | + carouselClassName = this.get("carouselClassName"); |
184 | + return nodeContainer.all("." + carouselClassName + " li"); |
185 | + }, |
186 | + updatePagination: function() { |
187 | + var nodeContainer = this.get("nodeContainer"), |
188 | + paginationListItems; |
189 | + paginationListItems = nodeContainer.all(".pagination li a"); |
190 | + paginationListItems.each(function(a){ |
191 | + var nodeClassName = a.get("className"); |
192 | + if (parseInt(nodeClassName.replace("p-", ""), 10) === this.curSlide) { |
193 | + a.addClass("active"); |
194 | + } else { |
195 | + a.removeClass("active"); |
196 | + } |
197 | + }, this); |
198 | + }, |
199 | + generatePagination: function() { |
200 | + var pageText = 'Page', |
201 | + nodeContainer = this.get("nodeContainer"), |
202 | + ol = document.createElement('ol'), |
203 | + li, a, sp, txt; |
204 | + |
205 | + ol.className = "pagination"; |
206 | + for (var i=0, j=this.numSlides; i < j; i++){ |
207 | + li = document.createElement('li'); |
208 | + a = document.createElement('a'); |
209 | + sp = document.createElement('span'); |
210 | + a.href = '#'; |
211 | + txt = document.createTextNode(pageText+(i+1)); |
212 | + sp.appendChild(txt); |
213 | + a.appendChild(sp); |
214 | + a.className = 'p-'+i; |
215 | + li.appendChild(a); |
216 | + ol.appendChild(li); |
217 | + } |
218 | + nodeContainer.append(ol); |
219 | + olNode = Y.one(ol); |
220 | + olNode.on("click", function(e){ |
221 | + var targetClass; |
222 | + e.preventDefault(); |
223 | + if (this.caroAnim.get("running") === false) { |
224 | + if (e && this.autoPlayTimer) { |
225 | + clearInterval(this.autoPlayTimer); |
226 | + } |
227 | + targetClass = e.target.get("className"); |
228 | + this.gotoSlide(parseInt(targetClass.replace("p-", ""), 10)); |
229 | + } |
230 | + }, this); |
231 | + }, |
232 | + generateControls: function() { |
233 | + var prev = Y.Node.create('<a href="#" class="prev"><span>Previous Slide</span></a>'), |
234 | + next = Y.Node.create('<a href="#" class="next"><span>Next Slide</span></a>'), |
235 | + nodeContainer = this.get("nodeContainer"); |
236 | + |
237 | + next.on("click", this.next, this); |
238 | + prev.on("click", this.prev, this); |
239 | + nodeContainer.appendChild(prev); |
240 | + nodeContainer.appendChild(next); |
241 | + }, |
242 | + advance: function(e, val){ |
243 | + if (e) { |
244 | + e.preventDefault(); |
245 | + } |
246 | + if (e && this.autoPlayTimer) { |
247 | + clearInterval(this.autoPlayTimer); |
248 | + } |
249 | + if (this.caroAnim.get("running") === true) { |
250 | + return; |
251 | + } |
252 | + this.gotoSlide(val); |
253 | + }, |
254 | + next: function(e){ |
255 | + this.advance(e, this.curSlide + 1); |
256 | + }, |
257 | + prev: function(e){ |
258 | + this.advance(e, this.curSlide - 1); |
259 | + }, |
260 | + gotoSlide: function(nSlideIndex, duration) { |
261 | + var xOffSet, slideWidth; |
262 | + slideWidth = parseInt(this.nodeCarousel.one("li").getStyle("width"), 10); |
263 | + duration = (duration === 0) ? duration : (duration || this.get("slideAnimDuration")); |
264 | + this.nSlideIndex = nSlideIndex; |
265 | + if (nSlideIndex < 0) { |
266 | + this.animateTo(-(slideWidth * (this.numSlides-1)), duration); |
267 | + this.curSlide = this.numSlides - 1; |
268 | + } else if (nSlideIndex >= (this.numSlides)) { |
269 | + this.animateTo(0, duration); |
270 | + this.curSlide = 0; |
271 | + } else { |
272 | + xOffSet = -slideWidth * nSlideIndex; |
273 | + this.animateTo(xOffSet, duration); |
274 | + this.curSlide = nSlideIndex; |
275 | + } |
276 | + |
277 | + }, |
278 | + autoPlay: function() { |
279 | + var that = this; |
280 | + this.autoPlayTimer = setInterval(function(){ |
281 | + that.next(); |
282 | + }, that.get("slideAnimInterval")); |
283 | + }, |
284 | + animateTo: function(value, duration) { |
285 | + var origDuration; |
286 | + if (duration === 0) { |
287 | + this.nodeCarousel.setStyle("left", value); |
288 | + } else { |
289 | + if (duration) { |
290 | + origDuration = this.caroAnim.get("duration"); |
291 | + this.caroAnim.set("duration", duration); |
292 | + } |
293 | + this.caroAnim.set("to", { "left": value }); |
294 | + this.caroAnim.run(); |
295 | + this.caroAnim.set("duration", origDuration); |
296 | + } |
297 | + }, |
298 | + }, { |
299 | + NAME: "carousel", |
300 | + ATTRS: { |
301 | + carouselClassName: { value: "carousel"}, |
302 | + containerHeight: { value: null }, |
303 | + containerWidth: { value: null }, |
304 | + nodeContainer: { |
305 | + setter: function(sel) { |
306 | + var n = Y.one(sel); |
307 | + if (!n) { |
308 | + Y.log('UWC:Carousel - invalid selector provided: ' + sel); |
309 | + } |
310 | + return n; |
311 | + } |
312 | + }, |
313 | + slideAnimDuration: { value: 1 }, |
314 | + slideAnimInterval: { value: 5000 }, |
315 | + slideEasing: { value: Y.Easing.easeBoth }, |
316 | + autoPlay: { value: true } |
317 | + } |
318 | + }); |
319 | + Y.uwc.Carousel = Carousel; |
320 | +}, '0.0.1', { |
321 | + requires: ['base', 'node', 'anim', 'event'] |
322 | +}); |
323 | |
324 | === modified file 'src/webcatalog/templates/webcatalog/application_detail.html' |
325 | --- src/webcatalog/templates/webcatalog/application_detail.html 2012-03-05 17:41:06 +0000 |
326 | +++ src/webcatalog/templates/webcatalog/application_detail.html 2012-03-06 17:02:19 +0000 |
327 | @@ -8,7 +8,7 @@ |
328 | {{ block.super }} |
329 | <script src="{{ STATIC_URL }}yui/3.4.0/build/yui/yui-min.js"></script> |
330 | <script> |
331 | -YUI({debug: false, combine: true, comboBase: '{% url wc-combo %}?', root: 'yui/3.4.0/build/'}).use('io-base', 'node-base', function (Y) { |
332 | +YUI({combine: true, comboBase: '{% url wc-combo %}?', root: 'yui/3.4.0/build/'}).use('io-base', 'node-base', function (Y) { |
333 | function complete(id, obj){ |
334 | var reviews_html = obj.responseText; |
335 | var reviews_div = Y.one('#reviews_placeholder'); |
336 | |
337 | === modified file 'src/webcatalog/templates/webcatalog/exhibits_widget.html' |
338 | --- src/webcatalog/templates/webcatalog/exhibits_widget.html 2012-03-01 22:42:00 +0000 |
339 | +++ src/webcatalog/templates/webcatalog/exhibits_widget.html 2012-03-06 17:02:19 +0000 |
340 | @@ -1,41 +1,32 @@ |
341 | +<div class="carousel-wrapper"> |
342 | + <div id="carousel"> |
343 | + <ol class="carousel"> |
344 | + {% autoescape off %} |
345 | + {% comment %} |
346 | +All slides except the first one start off with a "disabled" class, which will |
347 | +make them "display: none". This will avoid loading pointless remote resources |
348 | +(banners) if Javascript is disabled. The "disabled" class is then removed via |
349 | +Javascript. |
350 | + {% endcomment %} |
351 | + {% for exhibit in exhibits %} |
352 | + <li class="slide{% if forloop.counter > 1%} disabled{% endif %}"> |
353 | + <a href="{{ exhibit.destination_url }}"> |
354 | + {{ exhibit.html }} |
355 | + </a> |
356 | + </li> |
357 | + {% endfor %} |
358 | + {% endautoescape %} |
359 | + </ol> |
360 | + </div> |
361 | +</div> |
362 | <script type="text/javascript"> |
363 | - var activeExhibit = {{ active }}; |
364 | - var images = new Array(); |
365 | - |
366 | - function switchExhibit() { |
367 | - var tags = document.getElementsByClassName('exhibit-container'); |
368 | - var nExhibits = tags.length; |
369 | - activeExhibit = (activeExhibit + 1) % nExhibits; |
370 | - for (var i in tags) { |
371 | - if (i == activeExhibit) { |
372 | - tags[i].classList.add('enabled'); |
373 | - } |
374 | - else { |
375 | - tags[i].classList.remove('enabled'); |
376 | - } |
377 | - } |
378 | - setTimeout(switchExhibit, 10000); |
379 | - }; |
380 | - |
381 | - function preLoadBanners() { |
382 | - for (var i = 0; i < preLoadBanners.arguments.length; i++) { |
383 | - images[i] = new Image() |
384 | - images[i].src = preLoadBanners.arguments[i] |
385 | - } |
386 | - } |
387 | - |
388 | - window.onload = function() { |
389 | - preLoadBanners({% for exhibit in exhibits %}"{{ exhibit.banner_url }}"{% if not forloop.last %}, {% endif %}{% endfor %}); |
390 | - setTimeout(switchExhibit, 10000); |
391 | - } |
392 | +YUI({combine: true, comboBase: '{% url wc-combo %}?', root: 'yui/3.4.0/build/'}).use('uwc-carousel', function(Y) { |
393 | + var caro = new Y.uwc.Carousel({ |
394 | + nodeContainer: "#carousel", |
395 | + containerHeight: 200, |
396 | + containerWidth: 912, |
397 | + autoPlay: true |
398 | + }); |
399 | + Y.all('.slide').removeClass('disabled'); |
400 | +}); |
401 | </script> |
402 | - |
403 | -{% autoescape off %} |
404 | -{% for exhibit in exhibits %} |
405 | -<div class="exhibit-container{% ifequal forloop.counter0 active %} enabled{% endifequal %}"> |
406 | - <a href="{{ exhibit.destination_url }}"> |
407 | -{{ exhibit.html }} |
408 | - </a> |
409 | -</div> |
410 | -{% endfor %} |
411 | -{% endautoescape %} |
412 | \ No newline at end of file |
413 | |
414 | === modified file 'src/webcatalog/templates/webcatalog/index.html' |
415 | --- src/webcatalog/templates/webcatalog/index.html 2012-03-01 22:41:05 +0000 |
416 | +++ src/webcatalog/templates/webcatalog/index.html 2012-03-06 17:02:19 +0000 |
417 | @@ -5,6 +5,12 @@ |
418 | {% block header %}{% trans "Ubuntu Apps Directory" %}{% endblock %} |
419 | {% block search %}{% endblock %} |
420 | |
421 | +{% block head_extra %} |
422 | + <link rel="stylesheet" type="text/css" href="{% url wc-combo %}?light/css/reset.css&light/css/styles.css&css/webcatalog.css&light/css/forms.css&css/carousel.css"/> |
423 | + <script src="{% url wc-combo %}?yui/3.4.0/build/yui/yui-min.js&js/carousel.js"></script> |
424 | +{% endblock %} |
425 | + |
426 | + |
427 | {% block content %} |
428 | |
429 | {% if exhibits %} |
430 | |
431 | === modified file 'src/webcatalog/tests/test_views.py' |
432 | --- src/webcatalog/tests/test_views.py 2012-03-05 17:41:06 +0000 |
433 | +++ src/webcatalog/tests/test_views.py 2012-03-06 17:02:19 +0000 |
434 | @@ -419,17 +419,7 @@ |
435 | |
436 | response = self.client.get(reverse('wc-index')) |
437 | |
438 | - self.assertContains(response, '<div class="exhibit-container', |
439 | - count=1) |
440 | - |
441 | - def test_only_one_exhibit_enabled(self): |
442 | - for i in range(3): |
443 | - self.factory.make_exhibit(published=True) |
444 | - |
445 | - response = self.client.get(reverse('wc-index')) |
446 | - |
447 | - self.assertContains(response, |
448 | - '<div class="exhibit-container enabled">', count=1) |
449 | + self.assertContains(response, '<li class="slide', count=1) |
450 | |
451 | |
452 | class OverviewTestCase(TestCaseWithFactory): |
453 | |
454 | === modified file 'src/webcatalog/views.py' |
455 | --- src/webcatalog/views.py 2012-03-05 17:41:06 +0000 |
456 | +++ src/webcatalog/views.py 2012-03-06 17:02:19 +0000 |
457 | @@ -24,7 +24,7 @@ |
458 | |
459 | import operator |
460 | import os |
461 | -from random import randint |
462 | +from random import shuffle |
463 | from urllib import urlencode |
464 | |
465 | from convoy.combo import combine_files, parse_qs |
466 | @@ -114,13 +114,13 @@ |
467 | def index(request): |
468 | depts = Department.objects.filter(parent=None).order_by('name') |
469 | depts = depts.order_by('name') |
470 | - exhibits = Exhibit.objects.filter(Q(display=True) | |
471 | - Q(display=None, published=True,)) |
472 | + exhibits = list(Exhibit.objects.filter(Q(display=True) | |
473 | + Q(display=None, published=True,))) |
474 | + shuffle(exhibits) |
475 | |
476 | context = RequestContext(request, dict={ |
477 | 'depts': depts, |
478 | 'exhibits': exhibits, |
479 | - 'active': randint(0, max(exhibits.count() - 1, 1)), |
480 | }) |
481 | return render_to_response('webcatalog/index.html', |
482 | context_instance=context) |
483 | @@ -217,7 +217,7 @@ |
484 | content_type = "text/javascript" |
485 | elif fnames[0].endswith(".css"): |
486 | content_type = "text/css" |
487 | - content = combine_files(fnames, os.path.abspath(settings.STATIC_ROOT), |
488 | + content = combine_files(fnames, os.path.abspath(settings.CONVOY_ROOT), |
489 | resource_prefix=settings.MEDIA_URL, rewrite_urls=True) |
490 | # We're turning the generator returned by combine_files into a string |
491 | # here since GZipMiddleware would consume it if not. See Bug #822888. |
Brief screencast of the exhibits widget: http:// people. canonical. com/~anthony/ exhibits_ widget. ogv