Merge lp:~wallyworld/launchpad/infotype-widget-1007984 into lp:launchpad

Proposed by Ian Booth on 2012-06-05
Status: Merged
Merged at revision: 15361
Proposed branch: lp:~wallyworld/launchpad/infotype-widget-1007984
Merge into: lp:launchpad
Diff against target: 274 lines (+71/-28)
5 files modified
lib/lp/app/javascript/choice.js (+4/-4)
lib/lp/bugs/javascript/bug_subscription_portlet.js (+4/-2)
lib/lp/bugs/javascript/information_type_choice.js (+27/-8)
lib/lp/bugs/javascript/tests/test_information_type_choice.html (+2/-0)
lib/lp/bugs/javascript/tests/test_information_type_choice.js (+34/-14)
To merge this branch: bzr merge lp:~wallyworld/launchpad/infotype-widget-1007984
Reviewer Review Type Date Requested Status
Steve Kowalik (community) code 2012-06-05 Approve on 2012-06-05
Review via email: mp+108665@code.launchpad.net

Commit Message

Improve bug info type popup widget - add error display amd progress spinner.

Description of the Change

== Implementation ==

1. Implement the showError and handleError methods on the error handler object.
2. Wire up the spinner.
3. Render both the new value and description test when thepopup widget is clicked and reset back if there is an error.

== Tests ==

Update the relevant yui tests. In particular, add a new test to check that the behaviour when an error occurs is as expected.
Also, the tests as written had an issue in that they were failing to disable the animation on the subscribers portlet. This lead to null exceptions and browser issues when running the tests. So I added code to do the correct thing.

== Lint ==

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/app/javascript/choice.js
  lib/lp/bugs/javascript/bug_subscription_portlet.js
  lib/lp/bugs/javascript/information_type_choice.js
  lib/lp/bugs/javascript/tests/test_information_type_choice.html
  lib/lp/bugs/javascript/tests/test_information_type_choice.js

To post a comment you must log in.
Steve Kowalik (stevenk) wrote :

Looks good. I'm glad some of the bugs are contained within ChoiceSource itself.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/app/javascript/choice.js'
2--- lib/lp/app/javascript/choice.js 2012-06-04 11:41:47 +0000
3+++ lib/lp/app/javascript/choice.js 2012-06-05 08:13:22 +0000
4@@ -2,7 +2,7 @@
5
6 var namespace = Y.namespace('lp.app.choice');
7
8-function hook_up_spinner(widget) {
9+namespace.hook_up_choicesource_spinner = function(widget) {
10 // ChoiceSource makes assumptions about HTML in lazr-js
11 // that don't hold true here, so we need to do our own
12 // spinner icon and clear it when finished.
13@@ -19,7 +19,7 @@
14 icon.addClass('edit');
15 icon.setStyle('bottom', '0px');
16 }, widget, '_uiClearWaiting');
17-}
18+};
19
20 namespace.addBinaryChoice = function(config, resource_uri, attribute) {
21 var widget = new Y.ChoiceSource(config);
22@@ -28,7 +28,7 @@
23 cfg: {
24 patch: attribute,
25 resource: resource_uri}});
26- hook_up_spinner(widget);
27+ namespace.hook_up_choicesource_spinner(widget);
28 widget.render();
29 };
30
31@@ -41,7 +41,7 @@
32 cfg: {
33 patch: attribute,
34 resource: resource_uri}});
35- hook_up_spinner(widget);
36+ namespace.hook_up_choicesource_spinner(widget);
37 widget.on('save', function(e) {
38 var cb = widget.get('contentBox');
39 var value = widget.get('value');
40
41=== modified file 'lib/lp/bugs/javascript/bug_subscription_portlet.js'
42--- lib/lp/bugs/javascript/bug_subscription_portlet.js 2012-02-21 22:46:28 +0000
43+++ lib/lp/bugs/javascript/bug_subscription_portlet.js 2012-06-05 08:13:22 +0000
44@@ -58,7 +58,7 @@
45 /*
46 * Update the text and link at the top of the subscription portlet.
47 */
48-function update_subscription_status() {
49+function update_subscription_status(skip_animation) {
50 var status = Y.one('#current_user_subscription');
51 var span = status.one('span');
52 var whitespace = status.one('span+span');
53@@ -113,7 +113,9 @@
54 }
55 }
56 }
57- Y.lp.anim.green_flash({ node: status }).run();
58+ if(!Y.Lang.isBoolean(skip_animation) || !skip_animation) {
59+ Y.lp.anim.green_flash({ node: status }).run();
60+ }
61 }
62 namespace.update_subscription_status = update_subscription_status;
63
64
65=== modified file 'lib/lp/bugs/javascript/information_type_choice.js'
66--- lib/lp/bugs/javascript/information_type_choice.js 2012-05-30 20:31:37 +0000
67+++ lib/lp/bugs/javascript/information_type_choice.js 2012-06-05 08:13:22 +0000
68@@ -9,10 +9,25 @@
69 var namespace = Y.namespace('lp.bugs.information_type_choice');
70 var information_type_descriptions = {};
71
72-namespace.save_information_type = function(value, lp_client) {
73+// For testing.
74+var skip_animation = false;
75+
76+namespace.save_information_type = function(widget, value, lp_client) {
77 var error_handler = new Y.lp.client.ErrorHandler();
78+ error_handler.showError = function(error_msg) {
79+ Y.lp.app.errors.display_error(
80+ Y.one('#information-type'), error_msg);
81+ };
82+ error_handler.handleError = function(ioId, response) {
83+ var orig_value = LP.cache.bug.information_type;
84+ widget.set('value', orig_value);
85+ update_information_type_description(orig_value);
86+ return false;
87+ };
88 var config = {
89 on: {
90+ start: Y.bind(widget._uiSetWaiting),
91+ end: Y.bind(widget._uiClearWaiting),
92 success: function(id, response) {
93 namespace.information_type_save_success(value);
94 },
95@@ -35,7 +50,6 @@
96 };
97
98 namespace.get_information_type_banner_text = function(value) {
99- console.dir(LP.cache);
100 var fallback_text = "The information on this page is private.";
101 var text_template = "This page contains {info_type} information.";
102
103@@ -45,7 +59,7 @@
104 if (LP.cache.show_information_type_in_ui) {
105 return Y.Lang.substitute(text_template, {'info_type': value});
106 } else {
107- return fallback_text;
108+ return fallback_text;
109 }
110 };
111
112@@ -54,8 +68,7 @@
113 var private_type = (Y.Array.indexOf(LP.cache.private_types, value) >= 0);
114 var subscription_ns = Y.lp.bugs.bugtask_index.portlets.subscription;
115 var privacy_banner = Y.lp.app.banner.privacy.getPrivacyBanner();
116- subscription_ns.update_subscription_status();
117- update_information_type_description(value);
118+ subscription_ns.update_subscription_status(skip_animation);
119 if (private_type) {
120 var banner_text = namespace.get_information_type_banner_text(value);
121 privacy_banner.updateText(banner_text);
122@@ -67,7 +80,9 @@
123 }
124 };
125
126-namespace.setup_information_type_choice = function(privacy_link, lp_client) {
127+namespace.setup_information_type_choice = function(privacy_link, lp_client,
128+ skip_anim) {
129+ skip_animation = skip_anim;
130 Y.Array.each(LP.cache.information_types, function(info_type) {
131 information_type_descriptions[info_type.value] = info_type.description;
132 });
133@@ -81,6 +96,7 @@
134 items: LP.cache.information_types,
135 backgroundColor: '#FFFF99'
136 });
137+ Y.lp.app.choice.hook_up_choicesource_spinner(information_type_edit);
138 information_type_edit.render();
139 information_type_edit.on("save", function(e) {
140 var value = information_type_edit.get('value');
141@@ -89,10 +105,13 @@
142 if (value === 'Private') {
143 value = 'User Data';
144 }
145- namespace.save_information_type(value, lp_client);
146+ update_information_type_description(value);
147+ namespace.save_information_type(
148+ information_type_edit, value, lp_client);
149 });
150 privacy_link.addClass('js-action');
151+ return information_type_edit;
152 };
153 }, "0.1", {"requires": ["base", "oop", "node", "event", "io-base",
154 "lazr.choiceedit", "lp.bugs.bugtask_index",
155- "lp.app.banner.privacy"]});
156+ "lp.app.banner.privacy", "lp.app.choice"]});
157
158=== modified file 'lib/lp/bugs/javascript/tests/test_information_type_choice.html'
159--- lib/lp/bugs/javascript/tests/test_information_type_choice.html 2012-05-16 02:09:30 +0000
160+++ lib/lp/bugs/javascript/tests/test_information_type_choice.html 2012-06-05 08:13:22 +0000
161@@ -28,6 +28,8 @@
162 <script type="text/javascript"
163 src="../../../../../build/js/lp/app/lp.js"></script>
164 <script type="text/javascript"
165+ src="../../../../../build/js/lp/app/choice.js"></script>
166+ <script type="text/javascript"
167 src="../../../../../build/js/lp/app/testing/mockio.js"></script>
168 <script type="text/javascript"
169 src="../../../../../build/js/lp/app/client.js"></script>
170
171=== modified file 'lib/lp/bugs/javascript/tests/test_information_type_choice.js'
172--- lib/lp/bugs/javascript/tests/test_information_type_choice.js 2012-05-30 13:59:24 +0000
173+++ lib/lp/bugs/javascript/tests/test_information_type_choice.js 2012-06-05 08:13:22 +0000
174@@ -25,10 +25,12 @@
175 show_information_type_in_ui: true,
176 private_types: ['Private'],
177 information_types: [
178- {'value': 'Public', 'description': 'Public',
179- 'name': 'Public'},
180- {'value': 'Private', 'description': 'Private',
181- 'name': 'Private'}
182+ {'value': 'Public', 'name': 'Public',
183+ 'description': 'Public Description'},
184+ {'value': 'Private', 'name': 'Private',
185+ 'description': 'Private Description'},
186+ {'value': 'User Data', 'name': 'User Data',
187+ 'description': 'User Data Description'}
188 ]
189 }
190 };
191@@ -39,7 +41,8 @@
192
193 var lp_client = new Y.lp.client.Launchpad();
194 var privacy_link = Y.one('#privacy-link');
195- ns.setup_information_type_choice(privacy_link, lp_client);
196+ this.widget = ns.setup_information_type_choice(
197+ privacy_link, lp_client, true);
198 },
199 tearDown: function () {
200 if (this.fixture !== null) {
201@@ -75,7 +78,7 @@
202 var lp_client = new Y.lp.client.Launchpad({
203 io_provider: mockio
204 });
205- ns.save_information_type('User Data', lp_client);
206+ ns.save_information_type(this.widget, 'User Data', lp_client);
207 Y.Assert.areEqual('/api/devel/bug/1', mockio.last_request.url);
208 Y.Assert.areEqual(
209 'ws.op=transitionToInformationType&' +
210@@ -84,10 +87,6 @@
211 },
212
213 test_information_type_save_success_private: function() {
214- var description_node = Y.one('#information-type-description');
215- Y.Assert.areEqual(
216- 'Everyone can see this information.',
217- description_node.get('text'));
218 var old_func = this._shim_privacy_banner();
219 var hide_flag = false;
220 var update_flag = false;
221@@ -103,7 +102,6 @@
222 Y.Assert.isTrue(body.hasClass('private'));
223 Y.Assert.isTrue(hide_flag);
224 Y.Assert.isTrue(update_flag);
225- Y.Assert.areEqual('Private', description_node.get('text'));
226 this._unshim_privacy_banner(old_func);
227 },
228
229@@ -118,8 +116,6 @@
230 var body = Y.one('body');
231 Y.Assert.isTrue(body.hasClass('public'));
232 Y.Assert.isTrue(flag);
233- var description_node = Y.one('#information-type-description');
234- Y.Assert.areEqual('Public', description_node.get('text'));
235 this._unshim_privacy_banner(old_func);
236 },
237
238@@ -130,12 +126,36 @@
239 '.yui3-ichoicelist-content a[href=#Private]');
240 var orig_save_information_type = ns.save_information_type;
241 var function_called = false;
242- ns.save_information_type = function(value, lp_client) {
243+ ns.save_information_type = function(widget, value, lp_client) {
244 Y.Assert.areEqual(
245 'User Data', value); function_called = true; };
246 private_choice.simulate('click');
247+ var description_node = Y.one('#information-type-description');
248+ Y.Assert.areEqual(
249+ 'User Data Description', description_node.get('text'));
250 Y.Assert.isTrue(function_called);
251 ns.save_information_type = orig_save_information_type;
252+ },
253+
254+ test_information_type_save_error: function() {
255+ var mockio = new Y.lp.testing.mockio.MockIo();
256+ var lp_client = new Y.lp.client.Launchpad({
257+ io_provider: mockio
258+ });
259+ this.widget.set('value', 'User Data');
260+ ns.save_information_type(this.widget, 'User Data', lp_client);
261+ mockio.last_request.respond({
262+ status: 500,
263+ statusText: 'An error occurred'
264+ });
265+ // The original info type value from the cache should have been
266+ // set back into the widget.
267+ Y.Assert.areEqual('Public', this.widget.get('value'));
268+ var description_node = Y.one('#information-type-description');
269+ Y.Assert.areEqual(
270+ 'Public Description', description_node.get('text'));
271+ // The error was displayed.
272+ Y.Assert.isNotNull(Y.one('.yui3-lazr-formoverlay-errors'));
273 }
274 }));
275