Merge lp:~rharding/launchpad/lp_cache_update into lp:launchpad

Proposed by Richard Harding on 2012-09-13
Status: Merged
Approved by: j.c.sackett on 2012-09-13
Approved revision: no longer in the source branch.
Merged at revision: 15960
Proposed branch: lp:~rharding/launchpad/lp_cache_update
Merge into: lp:launchpad
Diff against target: 683 lines (+176/-123)
14 files modified
lib/lp/app/browser/informationtype.py (+7/-8)
lib/lp/app/javascript/information_type.js (+52/-43)
lib/lp/app/javascript/tests/test_information_type.js (+24/-13)
lib/lp/bugs/browser/bugtarget.py (+5/-8)
lib/lp/bugs/browser/tests/test_bugtarget_filebug.py (+4/-4)
lib/lp/bugs/browser/tests/test_bugview.py (+1/-1)
lib/lp/bugs/javascript/filebug.js (+14/-12)
lib/lp/bugs/javascript/tests/test_buglisting.html (+4/-0)
lib/lp/bugs/javascript/tests/test_filebug.html (+3/-0)
lib/lp/bugs/javascript/tests/test_filebug.js (+20/-9)
lib/lp/code/javascript/branch.information_type_choice.js (+3/-1)
lib/lp/code/javascript/tests/test_information_type_choice.js (+19/-11)
lib/lp/registry/browser/product.py (+4/-13)
lib/lp/registry/enums.py (+16/-0)
To merge this branch: bzr merge lp:~rharding/launchpad/lp_cache_update
Reviewer Review Type Date Requested Status
j.c.sackett (community) 2012-09-13 Approve on 2012-09-13
Review via email: mp+124217@code.launchpad.net

Commit Message

Update the information type data in the LP cache.

Description of the Change

= Summary =

Part of adding the privacy banner and the information type choice widgets to
the other parts of Launchpad requires copying a bunch of code.

This restructures the LP.cache data and creates a helper to make it simpler
and more reusable.

The eventual goal is to build on this and make the information type choice
widget more of a event driven widget that others can listen to, but that work
is not in this first step.

== Pre Implementation ==

Talked with Aaron on ideas for simplifying and what data is required.

== Implementation Notes ==

We remove the separate cache data for information type data and the list of
private types. We restructure the information type data to be an object vs a
list so that we can key in on the value and allow for finding data without
looping unless absolutely required.

The method that creates the LP.cache data writes out a new is_private property
that code can use to check if a specific information_type_data is private or
not.

We also add a helper method that will take the new object and generate the
list of data that the choicesource code wants to see.

There's a drive by of trying to s/namespace/ns to help aid in line length,
wrapping, and readability.

To post a comment you must log in.
j.c.sackett (jcsackett) wrote :

This looks good, with understanding that json_dump_information_types should be moved into the registry modules.

Thanks, Rick.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/app/browser/informationtype.py'
2--- lib/lp/app/browser/informationtype.py 2012-07-26 05:56:54 +0000
3+++ lib/lp/app/browser/informationtype.py 2012-09-14 01:06:22 +0000
4@@ -8,20 +8,19 @@
5
6 from lazr.restful.interfaces import IJSONRequestCache
7
8-from lp.registry.enums import PRIVATE_INFORMATION_TYPES
9+from lp.registry.enums import (
10+ json_dump_information_types,
11+ PRIVATE_INFORMATION_TYPES
12+ )
13
14
15 class InformationTypePortletMixin:
16
17 def initialize(self):
18 cache = IJSONRequestCache(self.request)
19- cache.objects['information_type_data'] = [
20- {'value': term.name, 'description': term.description,
21- 'name': term.title,
22- 'description_css_class': 'choice-description'}
23- for term in self.context.getAllowedInformationTypes(self.user)]
24- cache.objects['private_types'] = [
25- type.name for type in PRIVATE_INFORMATION_TYPES]
26+ json_dump_information_types(
27+ cache,
28+ self.context.getAllowedInformationTypes(self.user))
29
30 @property
31 def information_type(self):
32
33=== modified file 'lib/lp/app/javascript/information_type.js'
34--- lib/lp/app/javascript/information_type.js 2012-09-10 13:57:38 +0000
35+++ lib/lp/app/javascript/information_type.js 2012-09-14 01:06:22 +0000
36@@ -6,7 +6,7 @@
37
38 YUI.add('lp.app.information_type', function(Y) {
39
40-var namespace = Y.namespace('lp.app.information_type');
41+var ns = Y.namespace('lp.app.information_type');
42
43 // For testing.
44 var skip_animation = false;
45@@ -24,7 +24,7 @@
46 * @param lp_client
47 * @param validate_change
48 */
49-namespace.save_information_type = function(widget, initial_value, value,
50+ns.save_information_type = function(widget, initial_value, value,
51 lp_client, context,
52 subscribers_list, validate_change) {
53 var error_handler = new Y.lp.client.FormErrorHandler();
54@@ -35,16 +35,16 @@
55 error_handler.handleError = function(ioId, response) {
56 if( response.status === 400
57 && response.statusText === 'Bug Visibility') {
58- namespace._confirm_information_type_change(
59+ ns._confirm_information_type_change(
60 widget, initial_value, lp_client, context,
61 subscribers_list);
62 return true;
63 }
64- var orig_value = namespace.information_type_value_from_key(
65+ var orig_value = ns.information_type_value_from_key(
66 context.information_type, 'name', 'value');
67 widget.set('value', orig_value);
68 widget._showFailed();
69- namespace.update_privacy_portlet(orig_value);
70+ ns.update_privacy_portlet(orig_value);
71 return false;
72 };
73 var submit_url = document.URL + "/+secrecy";
74@@ -78,7 +78,7 @@
75 {
76 result_data = Y.JSON.parse(response.responseText);
77 }
78- namespace.information_type_save_success(
79+ ns.information_type_save_success(
80 widget, context, value, subscribers_list, result_data);
81 Y.lp.client.display_notifications(
82 response.getResponseHeader('X-Lazr-Notifications'));
83@@ -91,18 +91,16 @@
84
85 var get_information_type_banner_text = function(value) {
86 var text_template = "This page contains {info_type} information.";
87- var info_type = namespace.information_type_value_from_key(
88- value, 'value', 'name');
89+ var info_type = ns.information_type_value_from_key(value, 'value', 'name');
90 return Y.Lang.sub(text_template, {'info_type': info_type});
91 };
92
93-namespace.information_type_save_success = function(widget, context, value,
94+ns.information_type_save_success = function(widget, context, value,
95 subscribers_list,
96 subscribers_data) {
97 context.information_type =
98- namespace.information_type_value_from_key(
99- value, 'value', 'name');
100- namespace.update_privacy_banner(value);
101+ ns.information_type_value_from_key(value, 'value', 'name');
102+ ns.update_privacy_banner(value);
103 widget._showSucceeded();
104 if (Y.Lang.isObject(subscribers_data)) {
105 var subscribers = subscribers_data.subscription_data;
106@@ -116,8 +114,8 @@
107 }
108 }
109 if (Y.Lang.isValue(subscribers_list)){
110- var ns = Y.lp.bugs.bugtask_index.portlets.subscription;
111- ns.update_subscription_status(skip_animation);
112+ var subscription_ns = Y.lp.bugs.bugtask_index.portlets.subscription;
113+ subscription_ns.update_subscription_status(skip_animation);
114 }
115 };
116
117@@ -131,13 +129,13 @@
118 * @param lp_client
119 * @private
120 */
121-namespace._confirm_information_type_change = function(widget, initial_value,
122+ns._confirm_information_type_change = function(widget, initial_value,
123 lp_client, context,
124 subscribers_list) {
125 var value = widget.get('value');
126 var do_save = function() {
127- namespace.update_privacy_portlet(value);
128- namespace.save_information_type(
129+ ns.update_privacy_portlet(value);
130+ ns.save_information_type(
131 widget, initial_value, value, lp_client, context, subscribers_list,
132 false);
133 };
134@@ -145,7 +143,7 @@
135 // change while the confirmation dialog is showing.
136 var new_value = widget.get('value');
137 widget.set('value', initial_value);
138- namespace.update_privacy_portlet(initial_value);
139+ ns.update_privacy_portlet(initial_value);
140 var confirm_text_template = [
141 '<p class="block-sprite large-warning">',
142 ' You are about to mark this bug as ',
143@@ -156,14 +154,13 @@
144 ' <strong>Please confirm you really want to do this.</strong>',
145 '</p>'
146 ].join('');
147- var title = namespace.information_type_value_from_key(
148- value, 'value', 'name');
149+ var title = ns.information_type_value_from_key(value, 'value', 'name');
150 var confirm_text = Y.Lang.sub(confirm_text_template,
151 {information_type: title});
152 var co = new Y.lp.app.confirmationoverlay.ConfirmationOverlay({
153 submit_fn: function() {
154 widget.set('value', new_value);
155- namespace.update_privacy_portlet(new_value);
156+ ns.update_privacy_portlet(new_value);
157 do_save();
158 },
159 form_content: confirm_text,
160@@ -173,20 +170,23 @@
161 co.show();
162 };
163
164-namespace.setup_information_type_choice = function(privacy_link, lp_client,
165+ns.setup_information_type_choice = function(privacy_link, lp_client,
166 context, subscribers_list,
167 skip_anim) {
168 skip_animation = skip_anim;
169- var initial_value = namespace.information_type_value_from_key(
170+ var initial_value = ns.information_type_value_from_key(
171 context.information_type, 'name', 'value');
172 var information_type_value = Y.one('#information-type');
173+ var choice_list = ns.information_type_to_choicesource(
174+ LP.cache.information_type_data);
175+
176 var information_type_edit = new Y.ChoiceSource({
177 editicon: privacy_link,
178 contentBox: Y.one('#privacy'),
179 value_location: information_type_value,
180 value: initial_value,
181 title: "Change information type",
182- items: LP.cache.information_type_data,
183+ items: choice_list,
184 backgroundColor: '#FFFF99',
185 flashEnabled: false
186 });
187@@ -194,8 +194,8 @@
188 information_type_edit.render();
189 information_type_edit.on("save", function(e) {
190 var value = information_type_edit.get('value');
191- namespace.update_privacy_portlet(value);
192- namespace.save_information_type(
193+ ns.update_privacy_portlet(value);
194+ ns.save_information_type(
195 information_type_edit, initial_value, value, lp_client, context,
196 subscribers_list, true);
197 });
198@@ -206,22 +206,33 @@
199 /**
200 * Lookup the information_type property, keyed on the named value.
201 *
202+ * We might want to find based on the name Public or the value PUBLIC so we
203+ * allow for the user to request what cache field to search on.
204+ *
205 * @param cache_key_value the key value to lookup
206 * @param key_property_name the key property name used to access the key value
207 * @param value_property_name the value property name
208 * @return {*}
209 */
210-namespace.information_type_value_from_key = function(cache_key_value,
211- key_property_name,
212- value_property_name) {
213- var data = null;
214- Y.Array.some(LP.cache.information_type_data, function(info_type) {
215- if (info_type[key_property_name] === cache_key_value) {
216- data = info_type[value_property_name];
217- return true;
218+ns.information_type_value_from_key = function(cache_value,
219+ cache_field,
220+ data_field) {
221+ var cache = LP.cache.information_type_data;
222+ for (var key in cache) {
223+ if (cache[key][cache_field] === cache_value) {
224+ return cache[key][data_field];
225 }
226- return false;
227- });
228+ }
229+};
230+
231+
232+ns.information_type_to_choicesource = function (cache) {
233+ var data = [];
234+ for (var key in cache) {
235+ data.push(cache[key]);
236+ }
237+ // We need to order data based on the order attribute.
238+ data.sort(function(a, b) { return a.order - b.order; });
239 return data;
240 };
241
242@@ -230,16 +241,15 @@
243 *
244 * @param value
245 */
246-namespace.update_privacy_portlet = function(value) {
247- var description = namespace.information_type_value_from_key(
248+ns.update_privacy_portlet = function(value) {
249+ var description = ns.information_type_value_from_key(
250 value, 'value', 'description');
251 var desc_node = Y.one('#information-type-description');
252 if (Y.Lang.isValue(desc_node)) {
253 desc_node.set('text', description);
254 }
255 var summary = Y.one('#information-type-summary');
256- var private_type =
257- Y.Array.indexOf(LP.cache.private_types, value) >= 0;
258+ var private_type = LP.cache.information_type_data[value].is_private;
259 if (private_type) {
260 summary.replaceClass('public', 'private');
261 } else {
262@@ -252,11 +262,10 @@
263 *
264 * @param value
265 */
266-namespace.update_privacy_banner = function(value) {
267+ns.update_privacy_banner = function(value) {
268 var body = Y.one('body');
269 var privacy_banner = Y.lp.app.banner.privacy.getPrivacyBanner();
270- var private_type =
271- Y.Array.indexOf(LP.cache.private_types, value) >= 0;
272+ var private_type = LP.cache.information_type_data[value].is_private;
273 if (private_type) {
274 body.replaceClass('public', 'private');
275 var banner_text = get_information_type_banner_text(value);
276
277=== modified file 'lib/lp/app/javascript/tests/test_information_type.js'
278--- lib/lp/app/javascript/tests/test_information_type.js 2012-09-10 21:02:05 +0000
279+++ lib/lp/app/javascript/tests/test_information_type.js 2012-09-14 01:06:22 +0000
280@@ -22,17 +22,28 @@
281 information_type: 'Public',
282 self_link: '/bug/1'
283 },
284- private_types: ['PROPRIETARY', 'USERDATA'],
285- information_type_data: [
286- {'value': 'PUBLIC', 'name': 'Public',
287- 'description': 'Public Description'},
288- {'value': 'PUBLICSECURITY', 'name': 'Public Security',
289- 'description': 'Public Security Description'},
290- {'value': 'PROPRIETARY', 'name': 'Proprietary',
291- 'description': 'Private Description'},
292- {'value': 'USERDATA', 'name': 'Private',
293- 'description': 'Private Description'}
294- ]
295+ information_type_data: {
296+ PUBLIC: {
297+ value: 'PUBLIC', name: 'Public',
298+ is_private: false, order: 1,
299+ description: 'Public Description'
300+ },
301+ PUBLICSECURITY: {
302+ value: 'PUBLICSECURITY', name: 'Public Security',
303+ is_private: false, order: 2,
304+ description: 'Public Security Description'
305+ },
306+ PROPRIETARY: {
307+ value: 'PROPRIETARY', name: 'Proprietary',
308+ is_private: true, order: 3,
309+ description: 'Private Description'
310+ },
311+ USERDATA: {
312+ value: 'USERDATA', name: 'Private',
313+ is_private: true, order: 4,
314+ description: 'Private Description'
315+ }
316+ }
317 }
318 };
319 this.fixture = Y.one('#fixture');
320@@ -145,7 +156,7 @@
321 this._unshim_privacy_banner(old_func);
322 },
323
324- // Setting a private type hides the privacy banner.
325+ // Setting a public type hides the privacy banner.
326 test_information_type_save_success_public: function() {
327 this.makeWidget();
328 var old_func = this._shim_privacy_banner();
329@@ -156,7 +167,7 @@
330 var summary = Y.one('#information-type-summary');
331 summary.replaceClass('public', 'private');
332
333- ns.information_type_save_success(this.widget, 'PUBLIC');
334+ ns.information_type_save_success(this.widget, 'PUBLIC', 'PUBLIC');
335 var body = Y.one('body');
336 Y.Assert.isTrue(body.hasClass('public'));
337 Y.Assert.isTrue(flag);
338
339=== modified file 'lib/lp/bugs/browser/bugtarget.py'
340--- lib/lp/bugs/browser/bugtarget.py 2012-08-21 04:04:47 +0000
341+++ lib/lp/bugs/browser/bugtarget.py 2012-09-14 01:06:22 +0000
342@@ -116,6 +116,7 @@
343 ProductPrivateBugsMixin,
344 )
345 from lp.registry.enums import (
346+ json_dump_information_types,
347 InformationType,
348 PRIVATE_INFORMATION_TYPES,
349 PUBLIC_INFORMATION_TYPES,
350@@ -259,17 +260,13 @@
351 # the form is rendered during LaunchpadFormView's initialize()
352 # when an action is invokved.
353 cache = IJSONRequestCache(self.request)
354- cache.objects['private_types'] = [
355- type.name for type in PRIVATE_INFORMATION_TYPES]
356 cache.objects['bug_private_by_default'] = (
357 self.context.pillar.getDefaultBugInformationType() in
358 PRIVATE_INFORMATION_TYPES)
359- cache.objects['information_type_data'] = [
360- {'value': term.name, 'description': term.description,
361- 'name': term.title,
362- 'description_css_class': 'choice-description'}
363- for term in
364- self.context.pillar.getAllowedBugInformationTypes()]
365+ json_dump_information_types(
366+ cache,
367+ self.context.pillar.getAllowedBugInformationTypes())
368+
369 bugtask_status_data = vocabulary_to_choice_edit_items(
370 BugTaskStatus, include_description=True, css_class_prefix='status',
371 excluded_items=[
372
373=== modified file 'lib/lp/bugs/browser/tests/test_bugtarget_filebug.py'
374--- lib/lp/bugs/browser/tests/test_bugtarget_filebug.py 2012-08-29 03:19:38 +0000
375+++ lib/lp/bugs/browser/tests/test_bugtarget_filebug.py 2012-09-14 01:06:22 +0000
376@@ -28,6 +28,7 @@
377 BugSharingPolicy,
378 InformationType,
379 PRIVATE_INFORMATION_TYPES,
380+ PUBLIC_INFORMATION_TYPES,
381 )
382 from lp.registry.interfaces.projectgroup import IProjectGroup
383 from lp.services.webapp.servers import LaunchpadTestRequest
384@@ -636,16 +637,15 @@
385 bugtask_importance_data.append(new_item)
386 self.assertEqual(
387 bugtask_importance_data, cache['bugtask_importance_data'])
388- self.assertContentEqual(cache['private_types'], [
389- type.name for type in PRIVATE_INFORMATION_TYPES])
390 self.assertEqual(cache['bug_private_by_default'], private_bugs)
391- bugtask_info_type_data = []
392+ bugtask_info_type_data = {}
393 if not IProjectGroup.providedBy(view.context):
394 for item in view.context.getAllowedBugInformationTypes():
395 new_item = {'name': item.title, 'value': item.name,
396 'description': item.description,
397+ 'is_private': item not in PUBLIC_INFORMATION_TYPES,
398 'description_css_class': 'choice-description'}
399- bugtask_info_type_data.append(new_item)
400+ bugtask_info_type_data[item.name] = new_item
401 self.assertContentEqual(
402 bugtask_info_type_data, cache['information_type_data'])
403
404
405=== modified file 'lib/lp/bugs/browser/tests/test_bugview.py'
406--- lib/lp/bugs/browser/tests/test_bugview.py 2012-08-08 05:43:18 +0000
407+++ lib/lp/bugs/browser/tests/test_bugview.py 2012-09-14 01:06:22 +0000
408@@ -104,4 +104,4 @@
409 InformationType.USERDATA.name]
410 self.assertContentEqual(expected, [
411 type['value']
412- for type in cache.objects['information_type_data']])
413+ for type in cache.objects['information_type_data'].values()])
414
415=== modified file 'lib/lp/bugs/javascript/filebug.js'
416--- lib/lp/bugs/javascript/filebug.js 2012-09-05 23:06:42 +0000
417+++ lib/lp/bugs/javascript/filebug.js 2012-09-14 01:06:22 +0000
418@@ -42,9 +42,9 @@
419 val = itypes_table.one(
420 "input[name='field.information_type']:checked").get('value');
421 } else {
422- val = 'PUBLIC';
423+ val = 'PUBLIC';
424 }
425-
426+
427 if (LP.cache.bug_private_by_default) {
428 var filebug_privacy_text = "This report will be private. " +
429 "You can disclose it later.";
430@@ -65,20 +65,17 @@
431 };
432
433 var get_new_banner_text = function(value) {
434- var info_type_descriptions = {};
435- Y.Array.forEach(LP.cache.information_type_data, function(item) {
436- info_type_descriptions[item.value] = item.name;
437- });
438+ var cache = LP.cache.information_type_data;
439 var text_template = "This report contains {info_type} information." +
440 " You can change the information type later.";
441- value = info_type_descriptions[value];
442- return Y.Lang.substitute(text_template, {'info_type': value});
443+ return Y.Lang.substitute(text_template, {
444+ 'info_type': cache[value].name
445+ });
446 };
447
448 var update_banner_from_information_type = function(value) {
449 var banner_text = get_new_banner_text(value);
450- var is_private = (Y.Array.indexOf(
451- LP.cache.private_types, value) >= 0);
452+ var is_private = LP.cache.information_type_data[value].is_private;
453 update_privacy_banner(is_private, banner_text);
454 };
455
456@@ -94,12 +91,17 @@
457 }, "input[name='field.information_type']");
458 };
459
460+
461 var setupChoiceWidgets = function() {
462 Y.lp.app.choice.addPopupChoice('status', LP.cache.bugtask_status_data);
463 Y.lp.app.choice.addPopupChoice(
464 'importance', LP.cache.bugtask_importance_data);
465+ var cache = LP.cache.information_type_data;
466+ var information_helpers = Y.lp.app.information_type
467+ var choices = information_helpers.information_type_to_choicesource(cache)
468+
469 Y.lp.app.choice.addPopupChoiceForRadioButtons(
470- 'information_type', LP.cache.information_type_data, true);
471+ 'information_type', choices, true);
472 };
473
474 var setup_security_related = function() {
475@@ -125,5 +127,5 @@
476
477 }, "0.1", {"requires": [
478 "base", "node", "event", "node-event-delegate", "lp.ui.choiceedit",
479- "lp.app.banner.privacy", "lp.app.choice",
480+ "lp.app.banner.privacy", "lp.app.choice", "lp.app.information_type",
481 "lp.bugs.filebug_dupefinder"]});
482
483=== modified file 'lib/lp/bugs/javascript/tests/test_buglisting.html'
484--- lib/lp/bugs/javascript/tests/test_buglisting.html 2012-06-27 19:49:35 +0000
485+++ lib/lp/bugs/javascript/tests/test_buglisting.html 2012-09-14 01:06:22 +0000
486@@ -34,6 +34,8 @@
487 <script type="text/javascript"
488 src="../../../../../build/js/lp/app/client.js"></script>
489 <script type="text/javascript"
490+ src="../../../../../build/js/lp/app/configutils.js"></script>
491+ <script type="text/javascript"
492 src="../../../../../build/js/lp/app/errors.js"></script>
493 <script type="text/javascript"
494 src="../../../../../build/js/lp/app/expander.js"></script>
495@@ -50,6 +52,8 @@
496 <script type="text/javascript"
497 src="../../../../../build/js/lp/app/inlinehelp/inlinehelp.js"></script>
498 <script type="text/javascript"
499+ src="../../../../../build/js/lp/bugs/buglisting_utils.js"></script>
500+ <script type="text/javascript"
501 src="../../../../../build/js/lp/app/overlay/overlay.js"></script>
502 <script type="text/javascript"
503 src="../../../../../build/js/lp/app/testing/assert.js"></script>
504
505=== modified file 'lib/lp/bugs/javascript/tests/test_filebug.html'
506--- lib/lp/bugs/javascript/tests/test_filebug.html 2012-07-17 14:13:55 +0000
507+++ lib/lp/bugs/javascript/tests/test_filebug.html 2012-09-14 01:06:22 +0000
508@@ -40,6 +40,9 @@
509 <script type="text/javascript"
510 src="../../../../../build/js/lp/app/formwidgets/resizing_textarea.js"></script>
511 <script type="text/javascript"
512+ src="../../../../../build/js/lp/app/information_type.js"></script>
513+
514+ <script type="text/javascript"
515 src="../../../../../build/js/lp/app/overlay/overlay.js"></script>
516 <script type="text/javascript"
517 src="../../../../../build/js/lp/app/anim/anim.js"></script>
518
519=== modified file 'lib/lp/bugs/javascript/tests/test_filebug.js'
520--- lib/lp/bugs/javascript/tests/test_filebug.js 2012-08-27 00:38:02 +0000
521+++ lib/lp/bugs/javascript/tests/test_filebug.js 2012-09-14 01:06:22 +0000
522@@ -13,16 +13,27 @@
523 window.LP = {
524 links: {},
525 cache: {
526- private_types: ['PRIVATESECURITY', 'USERDATA'],
527- information_type_data: [
528- {name: 'Public', value: 'PUBLIC',
529- description: 'Public bug'},
530- {name: 'Private Security',
531+ information_type_data: {
532+ PUBLIC: {
533+ name: 'Public', value: 'PUBLIC',
534+ is_private: false,
535+ order: 1,
536+ description: 'Public bug'
537+ },
538+ PRIVATESECURITY: {
539+ name: 'Private Security',
540 value: 'PRIVATESECURITY',
541- description: 'private security bug'},
542- {name: 'Private', value: 'USERDATA',
543- description: 'Private bug'}
544- ],
545+ order: 2,
546+ is_private: true,
547+ description: 'private security bug'
548+ },
549+ USERDATA: {
550+ name: 'Private', value: 'USERDATA',
551+ is_private: true,
552+ order: 3,
553+ description: 'Private bug'
554+ }
555+ },
556 bugtask_status_data: [
557 {name: 'New', value: 'New'},
558 {name: 'Incomplete', value: 'Incomplete'}
559
560=== modified file 'lib/lp/code/javascript/branch.information_type_choice.js'
561--- lib/lp/code/javascript/branch.information_type_choice.js 2012-09-10 15:23:33 +0000
562+++ lib/lp/code/javascript/branch.information_type_choice.js 2012-09-14 01:06:22 +0000
563@@ -31,7 +31,9 @@
564 value_location: information_type_value,
565 value: initial_value,
566 title: "Change information type",
567- items: LP.cache.information_type_data,
568+ items: information_type.information_type_to_choicesource(
569+ LP.cache.information_type_data
570+ ),
571 backgroundColor: '#FFFF99',
572 flashEnabled: false
573 });
574
575=== modified file 'lib/lp/code/javascript/tests/test_information_type_choice.js'
576--- lib/lp/code/javascript/tests/test_information_type_choice.js 2012-09-10 21:02:05 +0000
577+++ lib/lp/code/javascript/tests/test_information_type_choice.js 2012-09-14 01:06:22 +0000
578@@ -17,17 +17,25 @@
579 web_link: '',
580 information_type: 'Public'
581 },
582- private_types: ['PROPRIETARY', 'USERDATA'],
583- information_type_data: [
584- {'value': 'PUBLIC', 'name': 'Public',
585- 'description': 'Public Description'},
586- {'value': 'PUBLICSECURITY', 'name': 'Public Security',
587- 'description': 'Public Security Description'},
588- {'value': 'PROPRIETARY', 'name': 'Proprietary',
589- 'description': 'Private Description'},
590- {'value': 'USERDATA', 'name': 'Private',
591- 'description': 'Private Description'}
592- ]
593+ information_type_data: {
594+ PUBLIC: {
595+ value: 'PUBLIC', name: 'Public',
596+ is_private: false, order: 1,
597+ description: 'Public Description'
598+ },
599+ PUBLICSECURITY: {
600+ value: 'PUBLICSECURITY', name: 'Public Security',
601+ is_private: false, order: 2,
602+ description: 'Public Security Description'},
603+ PROPRIETARY: {
604+ value: 'PROPRIETARY', name: 'Proprietary',
605+ is_private: true, order: 3,
606+ description: 'Private Description'},
607+ USERDATA: {
608+ value: 'USERDATA', name: 'Private',
609+ is_private: true, order: 4,
610+ description: 'Private Description'}
611+ }
612 }
613 };
614 this.fixture = Y.one('#fixture');
615
616=== modified file 'lib/lp/registry/browser/product.py'
617--- lib/lp/registry/browser/product.py 2012-09-12 11:55:21 +0000
618+++ lib/lp/registry/browser/product.py 2012-09-14 01:06:22 +0000
619@@ -159,9 +159,8 @@
620 )
621 from lp.registry.browser.productseries import get_series_branch_error
622 from lp.registry.enums import (
623+ json_dump_information_types,
624 InformationType,
625- PRIVATE_INFORMATION_TYPES,
626- PUBLIC_INFORMATION_TYPES,
627 )
628 from lp.registry.interfaces.pillar import IPillarNameSet
629 from lp.registry.interfaces.product import (
630@@ -2031,17 +2030,9 @@
631 # when an action is invokved.
632 if IProductSet.providedBy(self.context):
633 cache = IJSONRequestCache(self.request)
634- cache.objects['private_types'] = [
635- type.name for type in PRIVATE_INFORMATION_TYPES]
636- cache.objects['public_types'] = [
637- type.name for type in PUBLIC_INFORMATION_TYPES]
638- cache.objects['information_type_data'] = [
639- {'value': term.name, 'description': term.description,
640- 'name': term.title,
641- 'description_css_class': 'choice-description'}
642- for term in
643- self.context.getAllowedProductInformationTypes()]
644-
645+ json_dump_information_types(
646+ cache,
647+ self.context.getAllowedProductInformationTypes())
648 super(ProjectAddStepTwo, self).initialize()
649
650 @property
651
652=== modified file 'lib/lp/registry/enums.py'
653--- lib/lp/registry/enums.py 2012-09-06 19:05:05 +0000
654+++ lib/lp/registry/enums.py 2012-09-14 01:06:22 +0000
655@@ -14,6 +14,7 @@
656 'FREE_PRIVATE_INFORMATION_TYPES',
657 'INCLUSIVE_TEAM_POLICY',
658 'InformationType',
659+ 'json_dump_information_types',
660 'NON_EMBARGOED_INFORMATION_TYPES',
661 'PersonTransferJobType',
662 'PersonVisibility',
663@@ -108,6 +109,21 @@
664 )
665
666
667+def json_dump_information_types(cache, information_types):
668+ """Dump a dict of the data in the types requested."""
669+ dump = {}
670+ order = list(InformationType.sort_order)
671+ for term in information_types:
672+ dump[term.name] = {
673+ 'value': term.name,
674+ 'description': term.description,
675+ 'name': term.title,
676+ 'order': order.index(term.name),
677+ 'is_private': (term not in PUBLIC_INFORMATION_TYPES), 'description_css_class': 'choice-description',
678+ }
679+
680+ cache.objects['information_type_data'] = dump
681+
682 class SharingPermission(DBEnumeratedType):
683 """Sharing permission.
684