Merge lp:~michael.nelson/ubuntu-webcatalog/788207-paginator into lp:ubuntu-webcatalog

Proposed by Michael Nelson
Status: Merged
Approved by: Łukasz Czyżykowski
Approved revision: 70
Merged at revision: 53
Proposed branch: lp:~michael.nelson/ubuntu-webcatalog/788207-paginator
Merge into: lp:ubuntu-webcatalog
Diff against target: 232 lines (+101/-26)
7 files modified
src/webcatalog/static/css/webcatalog.css (+3/-0)
src/webcatalog/templates/webcatalog/application_detail.html (+25/-0)
src/webcatalog/templates/webcatalog/application_review_list.html (+1/-16)
src/webcatalog/templates/webcatalog/application_review_list_snippet.html (+18/-0)
src/webcatalog/tests/test_views.py (+33/-1)
src/webcatalog/utilities.py (+10/-1)
src/webcatalog/views.py (+11/-8)
To merge this branch: bzr merge lp:~michael.nelson/ubuntu-webcatalog/788207-paginator
Reviewer Review Type Date Requested Status
Canonical ISD hackers Pending
Review via email: mp+75556@code.launchpad.net

Commit message

Load reviews snippet via ajax and add to details page.

Description of the change

Overview
========
Contrary to the name, this doesn't add pagination for the reviews - that can wait :), instead it adds the ajax reviews to the app details page.

Some points:
 * I removed the caching on the reviews view and added it to the rnr api call - so that we can provide different responses with the one view for normal and json requests.
 * I'm pulling in the YUI components from the local server (STATIC_URL) rather than from yui (I'll land the YUI code in the following branch)[1]
 * Using just io-base and node-base seems to result in 14 requests - I'm assuming we should update to use a combo loader (actually, I'll check to see if there's standard combos already provided)

Test: `fab bootstrap && fab test`

[1] https://code.launchpad.net/~michael.nelson/ubuntu-webcatalog/788207-add-YUI-resources/+merge/75695

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
=== modified file 'src/webcatalog/static/css/webcatalog.css'
--- src/webcatalog/static/css/webcatalog.css 2011-09-15 10:53:40 +0000
+++ src/webcatalog/static/css/webcatalog.css 2011-09-16 09:53:23 +0000
@@ -220,6 +220,9 @@
220 margin: 0;220 margin: 0;
221 float: none;221 float: none;
222}222}
223.reviews {
224 padding: 16px;
225}
223.review {226.review {
224 margin: 8px 8px 16px 8px;227 margin: 8px 8px 16px 8px;
225}228}
226229
=== modified file 'src/webcatalog/templates/webcatalog/application_detail.html'
--- src/webcatalog/templates/webcatalog/application_detail.html 2011-09-15 10:53:40 +0000
+++ src/webcatalog/templates/webcatalog/application_detail.html 2011-09-16 09:53:23 +0000
@@ -4,6 +4,24 @@
44
5{% block title %}Application {{ application.name }}{% endblock %}5{% block title %}Application {{ application.name }}{% endblock %}
6{% block header %}Details for {{ application.name }}{% endblock %}6{% block header %}Details for {{ application.name }}{% endblock %}
7{% block head_extra %}
8{{ block.super }}
9<script src="{{ STATIC_URL }}yui/3.4.0/build/yui/yui-min.js"></script>
10<script>
11YUI().use('io-base', 'node-base', function (Y) {
12 function complete(id, obj){
13 var reviews_html = obj.responseText;
14 var reviews_div = Y.one('#reviews_placeholder');
15 reviews_div.set("innerHTML", reviews_html);
16 };
17 Y.on('io:complete', complete, Y);
18
19 // XXX michaeln 2011-09-16 bug=851660 Autoload further batches of results.
20 var uri = "{% url wc-package-reviews application.distroseries.code_name application.package_name %}";
21 Y.io(uri);
22});
23</script>
24{% endblock %}
725
8{% block content %}26{% block content %}
9 {% include "webcatalog/breadcrumbs_snippet.html" %}27 {% include "webcatalog/breadcrumbs_snippet.html" %}
@@ -56,5 +74,12 @@
56 </tr>74 </tr>
57 </table>75 </table>
58 </div>76 </div>
77 <div class="reviews">
78 <h2>{% trans "Reviews" %}</h2>
79 <div id="reviews_placeholder">
80 <a href="{% url wc-package-reviews application.distroseries.code_name application.package_name %}">
81 {% blocktrans %}View the reviews for this app{% endblocktrans %}</a>
82 </div>
83 </div>
59 </div>84 </div>
60{% endblock %}85{% endblock %}
6186
=== modified file 'src/webcatalog/templates/webcatalog/application_review_list.html'
--- src/webcatalog/templates/webcatalog/application_review_list.html 2011-09-15 10:53:40 +0000
+++ src/webcatalog/templates/webcatalog/application_review_list.html 2011-09-16 09:53:23 +0000
@@ -19,21 +19,6 @@
19 <h2>{{ application.name }}</h2>19 <h2>{{ application.name }}</h2>
20 <p>{{ application.comment }}</p>20 <p>{{ application.comment }}</p>
21 </div>21 </div>
22 {% for review in reviews %}22 {% include "webcatalog/application_review_list_snippet.html" %}
23 <div class="review">
24 <div class="meta">
25 <strong>{{ review.reviewer_displayname }}</strong>,
26 {{ review.date_created|slice:":10" }}
27 </div>
28 {% rating_summary review.rating %}
29 <strong>{{ review.summary }}</strong>
30 <p>{{ review.review_text }}</p>
31 <p class="usefulness">
32 {% blocktrans with favorable=review.usefulness_favorable total=review.usefulness_total %}
33 {{ favorable }} out of {{ total }} found this review helpful.
34 {% endblocktrans %}
35 </p>
36 </div>
37 {% endfor %}
38 </div>23 </div>
39{% endblock %}24{% endblock %}
4025
=== added file 'src/webcatalog/templates/webcatalog/application_review_list_snippet.html'
--- src/webcatalog/templates/webcatalog/application_review_list_snippet.html 1970-01-01 00:00:00 +0000
+++ src/webcatalog/templates/webcatalog/application_review_list_snippet.html 2011-09-16 09:53:23 +0000
@@ -0,0 +1,18 @@
1{% load i18n %}
2{% load webcatalog %}
3{% for review in reviews %}
4 <div class="review">
5 <div class="meta">
6 <strong>{{ review.reviewer_displayname }}</strong>,
7 {{ review.date_created|slice:":10" }}
8 </div>
9 {% rating_summary review.rating %}
10 <strong>{{ review.summary }}</strong>
11 <p>{{ review.review_text }}</p>
12 <p class="usefulness">
13 {% blocktrans with favorable=review.usefulness_favorable total=review.usefulness_total %}
14 {{ favorable }} out of {{ total }} found this review helpful.
15 {% endblocktrans %}
16 </p>
17 </div>
18{% endfor %}
019
=== modified file 'src/webcatalog/tests/test_views.py'
--- src/webcatalog/tests/test_views.py 2011-09-15 10:53:40 +0000
+++ src/webcatalog/tests/test_views.py 2011-09-16 09:53:23 +0000
@@ -116,6 +116,15 @@
116116
117 self.assertContains(response, 'action="apt://pkgfoo"')117 self.assertContains(response, 'action="apt://pkgfoo"')
118118
119 def test_link_to_package_reviews(self):
120 response, app = self.get_app_and_response()
121
122 self.assertContains(response, '<a href="{0}"'.format(
123 reverse('wc-package-reviews', args=[
124 app.distroseries.code_name,
125 app.package_name,
126 ])))
127
119 def test_button_for_non_puchase_app(self):128 def test_button_for_non_puchase_app(self):
120 response, app = self.get_app_and_response()129 response, app = self.get_app_and_response()
121130
@@ -515,7 +524,10 @@
515 get_reviews_fn = 'rnrclient.RatingsAndReviewsAPI.get_reviews'524 get_reviews_fn = 'rnrclient.RatingsAndReviewsAPI.get_reviews'
516 self.get_reviews_patcher = patch(get_reviews_fn)525 self.get_reviews_patcher = patch(get_reviews_fn)
517 self.mock_get_reviews = self.get_reviews_patcher.start()526 self.mock_get_reviews = self.get_reviews_patcher.start()
518 self.mock_get_reviews.return_value = []527 eg_review = ReviewDetails.from_dict(
528 dict(package_name='foo', summary='foo summary',
529 rating='3.5'))
530 self.mock_get_reviews.return_value = [eg_review]
519531
520 def tearDown(self):532 def tearDown(self):
521 self.get_reviews_patcher.stop()533 self.get_reviews_patcher.stop()
@@ -566,5 +578,25 @@
566578
567 self.assertTemplateUsed(579 self.assertTemplateUsed(
568 response, 'webcatalog/application_review_list.html')580 response, 'webcatalog/application_review_list.html')
581 self.assertTemplateUsed(
582 response, 'webcatalog/application_review_list_snippet.html')
583 self.assertContains(response, 'review_summary1')
584 self.assertContains(response, 'review_summary2')
585
586 def test_renders_reviews_only_for_json_request(self):
587 app = self.factory.make_application()
588 self.mock_get_reviews.return_value = [
589 self.make_review_details(summary='review_summary1'),
590 self.make_review_details(summary='review_summary2'),
591 ]
592
593 response = self.client.get(reverse('wc-package-reviews',
594 args=[app.distroseries.code_name, app.package_name]),
595 HTTP_X_REQUESTED_WITH='XMLHttpRequest')
596
597 self.assertTemplateNotUsed(
598 response, 'webcatalog/application_review_list.html')
599 self.assertTemplateUsed(
600 response, 'webcatalog/application_review_list_snippet.html')
569 self.assertContains(response, 'review_summary1')601 self.assertContains(response, 'review_summary1')
570 self.assertContains(response, 'review_summary2')602 self.assertContains(response, 'review_summary2')
571603
=== modified file 'src/webcatalog/utilities.py'
--- src/webcatalog/utilities.py 2011-09-15 08:58:19 +0000
+++ src/webcatalog/utilities.py 2011-09-16 09:53:23 +0000
@@ -34,6 +34,7 @@
34from httplib2 import ServerNotFoundError34from httplib2 import ServerNotFoundError
3535
36from django.conf import settings36from django.conf import settings
37from django.core.cache import cache
3738
38from lazr.restfulclient.authorize import BasicHttpAuthorizer39from lazr.restfulclient.authorize import BasicHttpAuthorizer
39from lazr.restfulclient.authorize.oauth import OAuthAuthorizer40from lazr.restfulclient.authorize.oauth import OAuthAuthorizer
@@ -95,8 +96,16 @@
95 return RatingsAndReviewsAPI(service_root=settings.RNR_SERVICE_ROOT)96 return RatingsAndReviewsAPI(service_root=settings.RNR_SERVICE_ROOT)
9697
97 def get_reviews_for_package(self, package_name, distroseries, page=1):98 def get_reviews_for_package(self, package_name, distroseries, page=1):
98 return self.rnr_api.get_reviews(packagename=package_name, 99 key = 'get_reviews_for_package-{0}-{1}-{2}'.format(
100 package_name, distroseries, page)
101 cached_reviews = cache.get(key)
102 if cached_reviews is not None:
103 return cached_reviews
104
105 fresh_reviews = self.rnr_api.get_reviews(packagename=package_name,
99 distroseries=distroseries, page=page)106 distroseries=distroseries, page=page)
107 cache.set(key, fresh_reviews, settings.REVIEWS_CACHE_TIMEOUT)
108 return fresh_reviews
100109
101 def _fake_validate_token(self, token, openid_identifier, signature):110 def _fake_validate_token(self, token, openid_identifier, signature):
102 """ This is a version of validate_token that gets the111 """ This is a version of validate_token that gets the
103112
=== modified file 'src/webcatalog/views.py'
--- src/webcatalog/views.py 2011-09-15 11:25:35 +0000
+++ src/webcatalog/views.py 2011-09-16 09:53:23 +0000
@@ -35,7 +35,6 @@
35 render_to_response,35 render_to_response,
36 )36 )
37from django.template import RequestContext37from django.template import RequestContext
38from django.views.decorators.cache import cache_page
3938
40from webcatalog.models import (39from webcatalog.models import (
41 Application,40 Application,
@@ -179,15 +178,19 @@
179 request, atts))178 request, atts))
180179
181180
182@cache_page(settings.REVIEWS_CACHE_TIMEOUT)
183def application_reviews(request, package_name, distro, page=1):181def application_reviews(request, package_name, distro, page=1):
184 app = get_object_or_404(Application, package_name=package_name,182 app = get_object_or_404(Application, package_name=package_name,
185 distroseries__code_name=distro)183 distroseries__code_name=distro)
186 # XXX michaeln 2011-09-15 Don't request reviews for all languages.184 # XXX michaeln 2011-09-15 bug=851662 Better review language options.
187 reviews = WebServices().get_reviews_for_package(package_name, 185 reviews = WebServices().get_reviews_for_package(package_name,
188 distroseries=distro, page=page)186 distroseries=distro, page=page)
189 return render_to_response(187
190 'webcatalog/application_review_list.html', RequestContext(188 context = dict(application=app, reviews=reviews)
191 request, dict(189 if request.is_ajax():
192 application=app, distroseries=distro, reviews=reviews,190 template = 'webcatalog/application_review_list_snippet.html'
193 breadcrumbs=app.crumbs())))191 else:
192 context['distroseries'] = distro
193 context['breadcrumbs'] = app.crumbs()
194 template = 'webcatalog/application_review_list.html'
195
196 return render_to_response(template, RequestContext(request, context))

Subscribers

People subscribed via source and target branches