Merge lp:~michael.nelson/ubuntu-webcatalog/962140-display-video-demos-pt-2 into lp:ubuntu-webcatalog

Proposed by Michael Nelson
Status: Merged
Approved by: Łukasz Czyżykowski
Approved revision: 126
Merged at revision: 117
Proposed branch: lp:~michael.nelson/ubuntu-webcatalog/962140-display-video-demos-pt-2
Merge into: lp:ubuntu-webcatalog
Diff against target: 180 lines (+116/-4)
5 files modified
src/webcatalog/models/applications.py (+15/-4)
src/webcatalog/static/css/webcatalog.css (+9/-0)
src/webcatalog/templates/webcatalog/application_detail.html (+8/-0)
src/webcatalog/tests/test_models.py (+73/-0)
src/webcatalog/tests/test_views.py (+11/-0)
To merge this branch: bzr merge lp:~michael.nelson/ubuntu-webcatalog/962140-display-video-demos-pt-2
Reviewer Review Type Date Requested Status
Canonical Consumer Applications Hackers Pending
Review via email: mp+104714@code.launchpad.net

Commit message

Add videos to the application detail page.

Description of the change

Overview
========

Adds videos to the application detail page, to look like this:

http://people.canonical.com/~michaeln/tmp/962140-video-iframes.png

Note:
 * The video we have on staging is no longer allowed to be embedded (that's an option set by the author)
 * I've also tweaked the style for the sharing options so that the facebook options are aligned.

`fab test`

To post a comment you must log in.
Revision history for this message
Łukasz Czyżykowski (lukasz-czyzykowski) wrote :

Why using setattr, gettattr, hasattr for media caching instead of just plain dict (self._media_cache = {}). Or other than doing per request cache, maybe it would be better to push that to django cache layer?

126. By Michael Nelson

REFACTOR: update media cache to use a single dict rather than multiple private attributes.

Revision history for this message
Michael Nelson (michael.nelson) wrote :

On Fri, May 4, 2012 at 12:47 PM, Łukasz Czyżykowski
<email address hidden> wrote:
> Why using setattr, gettattr, hasattr for media caching instead of just plain dict (self._media_cache = {}). Or other than doing per request cache, maybe it would be better to push that to django cache layer?

12:02 < noodles> lukasz: +1 for self._media_cache instead, but I think
we'd specifically not want to use the django cache layer as caching
over multiple requests would be bad?
12:02 * noodles updates
12:03 < lukasz> noodles, why?
12:06 < noodles> lukasz: run import_for_pay_apps, then view a specific
app, but it's screenshots haven't updated, or multiple points in the
code need to know about the cache (to clear it during import)
12:06 < noodles> lukasz: I guess the second option isn't so bad.
12:07 < lukasz> noodles, yeah, that would be my only concern, a need
for keeping the cache up to date
12:07 < lukasz> noodles, ok, let's leave it at dict
12:07 < noodles> k
12:12 < noodles> lukasz: pushed with r126

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/webcatalog/models/applications.py'
2--- src/webcatalog/models/applications.py 2012-05-03 09:59:18 +0000
3+++ src/webcatalog/models/applications.py 2012-05-04 12:14:18 +0000
4@@ -114,12 +114,23 @@
5 def __unicode__(self):
6 return u"{0} ({1})".format(self.name, self.package_name)
7
8+ def _get_media(self, media_type):
9+ if not hasattr(self, '_media_cache'):
10+ self._media_cache = {}
11+
12+ if not media_type in self._media_cache:
13+ medias = self.applicationmedia_set.filter(media_type=media_type)
14+ self._media_cache[media_type] = [media.url for media in medias]
15+
16+ return self._media_cache[media_type]
17+
18 @property
19 def screenshots(self):
20- if not hasattr(self, '_screenshots'):
21- qs = self.applicationmedia_set.filter(media_type='screenshot')
22- self._screenshots = [am.url for am in qs]
23- return self._screenshots
24+ return self._get_media('screenshot')
25+
26+ @property
27+ def video_iframe_urls(self):
28+ return self._get_media('video')
29
30 @property
31 def categories_set(self):
32
33=== modified file 'src/webcatalog/static/css/webcatalog.css'
34--- src/webcatalog/static/css/webcatalog.css 2012-04-19 23:05:19 +0000
35+++ src/webcatalog/static/css/webcatalog.css 2012-05-04 12:14:18 +0000
36@@ -58,6 +58,9 @@
37 .share {
38 padding: 16px;
39 }
40+.share .fb-like {
41+ height: 24px;
42+}
43 .description {
44 padding: 42px 16px;
45 font-size: 14px;
46@@ -427,3 +430,9 @@
47 margin: 32px;
48 color: #888;
49 }
50+
51+div.videos iframe {
52+ width: 100%;
53+ height: 225px;
54+ margin: 16px;
55+}
56
57=== modified file 'src/webcatalog/templates/webcatalog/application_detail.html'
58--- src/webcatalog/templates/webcatalog/application_detail.html 2012-04-20 18:22:42 +0000
59+++ src/webcatalog/templates/webcatalog/application_detail.html 2012-05-04 12:14:18 +0000
60@@ -119,6 +119,14 @@
61 {% endif %}
62 </table>
63 </div>
64+ {% if application.video_iframe_urls %}
65+ <div class="videos">
66+ <h3>Videos</h3>
67+ {% for iframe_url in application.video_iframe_urls %}
68+ <iframe src="{{ iframe_url }}"></iframe>
69+ {% endfor %}
70+ </div>
71+ {% endif %}
72 <div class="share">
73 {% include "webcatalog/twitter_share_snippet.html" %}
74 {% include "webcatalog/googleplus_share_snippet.html" %}
75
76=== modified file 'src/webcatalog/tests/test_models.py'
77--- src/webcatalog/tests/test_models.py 2012-04-05 01:09:37 +0000
78+++ src/webcatalog/tests/test_models.py 2012-05-04 12:14:18 +0000
79@@ -121,6 +121,79 @@
80 self.assertTrue(icon_url.startswith('/site_media/'))
81 self.assertTrue('ubuntu-cof' in icon_url)
82
83+ def test_screenshots(self):
84+ app = self.factory.make_application()
85+ app.applicationmedia_set.create(
86+ media_type='screenshot',
87+ url='http://example.com/screenshot1.png')
88+ app.applicationmedia_set.create(
89+ media_type='screenshot',
90+ url='http://example.com/screenshot2.png')
91+ app.applicationmedia_set.create(
92+ media_type='video',
93+ url='http://example.com/video.m4v')
94+
95+ urls = app.screenshots
96+
97+ self.assertEqual([
98+ 'http://example.com/screenshot1.png',
99+ 'http://example.com/screenshot2.png',
100+ ],
101+ urls)
102+
103+ def test_screenshots_cached(self):
104+ # The db isn't hit if _screenshots is already
105+ # cached.
106+ app = self.factory.make_application()
107+ app.applicationmedia_set.create(
108+ media_type='screenshot',
109+ url='http://example.com/screenshot1.png')
110+ app.screenshots
111+ app.applicationmedia_set.create(
112+ media_type='screenshot',
113+ url='http://example.com/screenshot2.png')
114+
115+ self.assertEqual([
116+ 'http://example.com/screenshot1.png',
117+ ], app.screenshots)
118+
119+ def test_video_iframes_urls(self):
120+ app = self.factory.make_application()
121+ app.applicationmedia_set.create(
122+ media_type='video',
123+ url='http://example.com/video1.m4v')
124+ app.applicationmedia_set.create(
125+ media_type='video',
126+ url='http://example.com/video2.m4v')
127+ app.applicationmedia_set.create(
128+ media_type='screenshot',
129+ url='http://example.com/screenshot.png')
130+
131+ urls = app.video_iframe_urls
132+
133+ self.assertEqual([
134+ 'http://example.com/video1.m4v',
135+ 'http://example.com/video2.m4v',
136+ ],
137+ urls)
138+
139+ def test_video_iframes_urls_cached(self):
140+ app = self.factory.make_application()
141+ app.applicationmedia_set.create(
142+ media_type='video',
143+ url='http://example.com/video1.m4v')
144+ app.video_iframe_urls
145+ app.applicationmedia_set.create(
146+ media_type='video',
147+ url='http://example.com/video2.m4v')
148+
149+ urls = app.video_iframe_urls
150+
151+ self.assertEqual([
152+ 'http://example.com/video1.m4v',
153+ ],
154+ urls)
155+
156
157 class DepartmentTestCase(TestCaseWithFactory):
158 def test_crumbs_no_parent(self):
159
160=== modified file 'src/webcatalog/tests/test_views.py'
161--- src/webcatalog/tests/test_views.py 2012-04-20 18:22:42 +0000
162+++ src/webcatalog/tests/test_views.py 2012-05-04 12:14:18 +0000
163@@ -366,6 +366,17 @@
164
165 self.assertNotContains(response, 'Hardware requirements')
166
167+ def test_videos_displayed(self):
168+ app = self.factory.make_application()
169+ app.applicationmedia_set.create(
170+ media_type="video",
171+ url="http://example.com/video_iframe.html")
172+
173+ response = self.client.get(self.get_app_details_url(app))
174+
175+ self.assertContains(response,
176+ '<iframe src="http://example.com/video_iframe.html"')
177+
178
179 class ApplicationDetailNoSeriesTestCase(TestCaseWithFactory):
180 def test_renders_latest(self):

Subscribers

People subscribed via source and target branches