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

Proposed by Richard Harding
Status: Merged
Approved by: j.c.sackett
Approved revision: no longer in the source branch.
Merged at revision: 16262
Proposed branch: lp:~rharding/launchpad/wire_new_banner
Merge into: lp:launchpad
Diff against target: 2161 lines (+306/-1337)
31 files modified
buildout-templates/bin/combine-css.in (+1/-0)
lib/canonical/launchpad/icing/css/components/beta_banner.css (+0/-48)
lib/canonical/launchpad/icing/css/components/global_notification.css (+0/-66)
lib/lp/app/browser/configure.zcml (+0/-7)
lib/lp/app/browser/tales.py (+4/-3)
lib/lp/app/browser/tests/base-layout.txt (+6/-5)
lib/lp/app/browser/tests/test_formatters.py (+1/-1)
lib/lp/app/doc/tales.txt (+1/-1)
lib/lp/app/javascript/banners/banner.js (+0/-156)
lib/lp/app/javascript/banners/beta-notification.js (+0/-104)
lib/lp/app/javascript/banners/privacy.js (+0/-119)
lib/lp/app/javascript/banners/tests/test_banner.html (+0/-46)
lib/lp/app/javascript/banners/tests/test_banner.js (+0/-110)
lib/lp/app/javascript/banners/tests/test_beta_notification.html (+0/-51)
lib/lp/app/javascript/banners/tests/test_beta_notification.js (+0/-140)
lib/lp/app/javascript/banners/tests/test_privacy.html (+0/-47)
lib/lp/app/javascript/banners/tests/test_privacy.js (+0/-117)
lib/lp/app/javascript/information_type.js (+46/-28)
lib/lp/app/javascript/tests/test_information_type.js (+0/-61)
lib/lp/app/templates/banner-macros.pt (+0/-56)
lib/lp/app/templates/base-layout-macros.pt (+5/-7)
lib/lp/app/templates/base-layout.pt (+10/-4)
lib/lp/blueprints/browser/tests/test_specification.py (+3/-4)
lib/lp/blueprints/javascript/addspec.js (+15/-2)
lib/lp/bugs/javascript/bugtask_index.js (+0/-1)
lib/lp/bugs/javascript/filebug.js (+67/-45)
lib/lp/bugs/javascript/tests/test_filebug.js (+118/-61)
lib/lp/code/javascript/branch.information_type_choice.js (+8/-5)
lib/lp/code/javascript/tests/test_information_type_choice.js (+14/-41)
lib/lp/registry/javascript/product_views.js (+6/-0)
lib/lp/services/features/flags.py (+1/-1)
To merge this branch: bzr merge lp:~rharding/launchpad/wire_new_banner
Reviewer Review Type Date Requested Status
j.c.sackett (community) Approve
Review via email: mp+133927@code.launchpad.net

Commit message

Wire up the new ui.banner code and the global.js view to handle all banner displaying.

Description of the change

= Summary =

In a previous MP [1] a new banner handling JS code was landed. This branch
wires that code into play and replaces all of the old banner code.

The basic change is that the old macros are gone and we generate the banners
from the JS code. It's handled by firing an information type event. View code
must watch for that event and handle updating banners as required.

== Pre Implementation ==

It's been a long road. Lots of chatter. The big thing here is that review of
the previous MP brought up messaging for non-js users. This branch does add in
a <noscript> message for those users.

== Implementation Notes ==

We need to make sure we combine our new css file for widget styling.

All of the old banner code is removed. This includes the old beta css, the
global-notification (which was really just the privacy/beta banner css), the
whole app/banner JS folder. The new code is all contained in
lp/app/ui/banner.js.

Since we're not using any of the global-notification css the css generating
tales needs to be updated along with tests referencing it.

One hack is that security invokes a privacy banner. Ideally, we'd create a new
security banner and treat it separately as we do the beta banner. This will now
be possible, but it's not implemented in this branch. Because of this we have
some special casing around the event work to generate the correct banner
message.

Anywhere we manually updated the banner we change that to just fire the
information type event that the information type has changed. The global.js
will catch and handle all banner issues. This also allows other code to watch
that event so that more than banners can update as appropriate when the
information type changes.

global.js makes sure we watch for things on all pages that use the base
layout. In the future all of the JS in base-layout-macros should be moved with
tests added, however this just starts with replacing the banner code and
adding tests for it.

For the use case of the lynx users on the server we add <noscript> messages.
This has been tested to work and because it's <strong> it appears in red using
default colors.

There's a few drive by fixes of not enabling the green flash effect when the
information type changes in places where that is not performing an ajax
request per our design guidelines.

Finally we add a nice message to the private project feature flag in order to
make sure the beta banner shows in a pretty way.

== Q/A ==

Banners for beta and privacy should function on:

- registering a new project
- editing a current project
- creating and editing a new blueprint

Privacy banner should still function for:

- filing a bug, editing a bug, changing the info type via portlet
- changing the info type via portlet

[1] https://code.launchpad.net/~rharding/launchpad/add_new_banner/+merge/133736

To post a comment you must log in.
Revision history for this message
j.c.sackett (jcsackett) wrote :

Rick--

Looks good. I cannot tell you how happy I am to see that _shim/_unshim mess in
the info_type js tests go away.

Two points, neither are blockers to approval but should be dealt with before
landing:

#1381: Pretty sure I see a copy paste error here--"The information on this
page is private" dropped into the middle of the comment.

#1691: Is there a bug for this? Should one be filed and added to this XXX?
And don't forget to add your name to the XXX comment so being following
up know who to talk to.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'buildout-templates/bin/combine-css.in'
2--- buildout-templates/bin/combine-css.in 2012-08-23 19:56:15 +0000
3+++ buildout-templates/bin/combine-css.in 2012-11-13 15:23:21 +0000
4@@ -27,6 +27,7 @@
5 #'lazr/build/yui/cssgrids/grids.css',
6 'cssgrids/grids.css',
7 'build/ui/assets/skins/sam/lazr.css',
8+ 'build/ui/assets/skins/sam/banner.css',
9 'build/inlineedit/assets/skins/sam/editor.css',
10 'build/autocomplete/assets/skins/sam/autocomplete.css',
11 'build/overlay/assets/skins/sam/pretty-overlay.css',
12
13=== removed file 'lib/canonical/launchpad/icing/css/components/beta_banner.css'
14--- lib/canonical/launchpad/icing/css/components/beta_banner.css 2012-05-16 20:32:47 +0000
15+++ lib/canonical/launchpad/icing/css/components/beta_banner.css 1970-01-01 00:00:00 +0000
16@@ -1,48 +0,0 @@
17-/* ===========
18- Beta banner
19-*/
20-.yui3-betabanner-content .global-notification {
21- position: fixed;
22- z-index: 9;
23- top: 0;
24- left: 0;
25- right: 0;
26- padding: 7px 20px;
27- /* Define colour for browsers that don't support transparency */
28- background-color: #606060;
29- /* Set transparent background for browsers that support it */
30- background-color: rgba(64, 64, 64, 0.9);
31- box-shadow: 0 0 5px #333;
32- color: #fff;
33- text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.5);
34- font-size: 14px;
35- line-height: 21px;
36- text-align: left;
37- }
38-.beta-banner .info-link {
39- color: #4884ef;
40-}
41-.beta-warning {
42- padding: 3px 6px 4px 6px;
43- margin-right: 12px;
44- background-color: #be0000;
45- font-weight: bold;
46- font-size: 12px;
47- text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
48- border-radius: 5px;
49- border-top: 1px solid #e20000;
50- background-color: #c10000;
51- background: linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%);
52- background: -o-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%);
53- background: -moz-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%);
54- background: -webkit-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%);
55- background: -ms-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%);
56- }
57-.beta-feature {
58- font-weight: bold;
59- }
60-.yui3-betabanner-content .global-notification-close,
61-.yui3-betabanner-content .global-notification-close:active,
62-.yui3-betabanner-content .global-notification-close:visited {
63- color: #fff;
64- }
65
66=== removed file 'lib/canonical/launchpad/icing/css/components/global_notification.css'
67--- lib/canonical/launchpad/icing/css/components/global_notification.css 2012-05-16 19:09:45 +0000
68+++ lib/canonical/launchpad/icing/css/components/global_notification.css 1970-01-01 00:00:00 +0000
69@@ -1,66 +0,0 @@
70-/* ====================
71- Global notifications
72-*/
73-/* Move the content down so the notification banner doesn't hide any content. */
74-body.global-notification-visible {
75- padding-top: 40px;
76- }
77-body.global-notification-visible .login-logout {
78- top: 45px;
79- }
80-.global-notification {
81- position: fixed;
82- z-index: 10;
83- top: 0;
84- left: 0;
85- right: 0;
86- padding: 8px 20px;
87- text-shadow: 0 -1px 0 #631616;
88- font-size: 14px;
89- line-height: 21px;
90- font-weight: bold;
91- box-shadow: 0 0 5px #333;
92- }
93-.global-notification .sprite.notification-private {
94- float: left;
95- display: inline-block;
96- height: 21px;
97- width: 20px;
98- margin-right: 10px;
99- padding: 0;
100- }
101-.global-notification-close,
102-.global-notification-close:active,
103-.global-notification-close:visited {
104- color: #e47a7a;
105- }
106-.global-notification-close {
107- display: block;
108- position: absolute;
109- top: 11px;
110- right: 20px;
111- font-size: 12px;
112- font-weight: normal;
113- line-height: 14px;
114- }
115-.global-notification-close .sprite.notification-close {
116- float: right;
117- display: block;
118- height: 9px;
119- width: 8px;
120- margin: 3px 0 0 7px;
121- padding: 0;
122- }
123-
124-/* =======
125- Privacy
126-*/
127-
128-.yui3-privacybanner-content .global-notification{
129- /* Define colour for browsers that don't support transparency */
130- background-color: #8d1f1f;
131- /* Set transparent background for browsers that support it */
132- background-color: rgba(125,0,0,0.9);
133- color: #fff;
134- text-align: left;
135-}
136
137=== modified file 'lib/lp/app/browser/configure.zcml'
138--- lib/lp/app/browser/configure.zcml 2012-08-09 03:50:49 +0000
139+++ lib/lp/app/browser/configure.zcml 2012-11-13 15:23:21 +0000
140@@ -33,13 +33,6 @@
141 />
142 <browser:page
143 for="*"
144- name="+banner-macros"
145- template="../templates/banner-macros.pt"
146- permission="zope.Public"
147- class="lp.app.browser.launchpad.Macro"
148- />
149- <browser:page
150- for="*"
151 name="launchpad_form"
152 layer="lp.layers.LaunchpadLayer"
153 permission="zope.Public"
154
155=== modified file 'lib/lp/app/browser/tales.py'
156--- lib/lp/app/browser/tales.py 2012-09-28 06:15:58 +0000
157+++ lib/lp/app/browser/tales.py 2012-11-13 15:23:21 +0000
158@@ -663,15 +663,16 @@
159 def global_css(self):
160 css_classes = set([])
161 view = self._context
162+
163+ # XXX: Bug #1076074
164 private = getattr(view, 'private', False)
165 if private:
166 css_classes.add('private')
167- css_classes.add('global-notification-visible')
168 else:
169 css_classes.add('public')
170 beta = getattr(view, 'beta_features', [])
171- if beta != []:
172- css_classes.add('global-notification-visible')
173+ if beta:
174+ css_classes.add('beta')
175 return ' '.join(list(css_classes))
176
177 def _getSaneBreadcrumbDetail(self, breadcrumb):
178
179=== modified file 'lib/lp/app/browser/tests/base-layout.txt'
180--- lib/lp/app/browser/tests/base-layout.txt 2012-05-22 17:00:08 +0000
181+++ lib/lp/app/browser/tests/base-layout.txt 2012-11-13 15:23:21 +0000
182@@ -158,12 +158,10 @@
183 -------------------------------
184
185 The base-layout master templates uses the fmt:global-css formatter to
186-add the 'public' or 'private' CSS class to the body tag as well as the
187-'global-notification-visible' tag, if needed.
188+add the 'public' or 'private' CSS class to the body tag.
189
190 When the context is private, the 'private' class is added to the body's class
191-attribute. If the context is private or there are beta features,
192-'global-notification-visible' is added to the body's class attribute.
193+attribute.
194
195 >>> from lp.registry.interfaces.person import PersonVisibility
196
197@@ -174,7 +172,10 @@
198 >>> view = MainOnlyView(team, request)
199 >>> body = find_tag_by_id(view.render(), 'document')
200 >>> print body['class']
201- tab-overview main_only global-notification-visible private yui3-skin-sam
202+ tab-overview
203+ main_only
204+ private
205+ yui3-skin-sam
206
207 When the context is public, the 'public' class is in the class attribute.
208
209
210=== modified file 'lib/lp/app/browser/tests/test_formatters.py'
211--- lib/lp/app/browser/tests/test_formatters.py 2012-08-08 07:23:58 +0000
212+++ lib/lp/app/browser/tests/test_formatters.py 2012-11-13 15:23:21 +0000
213@@ -91,7 +91,7 @@
214 view = create_view(person, name="+archivesubscriptions")
215 formatter = ObjectFormatterAPI(view)
216 self.assertEqual(
217- 'global-notification-visible private',
218+ 'private',
219 formatter.global_css())
220
221 class TestPillarFormatterAPI(TestCaseWithFactory):
222
223=== modified file 'lib/lp/app/doc/tales.txt'
224--- lib/lp/app/doc/tales.txt 2012-06-15 16:23:50 +0000
225+++ lib/lp/app/doc/tales.txt 2012-11-13 15:23:21 +0000
226@@ -1551,7 +1551,7 @@
227 True
228
229 >>> print test_tales('context/fmt:global-css', context=bug)
230- global-notification-visible private
231+ private
232
233 >>> login(ANONYMOUS)
234
235
236=== removed directory 'lib/lp/app/javascript/banners'
237=== removed file 'lib/lp/app/javascript/banners/banner.js'
238--- lib/lp/app/javascript/banners/banner.js 2012-10-04 14:17:23 +0000
239+++ lib/lp/app/javascript/banners/banner.js 1970-01-01 00:00:00 +0000
240@@ -1,156 +0,0 @@
241-/*
242- * Copyright 2012 Canonical Ltd. This software is licensed under the
243- * GNU Affero General Public License version 3 (see the file LICENSE).
244- *
245- * Notification banner widget
246- *
247- * @module lp.app.banner
248- */
249-
250-YUI.add('lp.app.banner', function (Y) {
251-var ns = Y.namespace('lp.app.banner');
252-
253-ns.Banner = Y.Base.create('banner', Y.Widget, [], {
254-
255- _getAnimTimes: function() {
256- var anim_times;
257- if (this.get('skip_animation')) {
258- anim_times = {
259- fade: 0.0,
260- slide_out: 0.0
261- };
262- } else {
263- anim_times = {
264- fade: 0.3,
265- slide_out: 0.2
266- };
267- }
268- return anim_times;
269- },
270-
271- _showBanner: function () {
272- var body = Y.one('body');
273- var global_notification = Y.one('.global-notification');
274- var anim_times = this._getAnimTimes();
275-
276- body.addClass('global-notification-visible');
277- global_notification.removeClass('hidden');
278-
279- var fade_in = new Y.Anim({
280- node: global_notification,
281- to: {opacity: 1},
282- duration: anim_times.fade
283- });
284- var body_space = new Y.Anim({
285- node: body,
286- to: {'paddingTop': '40px'},
287- duration: anim_times.slide_out,
288- easing: Y.Easing.easeOut
289- });
290- var login_space = new Y.Anim({
291- node: '.login-logout',
292- to: {'top': '45px'},
293- duration: anim_times.slide_out,
294- easing: Y.Easing.easeOut
295- });
296- // For testing, we don't do the animations or else the tests will fail.
297- if (anim_times.fade > 0) {
298- fade_in.run();
299- }
300- if (anim_times.slide_out > 0) {
301- body_space.run();
302- login_space.run();
303- }
304- },
305-
306- _hideBanner: function () {
307- var body = Y.one('body');
308- var global_notification = Y.one('.global-notification');
309- var anim_times = this._getAnimTimes();
310-
311- global_notification.addClass('transparent');
312-
313- var fade_out = new Y.Anim({
314- node: global_notification,
315- to: {opacity: 0},
316- duration: anim_times.fade
317- });
318- var body_space = new Y.Anim({
319- node: body,
320- to: {'paddingTop': 0},
321- duration: anim_times.slide_out,
322- easing: Y.Easing.easeOut
323- });
324- var login_space = new Y.Anim({
325- node: '.login-logout',
326- to: {'top': '6px'},
327- duration: anim_times.slide_out,
328- easing: Y.Easing.easeOut
329- });
330- fade_out.on('end', function() {
331- global_notification.addClass('hidden');
332- });
333- body_space.on('end', function() {
334- body.removeClass('global-notification-visible');
335- });
336-
337- fade_out.run();
338- body_space.run();
339- login_space.run();
340- },
341-
342- bindUI: function() {
343- this.after('visibleChange', function() {
344- if (this.get('visible')) {
345- this._showBanner();
346- } else {
347- this._hideBanner();
348- }
349- });
350- },
351-
352- renderUI: function () {
353- var banner_data = {
354- badge: this.get('banner_icon'),
355- text: this.get('notification_text')
356- };
357- var banner_html = Y.lp.mustache.to_html(
358- this.get('banner_template'),
359- banner_data);
360- this.get('contentBox').append(banner_html);
361- },
362-
363- updateText: function (new_text) {
364- var text_node = this.get('contentBox').one('.banner-text');
365- if (!Y.Lang.isValue(new_text)) {
366- new_text = this.get('notification_text');
367- }
368-
369- if (text_node) {
370- text_node.set('text', new_text);
371- } else {
372- Y.log('No text node to update banner text.', 'error');
373- }
374- }
375-
376-}, {
377- ATTRS: {
378- banner_icon: { value: "<span></span>" },
379- banner_template: {
380- valueFn: function() {
381- return [
382- '<div class="global-notification transparent hidden">',
383- '{{{ badge }}}',
384- '<span class="banner-text">{{ text }}</span>',
385- "</div>"].join('');
386- }
387- },
388- notification_text: { value: "" },
389- skip_animation: { value: false },
390- visible: { value: false }
391- }
392-});
393-
394-}, '0.1', {
395- requires: ['base', 'node', 'anim', 'widget', 'lp.mustache', 'yui-log']
396-});
397
398=== removed file 'lib/lp/app/javascript/banners/beta-notification.js'
399--- lib/lp/app/javascript/banners/beta-notification.js 2012-09-25 18:47:19 +0000
400+++ lib/lp/app/javascript/banners/beta-notification.js 1970-01-01 00:00:00 +0000
401@@ -1,104 +0,0 @@
402-/**
403- * Add a BetaBanner widget for use.
404- *
405- * @namespace lp.app.banner
406- * @module beta
407- *
408- */
409-YUI.add('lp.app.banner.beta', function(Y) {
410-
411-var ns = Y.namespace('lp.app.banner.beta');
412-var Banner = Y.lp.app.banner.Banner;
413-
414-// For the beta banner to work, it needs to have one instance, and one
415-// instance only.
416-window._singleton_beta_banner = null;
417-
418-ns.show_beta_if_needed = function () {
419- if (window._singleton_beta_banner === null) {
420- var src = Y.one('.yui3-betabanner');
421- window._singleton_beta_banner = new ns.BetaBanner({ srcNode: src });
422- }
423- if (window._singleton_beta_banner.get('features').length !== 0) {
424- window._singleton_beta_banner.render();
425- window._singleton_beta_banner.show();
426- }
427-};
428-
429-
430-/**
431- * Banner to display for beta features.
432- *
433- * @class BetaBanner
434- * @extends Banner
435- *
436- */
437-ns.BetaBanner = Y.Base.create('betaBanner', Banner, [], {
438-
439- bindUI: function () {
440- Banner.prototype.bindUI.apply(this, arguments);
441- var close_box = Y.one('.global-notification-close');
442- var that = this;
443- close_box.on('click', function(e) {
444- e.halt();
445- that.hide();
446- });
447- },
448-
449- renderUI: function () {
450- var banner_data = {
451- badge: this.get('banner_icon'),
452- text: this.get('notification_text'),
453- features: this.get('features'),
454- };
455- var banner_html = Y.lp.mustache.to_html(
456- this.get('banner_template'),
457- banner_data);
458- this.get('contentBox').append(banner_html);
459- var beta_node = Y.one('.global-notification');
460- var close_box = Y.Node.create(
461- '<a href="#" class="global-notification-close">Hide' +
462- '<span class="notification-close sprite" /></a>');
463- beta_node.appendChild(close_box);
464- }
465-
466-}, {
467- ATTRS: {
468- banner_icon: { value: '<span class="beta-warning">BETA!</span>' },
469-
470- banner_template: {
471- valueFn: function() {
472- return [
473- '<div class="global-notification transparent hidden">',
474- '{{{ badge }}}',
475- '<span class="banner-text">',
476- '{{ text }}{{{ features }}}',
477- '</span>',
478- "</div>"].join('');
479- }
480- },
481-
482- features: {
483- valueFn: function () {
484- var features_template = [
485- '{{#features}}{{#is_beta}}',
486- '<span class="beta-feature"> {{title}}',
487- '{{#url}}',
488- ' (<a href="{{url}}" class="info-link">read more</a>)',
489- '{{/url}}',
490- '</span>',
491- '{{/is_beta}}{{/features}}'].join('');
492- var feature_data = {
493- features: Y.Object.values(LP.cache.related_features)
494- };
495- return Y.lp.mustache.to_html(features_template, feature_data);
496- }
497- },
498-
499- notification_text: { value: "Some parts of this page are in beta: " }
500- }
501-});
502-
503-
504-}, '0.1', {'requires': ['base', 'node', 'anim', 'lp.mustache',
505- 'lp.app.banner']});
506
507=== removed file 'lib/lp/app/javascript/banners/privacy.js'
508--- lib/lp/app/javascript/banners/privacy.js 2012-10-04 14:17:23 +0000
509+++ lib/lp/app/javascript/banners/privacy.js 1970-01-01 00:00:00 +0000
510@@ -1,119 +0,0 @@
511-/**
512- * Add a PrivacyBanner widget for use.
513- *
514- * @namespace lp.app.banner
515- * @module privacy
516- *
517- */
518-YUI.add('lp.app.banner.privacy', function(Y) {
519-var ns = Y.namespace('lp.app.banner.privacy');
520-var Banner = Y.lp.app.banner.Banner;
521-
522-ns.EV_SHOW = 'privacy_banner:show';
523-ns.EV_HIDE = 'privacy_banner:hide';
524-
525-/**
526- * Allow for adjusting the global instance of the Privacy Banner via events.
527- *
528- * @event privacy_banner:show
529- * @param text The message to show
530- */
531-Y.publish(ns.EV_SHOW, {
532- emitFacade: true
533-});
534-
535-/**
536- * Hide the global instance of the banner via events.
537- *
538- * @event privacy_banner:hide
539- */
540-Y.publish(ns.EV_HIDE, {
541- emitFacade: true
542-});
543-
544-
545-// For the privacy banner to work, it needs to have one instance, and one
546-// instance only.
547-window._singleton_privacy_banner = null;
548-ns.getPrivacyBanner = function (banner_text, skip_animation) {
549- if (window._singleton_privacy_banner === null) {
550- var src = Y.one('.yui3-privacybanner');
551- window._singleton_privacy_banner = new ns.PrivacyBanner(
552- { srcNode: src, skip_animation: skip_animation });
553- window._singleton_privacy_banner.render();
554- }
555- if (Y.Lang.isValue(banner_text)) {
556- window._singleton_privacy_banner.updateText(banner_text);
557- }
558- return window._singleton_privacy_banner;
559-};
560-
561-
562-/**
563- * Banner to display when page contains private information.
564- *
565- * @class PrivacyBanner
566- * @extends Banner
567- *
568- */
569-ns.PrivacyBanner = Y.Base.create('privacyBanner', Banner, [], {
570- _custom_message: function (ev) {
571- var body = Y.one('body');
572- body.replaceClass('public', 'private');
573- if (!ev.text) {
574- throw('A custom privacy banner must have a text attribute');
575- }
576- this.updateText(ev.text);
577- this.show();
578- },
579-
580- _make_public: function (ev) {
581- var body = Y.one('body');
582- body.replaceClass('private', 'public');
583- this.hide();
584- },
585-
586- _make_private: function (ev) {
587- // Update the text in the banner before we show it.
588- var body = Y.one('body');
589- body.replaceClass('public', 'private');
590-
591- if (!ev.text) {
592- throw('Showing a privacy banner must supply text for the banner');
593- }
594- this.updateText(ev.text);
595- this.show();
596- },
597-
598- bindUI: function () {
599- var that = this;
600- var info_type = Y.lp.app.information_type;
601- Banner.prototype.bindUI.apply(this, arguments);
602-
603- // We care about changes to Information Type in the UI.
604- Y.on(info_type.EV_ISPUBLIC, that._make_public, that);
605- Y.on(info_type.EV_ISPRIVATE, that._make_private, that);
606-
607- // And provide our own manual events for the Security banner usage.
608- Y.on(ns.EV_SHOW, that._custom_message, that);
609- Y.on(ns.EV_HIDE, function (ev) {
610- that.hide();
611- }, that);
612- }
613-
614-}, {
615- ATTRS: {
616- banner_icon: {
617- value: '<span class="sprite notification-private"></span>'
618- },
619- notification_text: {
620- value: "The information on this page is private."
621- }
622- }
623-});
624-
625-}, "0.1", {
626- requires: [
627- "base", "node", "anim", "lp.app.banner",
628- "lp.app.information_type"]
629-});
630
631=== removed directory 'lib/lp/app/javascript/banners/tests'
632=== removed file 'lib/lp/app/javascript/banners/tests/test_banner.html'
633--- lib/lp/app/javascript/banners/tests/test_banner.html 2012-10-26 09:54:28 +0000
634+++ lib/lp/app/javascript/banners/tests/test_banner.html 1970-01-01 00:00:00 +0000
635@@ -1,46 +0,0 @@
636-<!DOCTYPE html>
637-<!--
638-Copyright 2012 Canonical Ltd. This software is licensed under the
639-GNU Affero General Public License version 3 (see the file LICENSE).
640--->
641-
642-<html>
643- <head>
644- <title>lp.app.banner Tests</title>
645-
646- <!-- YUI and test setup -->
647- <script type="text/javascript"
648- src="../../../../../../build/js/yui/yui/yui.js">
649- </script>
650- <link rel="stylesheet"
651- href="../../../../../../build/js/yui/console/assets/console-core.css" />
652- <link rel="stylesheet"
653- href="../../../../../../build/js/yui/test-console/assets/skins/sam/test-console.css" />
654- <link rel="stylesheet"
655- href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" />
656-
657- <script type="text/javascript"
658- src="../../../../../../build/js/lp/app/testing/testrunner.js"></script>
659-
660- <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
661-
662- <!-- Dependencies -->
663- <script type="text/javascript"
664- src="../../../../../../build/js/lp/app/mustache.js"></script>
665-
666- <!-- The module under test. -->
667- <script type="text/javascript" src="../banner.js"></script>
668-
669- <!-- Placeholder for any css asset for this module. -->
670- <!-- <link rel="stylesheet" href="../assets/${LIBRARY}-core.css" /> -->
671-
672- <!-- The test suite -->
673- <script type="text/javascript" src="test_banner.js"></script>
674-
675- </head>
676- <body class="yui3-skin-sam">
677- <ul id="suites">
678- <li>lp.app.banner.test</li>
679- </ul>
680- </body>
681-</html>
682
683=== removed file 'lib/lp/app/javascript/banners/tests/test_banner.js'
684--- lib/lp/app/javascript/banners/tests/test_banner.js 2012-10-26 10:00:20 +0000
685+++ lib/lp/app/javascript/banners/tests/test_banner.js 1970-01-01 00:00:00 +0000
686@@ -1,110 +0,0 @@
687-/* Copyright (c) 2012, Canonical Ltd. All rights reserved. */
688-
689-YUI.add('lp.app.banner.test', function (Y) {
690-
691- var tests = Y.namespace('lp.app.banner.test');
692- tests.suite = new Y.Test.Suite('lp.app.banner Tests');
693-
694- tests.suite.add(new Y.Test.Case({
695- name: 'banner_tests',
696-
697- setUp: function () {
698- var main = Y.Node.create('<div id="maincontent"></div>');
699- var login_logout = Y.Node.create('<div></div>')
700- .addClass('login-logout');
701- main.appendChild(login_logout);
702- Y.one('body').appendChild(main);
703- },
704-
705- tearDown: function () {
706- Y.one('#maincontent').remove(true);
707- Y.all('.yui3-banner').remove(true);
708- },
709-
710- test_library_exists: function () {
711- Y.Assert.isObject(Y.lp.app.banner,
712- "Could not locate the lp.app.banner module");
713- },
714-
715- test_init_without_config: function () {
716- var banner = new Y.lp.app.banner.Banner();
717- Y.Assert.areEqual("", banner.get('notification_text'));
718- Y.Assert.areEqual("<span></span>", banner.get('banner_icon'));
719- },
720-
721- test_init_with_config: function () {
722- var cfg = {
723- notification_text: "Some text.",
724- banner_icon: '<span class="sprite"></span>'
725- };
726- var banner = new Y.lp.app.banner.Banner(cfg);
727- Y.Assert.areEqual(
728- cfg.notification_text,
729- banner.get('notification_text'));
730- Y.Assert.areEqual(cfg.banner_icon, banner.get('banner_icon'));
731- },
732-
733- test_render_no_config: function () {
734- var banner = new Y.lp.app.banner.Banner({ skip_animation: true });
735- banner.render();
736-
737- var banner_node = Y.one(".global-notification");
738- Y.Assert.isObject(banner_node);
739- Y.Assert.isTrue(banner_node.hasClass('hidden'));
740- },
741-
742- test_render_with_config: function () {
743- var cfg = {
744- notification_text: "Some text.",
745- banner_icon: '<span class="sprite"></span>',
746- skip_animation: true
747- };
748- var banner = new Y.lp.app.banner.Banner(cfg);
749- banner.render();
750-
751- var banner_node = Y.one(".global-notification");
752- var badge = banner_node.one('.sprite');
753- Y.Assert.isObject(banner_node);
754- Y.Assert.areEqual(cfg.notification_text, banner_node.get('text'));
755- Y.Assert.isObject(badge);
756- },
757-
758- test_show: function() {
759- var banner = new Y.lp.app.banner.Banner({ skip_animation: true });
760- banner.render();
761- banner.show();
762- var banner_node = Y.one(".global-notification");
763- Y.Assert.isFalse(banner_node.hasClass('hidden'));
764- },
765-
766- test_hide: function() {
767- var banner = new Y.lp.app.banner.Banner({ skip_animation: true });
768- banner.render();
769- banner.show();
770-
771- // Even with animation times set to 0, this test needs a slight
772- // delay in order for the animation end events to fire.
773- var banner_node = Y.one(".global-notification");
774- var wait_for_anim = 20;
775- var check = function () {
776- Y.Assert.isTrue(banner_node.hasClass('hidden'));
777- };
778- banner.hide();
779- this.wait(check, wait_for_anim);
780- },
781-
782- test_updateText: function() {
783- var banner = new Y.lp.app.banner.Banner({ skip_animation: true });
784- banner.render();
785- var new_text = 'some new text';
786- banner.updateText(new_text);
787- var banner_node = Y.one(".global-notification");
788- Y.Assert.areEqual(new_text, banner_node.get('text'));
789-
790- banner.updateText();
791- banner_node = Y.one(".global-notification");
792- Y.Assert.areEqual("", banner_node.get('text'));
793- }
794- }));
795-
796-}, '0.1', {'requires': ['test', 'test-console', 'lp.app.banner']});
797
798=== removed file 'lib/lp/app/javascript/banners/tests/test_beta_notification.html'
799--- lib/lp/app/javascript/banners/tests/test_beta_notification.html 2012-10-26 09:54:28 +0000
800+++ lib/lp/app/javascript/banners/tests/test_beta_notification.html 1970-01-01 00:00:00 +0000
801@@ -1,51 +0,0 @@
802-<!DOCTYPE html>
803-<!--
804-Copyright 2012 Canonical Ltd. This software is licensed under the
805-GNU Affero General Public License version 3 (see the file LICENSE).
806--->
807-
808-<html>
809- <head>
810- <title>Test beta-notification</title>
811-
812- <!-- YUI and test setup -->
813- <script type="text/javascript"
814- src="../../../../../../build/js/yui/yui/yui.js">
815- </script>
816- <link rel="stylesheet"
817- href="../../../../../../build/js/yui/console/assets/console-core.css" />
818- <link rel="stylesheet"
819- href="../../../../../../build/js/yui/test-console/assets/skins/sam/test-console.css" />
820- <link rel="stylesheet"
821- href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" />
822-
823- <script type="text/javascript"
824- src="../../../../../../build/js/lp/app/testing/testrunner.js"></script>
825-
826- <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
827-
828- <!-- Dependencies -->
829- <script type="text/javascript"
830- src="../../../../../../build/js/lp/app/banners/banner.js"></script>
831- <script type="text/javascript"
832- src="../../../../../../build/js/lp/app/mustache.js"></script>
833-
834- <!-- The module under test. -->
835- <script type="text/javascript" src="../beta-notification.js"></script>
836-
837- <!-- Placeholder for any css asset for this module. -->
838- <!-- <link rel="stylesheet" href="../assets/beta-notification-core.css" /> -->
839-
840- <!-- The test suite. -->
841- <script type="text/javascript" src="test_beta_notification.js"></script>
842-
843- </head>
844- <body class="yui3-skin-sam">
845- <ul id="suites">
846- <!-- <li>lp.large_indicator.test</li> -->
847- <li>lp.app.banner.beta.test</li>
848- </ul>
849- <!-- The example markup required by the script to run. -->
850- <div id="maincontent"></div>
851- </body>
852-</html>
853
854=== removed file 'lib/lp/app/javascript/banners/tests/test_beta_notification.js'
855--- lib/lp/app/javascript/banners/tests/test_beta_notification.js 2012-10-26 10:00:20 +0000
856+++ lib/lp/app/javascript/banners/tests/test_beta_notification.js 1970-01-01 00:00:00 +0000
857@@ -1,140 +0,0 @@
858-/* Copyright (c) 2012, Canonical Ltd. All rights reserved. */
859-
860-// Set the "enabled" variable, normally set by base-layout-macros.
861-// This must be a global variable for the code being tested to work.
862-var privacy_notification_enabled = true;
863-
864-YUI.add('lp.app.banner.beta.test', function (Y) {
865-
866- var tests = Y.namespace('lp.app.banner.beta.test');
867- tests.suite = new Y.Test.Suite('lp.app.banner.beta Tests');
868-
869- tests.suite.add(new Y.Test.Case({
870- name: 'beta-notification',
871-
872- setUp: function () {
873- var main = Y.Node.create('<div id="maincontent"></div>');
874- var login_logout = Y.Node.create('<div></div>')
875- .addClass('login-logout');
876- main.appendChild(login_logout);
877- Y.one('body').append(main);
878- window.LP = {
879- cache: {}
880- };
881- },
882-
883- tearDown: function () {
884- Y.one('#maincontent').remove(true);
885- Y.all('.yui3-banner').remove(true);
886- },
887-
888- test_library_exists: function () {
889- Y.Assert.isObject(Y.lp.app.banner.beta,
890- "Could not locate the lp.app.banner.beta module");
891- },
892-
893- test_beta_banner_one_beta_feature: function() {
894- LP.cache.related_features = {
895- '': {
896- is_beta: true,
897- title: 'A beta feature',
898- url: 'http://lp.dev/LEP/one'
899- }};
900- var betabanner = new Y.lp.app.banner.beta.BetaBanner(
901- {skip_animation: true});
902- betabanner.render();
903- betabanner.show();
904-
905- var body = Y.one('body');
906- // The <body> node has the class global-notification-visible,
907- // so that the element has enough padding for the beta banner.
908- Y.Assert.isTrue(body.hasClass('global-notification-visible'));
909-
910- feature_info = Y.one('.beta-feature');
911- // The message about a beta feature consists of the feature
912- // title and a link to a page with more information about
913- // the feature.
914- Y.Assert.areEqual(
915- ' A beta feature (read more)', feature_info.get('text'));
916- info_link = feature_info.get('children').item(0);
917- Y.Assert.areEqual('http://lp.dev/LEP/one', info_link.get('href'));
918- },
919-
920- test_beta_banner_two_beta_features: function() {
921- LP.cache.related_features = {
922- '1': {
923- is_beta: true,
924- title: 'Beta feature 1',
925- url: 'http://lp.dev/LEP/one'
926- },
927- '2': {
928- is_beta: true,
929- title: 'Beta feature 2',
930- url: ''
931- }};
932- var betabanner = new Y.lp.app.banner.beta.BetaBanner(
933- {skip_animation: true});
934- betabanner.render();
935- betabanner.show();
936-
937- var body = Y.one('body');
938- Y.Assert.isTrue(body.hasClass('global-notification-visible'));
939-
940- // Notifications about several features can be displayed.
941- feature_info = Y.all('.beta-feature').item(0);
942- Y.Assert.areEqual(
943- ' Beta feature 1 (read more)', feature_info.get('text'));
944- info_link = feature_info.get('children').item(0);
945- Y.Assert.areEqual('http://lp.dev/LEP/one', info_link.get('href'));
946-
947- // If an entry in LP.cache.related_features does not provide a
948- // "read more" link, the corrsponding node is not added.
949- feature_info = Y.all('.beta-feature').item(1);
950- Y.Assert.areEqual(
951- ' Beta feature 2', feature_info.get('text'));
952- Y.Assert.isNull(feature_info.get('children').item(0));
953- },
954-
955- test_beta_banner_no_beta_features_defined: function() {
956- LP.cache.related_features = {
957- foo_feature: {
958- is_beta: false,
959- title: 'Non-beta feature',
960- url: 'http://example.org'
961- }};
962- Y.lp.app.banner.beta.show_beta_if_needed();
963- Y.Assert.isNull(Y.one('.global-notification'));
964- },
965-
966- test_hide_beta_banner: function() {
967- LP.cache.related_features = {
968- '': {
969- is_beta: true,
970- title: 'A beta feature',
971- url: 'http://lp.dev/LEP/one'
972- }};
973- var betabanner = new Y.lp.app.banner.beta.BetaBanner(
974- {skip_animation: true});
975- betabanner.render();
976- betabanner.show();
977- var body = Y.one('body');
978- var banner = Y.one('.global-notification');
979- Y.Assert.isFalse(banner.hasClass('hidden'));
980-
981- // Even with animation times set to 0, this test needs a slight
982- // delay in order for the animation end events to fire.
983- var check = function() {
984- Y.Assert.isTrue(banner.hasClass('hidden'));
985- Y.Assert.isFalse(
986- body.hasClass('global-notification-visible'));
987- };
988- close_link = Y.one('.global-notification-close');
989- close_link.simulate('click');
990- var wait_time = 20;
991- this.wait(check, wait_time);
992- }
993- }));
994-
995-}, '0.1', { 'requires': ['test', 'test-console', 'node', 'lp.app.banner.beta',
996- 'node-event-simulate']
997-});
998
999=== removed file 'lib/lp/app/javascript/banners/tests/test_privacy.html'
1000--- lib/lp/app/javascript/banners/tests/test_privacy.html 2012-10-26 09:54:28 +0000
1001+++ lib/lp/app/javascript/banners/tests/test_privacy.html 1970-01-01 00:00:00 +0000
1002@@ -1,47 +0,0 @@
1003-<!DOCTYPE html>
1004-<!--
1005-Copyright 2012 Canonical Ltd. This software is licensed under the
1006-GNU Affero General Public License version 3 (see the file LICENSE).
1007--->
1008-
1009-<html>
1010- <head>
1011- <title>lp.app.banner.privacy Tests</title>
1012-
1013- <!-- YUI and test setup -->
1014- <script type="text/javascript"
1015- src="../../../../../../build/js/yui/yui/yui.js">
1016- </script>
1017- <link rel="stylesheet"
1018- href="../../../../../../build/js/yui/console/assets/console-core.css" />
1019- <link rel="stylesheet"
1020- href="../../../../../../build/js/yui/test-console/assets/skins/sam/test-console.css" />
1021- <link rel="stylesheet"
1022- href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" />
1023-
1024- <script type="text/javascript"
1025- src="../../../../../../build/js/lp/app/testing/testrunner.js"></script>
1026-
1027- <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" />
1028-
1029- <!-- Dependencies -->
1030- <script type="text/javascript"
1031- src="../../../../../../build/js/lp/app/mustache.js"></script>
1032- <script type="text/javascript"
1033- src="../../../../../../build/js/lp/app/banners/banner.js"></script>
1034- <script type="text/javascript"
1035- src="../../../../../../build/js/lp/app/information_type.js"></script>
1036-
1037- <!-- The module under test. -->
1038- <script type="text/javascript" src="../privacy.js"></script>
1039-
1040- <!-- The test suite. -->
1041- <script type="text/javascript" src="test_privacy.js"></script>
1042-
1043- </head>
1044- <body class="yui3-skin-sam">
1045- <ul id="suites">
1046- <li>lp.app.banner.privacy.test</li>
1047- </ul>
1048- </body>
1049-</html>
1050
1051=== removed file 'lib/lp/app/javascript/banners/tests/test_privacy.js'
1052--- lib/lp/app/javascript/banners/tests/test_privacy.js 2012-10-26 10:00:20 +0000
1053+++ lib/lp/app/javascript/banners/tests/test_privacy.js 1970-01-01 00:00:00 +0000
1054@@ -1,117 +0,0 @@
1055-/* Copyright 2011-2012 Canonical Ltd. This software is licensed under the
1056- * GNU Affero General Public License version 3 (see the file LICENSE).
1057- */
1058-
1059-YUI.add('lp.app.banner.privacy.test', function (Y) {
1060-
1061- var tests = Y.namespace('lp.app.banner.privacy.test');
1062- tests.suite = new Y.Test.Suite('lp.app.banner.privacy Tests');
1063-
1064- tests.suite.add(new Y.Test.Case({
1065- name: 'privacy_tests',
1066-
1067- setUp: function () {
1068- var main = Y.Node.create('<div id="maincontent"></div>');
1069- var login_logout = Y.Node.create('<div></div>')
1070- .addClass('login-logout');
1071- main.appendChild(login_logout);
1072-
1073- var banner_node = Y.Node.create('<div></div>')
1074- .addClass('yui3-privacybanner');
1075- main.appendChild(banner_node);
1076- Y.one('body').appendChild(main);
1077- },
1078-
1079- tearDown: function () {
1080- Y.one('#maincontent').remove(true);
1081- window._singleton_privacy_banner = null;
1082- delete window.LP;
1083- },
1084-
1085- test_library_exists: function () {
1086- Y.Assert.isObject(Y.lp.app.banner.privacy,
1087- "Could not locate the lp.app.banner.privacy module");
1088- },
1089- test_init: function () {
1090- var banner = new Y.lp.app.banner.privacy.PrivacyBanner();
1091- Y.Assert.areEqual(
1092- "The information on this page is private.",
1093- banner.get('notification_text'));
1094- Y.Assert.areEqual(
1095- '<span class="sprite notification-private"></span>',
1096- banner.get('banner_icon'));
1097- },
1098-
1099- test_only_one_banner: function () {
1100- // getPrivacyBanner only returns one banner.
1101- var banner = Y.lp.app.banner.privacy.getPrivacyBanner();
1102- Y.Assert.areEqual(1, Y.all('.global-notification').size());
1103-
1104- var new_text = 'This is new text';
1105- banner = Y.lp.app.banner.privacy.getPrivacyBanner(new_text);
1106- Y.Assert.areEqual(1, Y.all('.global-notification').size());
1107- var banner_node = Y.one('.global-notification');
1108- Y.Assert.areEqual(
1109- new_text,
1110- Y.one('.global-notification').get('text'));
1111- },
1112-
1113- test_banner_with_custom_text: function () {
1114- var banner = Y.lp.app.banner.privacy.getPrivacyBanner();
1115- var new_text = 'New custom text';
1116-
1117- Y.fire('privacy_banner:show', {
1118- text: new_text
1119- });
1120- Y.Assert.areEqual(
1121- new_text,
1122- Y.one('.global-notification').get('text'));
1123- Y.Assert.isTrue(banner.get('visible'),
1124- 'Banner should be visible.');
1125- },
1126-
1127- test_banner_hide_event: function () {
1128- var banner = Y.lp.app.banner.privacy.getPrivacyBanner();
1129- var new_text = 'New custom text';
1130-
1131- Y.fire('privacy_banner:show', {
1132- text: new_text
1133- });
1134- Y.fire('privacy_banner:hide');
1135- Y.Assert.isFalse(banner.get('visible'),
1136- 'Banner should not be visible.');
1137- },
1138-
1139- test_info_type_private_event: function () {
1140- var banner = Y.lp.app.banner.privacy.getPrivacyBanner();
1141- var body = Y.one('body');
1142- var msg = 'Some private message';
1143- Y.fire('information_type:is_private', {
1144- text: msg,
1145- value: 'PROPRIETARY'
1146- });
1147- Y.Assert.areEqual(
1148- msg,
1149- Y.one('.global-notification').get('text'));
1150- Y.Assert.isTrue(body.hasClass('private'),
1151- 'Body should be private');
1152- Y.Assert.isTrue(banner.get('visible'),
1153- 'Banner should be visible.');
1154- },
1155-
1156- test_info_type_public_event: function () {
1157- var banner = Y.lp.app.banner.privacy.getPrivacyBanner();
1158- var new_text = 'New custom text';
1159-
1160- Y.fire('privacy_banner:show', {
1161- text: new_text
1162- });
1163- Y.fire('information_type:is_public');
1164- var body = Y.one('body');
1165- Y.Assert.isTrue(body.hasClass('public'), 'Body should be public');
1166- Y.Assert.isFalse(banner.get('visible'),
1167- 'Banner should not be visible.');
1168- }
1169- }));
1170-
1171-}, '0.1', {'requires': ['test', 'test-console', 'lp.app.banner.privacy']});
1172
1173=== modified file 'lib/lp/app/javascript/information_type.js'
1174--- lib/lp/app/javascript/information_type.js 2012-10-04 14:17:23 +0000
1175+++ lib/lp/app/javascript/information_type.js 2012-11-13 15:23:21 +0000
1176@@ -44,6 +44,29 @@
1177 emitFacade: true
1178 });
1179
1180+
1181+/**
1182+ * Provide some logic to check if this is a private inducing event. This could
1183+ * be due to a non-public information type or as security related information
1184+ * type/value.
1185+ */
1186+var is_private_event = function (value) {
1187+ var is_private = false;
1188+ if (ns.get_cache_data_from_key(value,
1189+ 'value',
1190+ 'is_private')) {
1191+
1192+ is_private = true;
1193+ }
1194+
1195+ if (value.indexOf('SECURITY') !== -1) {
1196+ is_private = true;
1197+ }
1198+
1199+ return is_private;
1200+};
1201+
1202+
1203 /**
1204 * Wire up a helper event so that if someone changes the event, we take care
1205 * of also firing any is_private/is_public event shortcuts others want to
1206@@ -58,9 +81,7 @@
1207 throw('Information type change event without new value');
1208 }
1209
1210- if (ns.get_cache_data_from_key(ev.value,
1211- 'value',
1212- 'is_private')) {
1213+ if (is_private_event(ev.value)) {
1214 Y.fire(ns.EV_ISPRIVATE, {
1215 text: ns.get_banner_text(ev.value),
1216 value: ev.value
1217@@ -155,16 +176,33 @@
1218 };
1219
1220 ns.get_banner_text = function(value) {
1221- var text_template = "This page contains {info_type} information.";
1222- var info_type = ns.get_cache_data_from_key(value, 'value', 'name');
1223- return Y.Lang.sub(text_template, {'info_type': info_type});
1224+ // Construct a different message for security related banner content.
1225+ var text;
1226+ if (value.indexOf('SECURITY') !== -1) {
1227+ var security_text = "This report will be private " +
1228+ "because it is a security " +
1229+ "vulnerability. You can " +
1230+ "disclose it later.";
1231+ text = security_text;
1232+ } else {
1233+ var text_template = "This page contains {info_type} information.";
1234+ var info_type = ns.get_cache_data_from_key(value, 'value', 'name');
1235+ text = Y.Lang.sub(text_template, {'info_type': info_type});
1236+ }
1237+ return text;
1238 };
1239
1240 ns.save_success = function(widget, context, value, subscribers_list,
1241 result_data) {
1242 context.information_type =
1243 ns.get_cache_data_from_key(value, 'value', 'name');
1244- ns.update_privacy_banner(value);
1245+
1246+ // Let the world know the information type has been updated. Allows
1247+ // banners to update.
1248+ Y.fire(ns.EV_CHANGE, {
1249+ value: value
1250+ });
1251+
1252 widget._showSucceeded();
1253 if (Y.Lang.isObject(result_data)) {
1254 var subscribers = result_data.subscription_data;
1255@@ -344,27 +382,7 @@
1256 }
1257 };
1258
1259-/**
1260- * Update the privacy banner to display the specified information type value.
1261- *
1262- * @param value
1263- */
1264-ns.update_privacy_banner = function(value) {
1265- var body = Y.one('body');
1266- var privacy_banner = Y.lp.app.banner.privacy.getPrivacyBanner(
1267- undefined, skip_animation);
1268- var private_type = LP.cache.information_type_data[value].is_private;
1269- if (private_type) {
1270- body.replaceClass('public', 'private');
1271- var banner_text = ns.get_banner_text(value);
1272- privacy_banner.updateText(banner_text);
1273- privacy_banner.show();
1274- } else {
1275- body.replaceClass('private', 'public');
1276- privacy_banner.hide();
1277- }
1278-};
1279
1280 }, "0.1", {"requires": [
1281 "base", "oop", "node", "event", "io-base", "lp.mustache", "lp.app.choice",
1282- "lp.bugs.bugtask_index", "lp.app.banner.privacy", "lp.ui.choiceedit"]});
1283+ "lp.bugs.bugtask_index", "lp.ui.choiceedit"]});
1284
1285=== modified file 'lib/lp/app/javascript/tests/test_information_type.js'
1286--- lib/lp/app/javascript/tests/test_information_type.js 2012-10-26 10:00:20 +0000
1287+++ lib/lp/app/javascript/tests/test_information_type.js 2012-11-13 15:23:21 +0000
1288@@ -84,22 +84,6 @@
1289 privacy_link, this.lp_client, LP.cache.bug, null, true);
1290 },
1291
1292- _shim_privacy_banner: function () {
1293- var old_func = Y.lp.app.banner.privacy.getPrivacyBanner;
1294- Y.lp.app.banner.privacy.getPrivacyBanner = function () {
1295- return {
1296- show: function () { Y.fire('test:banner:show'); },
1297- hide: function () { Y.fire('test:banner:hide'); },
1298- updateText: function () { Y.fire('test:banner:update'); }
1299- };
1300- };
1301- return old_func;
1302- },
1303-
1304- _unshim_privacy_banner: function (old_func) {
1305- Y.lp.app.banner.privacy.getPrivacyBanner = old_func;
1306- },
1307-
1308 test_library_exists: function () {
1309 Y.Assert.isObject(Y.lp.app.information_type,
1310 "Cannot locate the lp.app.information_type module");
1311@@ -142,53 +126,9 @@
1312 ns.save_success = orig_save_success;
1313 },
1314
1315- // Setting a private type shows the privacy banner.
1316- test_save_success_private: function() {
1317- this.makeWidget();
1318- var old_func = this._shim_privacy_banner();
1319- var hide_flag = false;
1320- var update_flag = false;
1321- Y.on('test:banner:show', function() {
1322- hide_flag = true;
1323- });
1324- Y.on('test:banner:update', function() {
1325- update_flag = true;
1326- });
1327-
1328- ns.save_success(this.widget, LP.cache.bug,
1329- 'PROPRIETARY');
1330- var body = Y.one('body');
1331- Y.Assert.isTrue(body.hasClass('private'));
1332- Y.Assert.isTrue(hide_flag);
1333- Y.Assert.isTrue(update_flag);
1334- Y.Assert.areEqual(
1335- 'Proprietary', LP.cache.bug.information_type);
1336- this._unshim_privacy_banner(old_func);
1337- },
1338-
1339- // Setting a public type hides the privacy banner.
1340- test_save_success_public: function() {
1341- this.makeWidget();
1342- var old_func = this._shim_privacy_banner();
1343- var flag = false;
1344- Y.on('test:banner:hide', function() {
1345- flag = true;
1346- });
1347- var summary = Y.one('#information-type-summary');
1348- summary.replaceClass('public', 'private');
1349-
1350- ns.save_success(this.widget, 'PUBLIC', 'PUBLIC');
1351- var body = Y.one('body');
1352- Y.Assert.isTrue(body.hasClass('public'));
1353- Y.Assert.isTrue(flag);
1354- Y.Assert.areEqual('Public', LP.cache.bug.information_type);
1355- this._unshim_privacy_banner(old_func);
1356- },
1357-
1358 // A successful save updates the subscribers portlet.
1359 test_save_success_with_subscribers_data: function() {
1360 this.makeWidget();
1361- var old_func = this._shim_privacy_banner();
1362 var flag = false;
1363 Y.on('test:banner:hide', function() {
1364 flag = true;
1365@@ -216,7 +156,6 @@
1366 Y.Assert.isTrue(load_subscribers_called);
1367 Y.Assert.areEqual('value1', window.LP.cache.item1);
1368 Y.Assert.areEqual('value2', window.LP.cache.item2);
1369- this._unshim_privacy_banner(old_func);
1370 },
1371
1372 // A successful save updates the task actions.
1373
1374=== removed file 'lib/lp/app/templates/banner-macros.pt'
1375--- lib/lp/app/templates/banner-macros.pt 2012-05-30 13:59:24 +0000
1376+++ lib/lp/app/templates/banner-macros.pt 1970-01-01 00:00:00 +0000
1377@@ -1,56 +0,0 @@
1378-<macros
1379- xmlns="http://www.w3.org/1999/xhtml"
1380- xmlns:tal="http://xml.zope.org/namespaces/tal"
1381- xmlns:metal="http://xml.zope.org/namespaces/metal"
1382- xmlns:i18n="http://xml.zope.org/namespaces/i18n"
1383- i18n:domain="launchpad"
1384- tal:omit-tag=""
1385->
1386-
1387-<metal:privacy define-macro="privacy-banner">
1388- <tal:show-banner condition="view/private">
1389- <div class="yui3-widget yui3-banner yui3-privacybanner">
1390- <div class="yui3-privacybanner-content">
1391- <div class="global-notification">
1392- <span class="sprite notification-private"></span>
1393- <tal:info_type
1394- define="info_type python: getattr(view, 'information_type', None)">
1395- <span tal:condition="not: info_type" class="banner-text">
1396- The information on this page is private.
1397- </span>
1398- <span tal:condition="info_type" class="banner-text">
1399- <tal:text
1400- content="string: This page contains ${info_type} information."/>
1401- </span>
1402- </tal:info_type>
1403- </div>
1404- </div>
1405- </div>
1406- </tal:show-banner>
1407-</metal:privacy>
1408-
1409-<metal:beta define-macro="beta-banner">
1410- <tal:show-banner condition="view/beta_features">
1411- <div class="yui3-widget yui3-banner yui3-betabanner">
1412- <div class="yui3-betabanner-content">
1413- <div class="global-notification">
1414- <span class="beta-warning">BETA!</span>
1415- <span class="banner-text">
1416- Some parts of this page are in beta:&nbsp;
1417- <span class="beta-feature">
1418- <tal:features
1419- repeat="feature view/beta_features">
1420- <tal:feature replace="feature/title" />
1421- <tal:link condition="feature/url">
1422- (<a tal:attributes="href feature/url" class="info-link">read more</a>)
1423- </tal:link>
1424- </tal:features>
1425- </span>
1426- </span>
1427- </div>
1428- </div>
1429- </div>
1430- </tal:show-banner>
1431-</metal:beta>
1432-
1433-</macros>
1434
1435=== modified file 'lib/lp/app/templates/base-layout-macros.pt'
1436--- lib/lp/app/templates/base-layout-macros.pt 2012-08-13 17:49:31 +0000
1437+++ lib/lp/app/templates/base-layout-macros.pt 2012-11-13 15:23:21 +0000
1438@@ -163,19 +163,17 @@
1439 <script id="base-layout-load-scripts" type="text/javascript">
1440 //<![CDATA[
1441 LPJS.use('base', 'node', 'console', 'event',
1442- 'oop', 'lp', 'lp.app.banner.privacy',
1443- 'lp.app.banner.beta', 'lp.app.foldables','lp.app.sorttable',
1444+ 'oop', 'lp', 'lp.app.foldables','lp.app.sorttable',
1445 'lp.app.inlinehelp', 'lp.app.links', 'lp.app.longpoll',
1446 'lp.bugs.bugtask_index', 'lp.bugs.subscribers',
1447 'lp.app.ellipsis', 'lp.code.branchmergeproposal.diff',
1448+ 'lp.views.global',
1449 function(Y) {
1450
1451 Y.on("domready", function () {
1452- if (Y.one(document.body).hasClass('private')) {
1453- banner = Y.lp.app.banner.privacy.getPrivacyBanner();
1454- banner.show();
1455- }
1456- Y.lp.app.banner.beta.show_beta_if_needed();
1457+ var global_view = new Y.lp.views.Global();
1458+ global_view.render();
1459+
1460 Y.lp.app.sorttable.SortTable.init();
1461 Y.lp.app.inlinehelp.init_help();
1462 Y.lp.activate_collapsibles();
1463
1464=== modified file 'lib/lp/app/templates/base-layout.pt'
1465--- lib/lp/app/templates/base-layout.pt 2012-05-18 22:04:13 +0000
1466+++ lib/lp/app/templates/base-layout.pt 2012-11-13 15:23:21 +0000
1467@@ -64,6 +64,16 @@
1468 ${view/macro:pagetype}
1469 ${view/fmt:global-css}
1470 yui3-skin-sam">
1471+ <tal:beta-banner condition="view/beta_features">
1472+ <div class="beta_banner_container">
1473+ <noscript ><strong>Some parts of this page are in beta.</strong></noscript>
1474+ </div>
1475+ </tal:beta-banner>
1476+ <tal:private-banner condition="view/private">
1477+ <div class="private_banner_container">
1478+ <noscript><strong>The information on this page is private.</strong></noscript>
1479+ </div>
1480+ </tal:private-banner>
1481 <script type="text/javascript"
1482 tal:condition="python: is_lpnet">
1483 var _gaq = _gaq || [];
1484@@ -97,10 +107,6 @@
1485 <div class="yui-t4"
1486 tal:omit-tag="not: view/macro:pagehas/portlets">
1487 <div id="maincontent" class="yui-main">
1488- <metal:privacy-banner
1489- use-macro="view/@@+banner-macros/beta-banner"/>
1490- <metal:privacy-banner
1491- use-macro="view/@@+banner-macros/privacy-banner"/>
1492 <div class="yui-b"
1493 tal:attributes="
1494 lang view/lang|default_language|default;
1495
1496=== modified file 'lib/lp/blueprints/browser/tests/test_specification.py'
1497--- lib/lp/blueprints/browser/tests/test_specification.py 2012-10-15 23:20:25 +0000
1498+++ lib/lp/blueprints/browser/tests/test_specification.py 2012-11-13 15:23:21 +0000
1499@@ -256,7 +256,7 @@
1500 with person_logged_in(owner):
1501 browser = self.getViewBrowser(spec, user=owner)
1502 privacy_banner = soupmatchers.Tag('privacy-banner', True,
1503- attrs={'class': 'banner-text'})
1504+ attrs={'class': 'private_banner_container'})
1505 self.assertThat(browser.contents,
1506 soupmatchers.HTMLContains(privacy_banner))
1507
1508@@ -312,7 +312,7 @@
1509 self.assertEqual(InformationType.PUBLIC, spec.information_type)
1510
1511 def test_view_banner(self):
1512- """The privacy banner should reflect the information_type."""
1513+ """The privacy banner should contain a noscript message"""
1514 owner = self.factory.makePerson()
1515 policy = SpecificationSharingPolicy.PUBLIC_OR_PROPRIETARY
1516 product = self.factory.makeProduct(
1517@@ -323,8 +323,7 @@
1518 product=product)
1519
1520 privacy_banner = soupmatchers.Tag('privacy-banner', True,
1521- attrs={'class': 'banner-text'},
1522- text=re.compile('This page contains Proprietary information'))
1523+ text=re.compile('The information on this page is private'))
1524
1525 getUtility(IService, 'sharing').ensureAccessGrants(
1526 [owner], owner, specifications=[spec],
1527
1528=== modified file 'lib/lp/blueprints/javascript/addspec.js'
1529--- lib/lp/blueprints/javascript/addspec.js 2012-10-15 16:01:38 +0000
1530+++ lib/lp/blueprints/javascript/addspec.js 2012-11-13 15:23:21 +0000
1531@@ -10,11 +10,24 @@
1532
1533 var namespace = Y.namespace('lp.blueprints.addspec');
1534 var to_choice = Y.lp.app.information_type.cache_to_choicesource;
1535+var info_type = Y.lp.app.information_type;
1536
1537 namespace.set_up = function () {
1538 var choice_data = to_choice(LP.cache.information_type_data);
1539- Y.lp.app.choice.addPopupChoiceForRadioButtons('information_type',
1540- choice_data);
1541+ var widget = Y.lp.app.choice.addPopupChoiceForRadioButtons(
1542+ 'information_type',
1543+ choice_data);
1544+
1545+ // We are not doing ajax saves of the information type so we need to
1546+ // disable the flash on save for the widget.
1547+ widget.set('flashEnabled', false);
1548+
1549+ // Make sure we catch changes to the information type.
1550+ widget.on('save', function (ev) {
1551+ Y.fire(info_type.EV_CHANGE, {
1552+ value: ev.target.get('value')
1553+ });
1554+ });
1555 };
1556
1557 }, "0.1", {"requires": ['lp.app.information_type', 'lp.app.choice']});
1558
1559=== modified file 'lib/lp/bugs/javascript/bugtask_index.js'
1560--- lib/lp/bugs/javascript/bugtask_index.js 2012-10-11 04:57:59 +0000
1561+++ lib/lp/bugs/javascript/bugtask_index.js 2012-11-13 15:23:21 +0000
1562@@ -1131,6 +1131,5 @@
1563 "lp.app.information_type",
1564 "lp.app.widgets.expander", "lp.client", "escape",
1565 "lp.client.plugins", "lp.app.errors",
1566- "lp.app.banner.privacy",
1567 "lp.app.confirmationoverlay",
1568 "lp.bugs.duplicates"]});
1569
1570=== modified file 'lib/lp/bugs/javascript/filebug.js'
1571--- lib/lp/bugs/javascript/filebug.js 2012-09-25 19:15:04 +0000
1572+++ lib/lp/bugs/javascript/filebug.js 2012-11-13 15:23:21 +0000
1573@@ -9,6 +9,7 @@
1574 YUI.add('lp.bugs.filebug', function(Y) {
1575
1576 var namespace = Y.namespace('lp.bugs.filebug');
1577+var info_type = Y.lp.app.information_type;
1578
1579 // For tests.
1580 var skip_animation;
1581@@ -28,13 +29,40 @@
1582 if (Y.Lang.isValue(search_button )) {
1583 search_button.set('value', 'Check again');
1584 }
1585+ setup_plain_inputs();
1586 set_default_privacy_banner();
1587- setup_information_type();
1588 setup_security_related();
1589 setupChoiceWidgets();
1590 }
1591 };
1592
1593+
1594+/**
1595+ * If there are not choice widgets, but radio buttons, then we should watch
1596+ * those radio buttons for change to make sure we fire the information type
1597+ * change events.
1598+ */
1599+var setup_plain_inputs = function () {
1600+ var itypes_table = Y.one('.radio-button-widget');
1601+
1602+ if (itypes_table) {
1603+ itypes_table.delegate('change', function(ev) {
1604+ Y.fire(info_type.EV_CHANGE, {
1605+ value: this.get('value')
1606+ });
1607+ }, "input[name='field.information_type']");
1608+ }
1609+};
1610+
1611+/**
1612+ * Due to the privacy setting of the project/bugs we might only allow a
1613+ * non-public information type. In this case we need to go ahead and let the
1614+ * user know it's going to be private.
1615+ *
1616+ * This is used by the security checks. If the issue is unmade/not security
1617+ * related then we need to check the normal default behavior to make sure we
1618+ * show the correct banner.
1619+ */
1620 var set_default_privacy_banner = function() {
1621 var itypes_table = Y.one('.radio-button-widget');
1622 var val = null;
1623@@ -48,47 +76,12 @@
1624 if (LP.cache.bug_private_by_default) {
1625 var filebug_privacy_text = "This report will be private. " +
1626 "You can disclose it later.";
1627- update_privacy_banner(true, filebug_privacy_text);
1628- } else {
1629- update_banner_from_information_type(val);
1630- }
1631-};
1632-
1633-var update_privacy_banner = function(show, banner_text) {
1634- var banner = Y.lp.app.banner.privacy.getPrivacyBanner(
1635- banner_text, skip_animation);
1636- if (show) {
1637- banner.show();
1638- } else {
1639- banner.hide();
1640- }
1641-};
1642-
1643-var get_new_banner_text = function(value) {
1644- var cache = LP.cache.information_type_data;
1645- var text_template = "This report contains {info_type} information." +
1646- " You can change the information type later.";
1647- return Y.Lang.substitute(text_template, {
1648- 'info_type': cache[value].name
1649- });
1650-};
1651-
1652-var update_banner_from_information_type = function(value) {
1653- var banner_text = get_new_banner_text(value);
1654- var is_private = LP.cache.information_type_data[value].is_private;
1655- update_privacy_banner(is_private, banner_text);
1656-};
1657-
1658-var setup_information_type = function() {
1659- var itypes_table = Y.one('.radio-button-widget');
1660- if (!Y.Lang.isValue(itypes_table)) {
1661- return;
1662- }
1663-
1664-
1665- itypes_table.delegate('change', function() {
1666- update_banner_from_information_type(this.get('value'));
1667- }, "input[name='field.information_type']");
1668+
1669+ Y.fire(info_type.EV_ISPRIVATE, {
1670+ text: filebug_privacy_text,
1671+ value: val
1672+ });
1673+ }
1674 };
1675
1676
1677@@ -100,8 +93,25 @@
1678 var information_helpers = Y.lp.app.information_type;
1679 var choices = information_helpers.cache_to_choicesource(cache);
1680
1681- Y.lp.app.choice.addPopupChoiceForRadioButtons(
1682+ var information_type = Y.lp.app.choice.addPopupChoiceForRadioButtons(
1683 'information_type', choices, true);
1684+
1685+ // When dealing with legacy inputs the information type could have not
1686+ // been created and we get back a null value.
1687+ if (information_type) {
1688+ // We are not doing ajax saves of the information type so we need to
1689+ // disable the flash on save for the widget.
1690+ information_type.set('flashEnabled', false);
1691+
1692+ // When the information type widget changes we need to let the
1693+ // information type module know so it can process the change and
1694+ // update things like banners displayed.
1695+ information_type.on('save', function (ev) {
1696+ Y.fire(info_type.EV_CHANGE, {
1697+ value: ev.target.get('value')
1698+ });
1699+ });
1700+ }
1701 };
1702
1703 var setup_security_related = function() {
1704@@ -116,8 +126,20 @@
1705 security_related.on('change', function() {
1706 var checked = security_related.get('checked');
1707 if (checked) {
1708- update_privacy_banner(true, notification_text);
1709+ // XXX: Bug #1078054
1710+ // This should use the correct information type based on the
1711+ // project default. We use PRIVATESECURITY because it'll get the
1712+ // right banner shown.
1713+ Y.fire(info_type.EV_ISPRIVATE, {
1714+ text: notification_text,
1715+ value: 'PRIVATESECURITY'
1716+ });
1717 } else {
1718+ Y.fire(info_type.EV_ISPUBLIC, {
1719+ value: 'PUBLIC'
1720+ });
1721+ // Check with the default settings if we should add the privacy
1722+ // banner back because it's the default of the current project.
1723 set_default_privacy_banner();
1724 }
1725 });
1726@@ -127,5 +149,5 @@
1727
1728 }, "0.1", {"requires": [
1729 "base", "node", "event", "node-event-delegate", "lp.ui.choiceedit",
1730- "lp.app.banner.privacy", "lp.app.choice", "lp.app.information_type",
1731+ "lp.ui.banner", "lp.app.choice", "lp.app.information_type",
1732 "lp.bugs.filebug_dupefinder"]});
1733
1734=== modified file 'lib/lp/bugs/javascript/tests/test_filebug.js'
1735--- lib/lp/bugs/javascript/tests/test_filebug.js 2012-10-26 10:00:20 +0000
1736+++ lib/lp/bugs/javascript/tests/test_filebug.js 2012-11-13 15:23:21 +0000
1737@@ -3,6 +3,8 @@
1738 YUI.add('lp.bugs.filebug.test', function (Y) {
1739
1740 var tests = Y.namespace('lp.bugs.filebug.test');
1741+ var info_type = Y.lp.app.information_type;
1742+
1743 tests.suite = new Y.Test.Suite(
1744 'lp.bugs.filebug Tests');
1745
1746@@ -73,96 +75,136 @@
1747
1748 // Filing a public bug does not show the privacy banner.
1749 test_setup_filebug_public: function () {
1750+ // Watch out for the event that showing a privacy banner would
1751+ // fire.
1752+ var fired = false;
1753+ var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) {
1754+ fired = true;
1755+ });
1756 this.setupForm(true);
1757- var banner_hidden = Y.one('.yui3-privacybanner-hidden');
1758- Y.Assert.isNotNull(banner_hidden);
1759+ Y.Assert.isFalse(fired);
1760+ ev.detach();
1761 },
1762
1763 // Filing a bug for a project with private bugs shows the privacy
1764 // banner.
1765 test_setup_filebug_private: function () {
1766+ var fired = false;
1767+ var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) {
1768+ fired = true;
1769+ Y.Assert.areEqual(
1770+ 'This report will be private. ' +
1771+ 'You can disclose it later.', ev.text);
1772+ });
1773+
1774 window.LP.cache.bug_private_by_default = true;
1775 this.setupForm(true);
1776- var banner_hidden = Y.one('.yui3-privacybanner-hidden');
1777- Y.Assert.isNull(banner_hidden);
1778- var banner_text = Y.one('.banner-text').get('text');
1779- Y.Assert.areEqual(
1780- 'This report will be private. ' +
1781- 'You can disclose it later.', banner_text);
1782+ Y.Assert.isTrue(fired);
1783+ ev.detach();
1784 },
1785
1786 // Selecting a private info type using the legacy radio buttons
1787 // turns on the privacy banner.
1788 test_legacy_select_private_info_type: function () {
1789+ var fired = false;
1790+ var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) {
1791+ fired = true;
1792+ Y.Assert.areEqual(
1793+ 'This report will be private because it is a security ' +
1794+ 'vulnerability. You can disclose it later.', ev.text);
1795+ });
1796+
1797 this.setupForm(true);
1798- var banner_hidden = Y.one('.yui3-privacybanner-hidden');
1799- Y.Assert.isNotNull(banner_hidden);
1800+ Y.Assert.isFalse(fired);
1801+
1802 Y.one('[id="field.information_type.2"]').simulate('click');
1803- banner_hidden = Y.one('.yui3-privacybanner-hidden');
1804- Y.Assert.isNull(banner_hidden);
1805- var banner_text = Y.one('.banner-text').get('text');
1806- Y.Assert.areEqual(
1807- 'This report contains Private Security information. ' +
1808- 'You can change the information type later.', banner_text);
1809+ // And the event should be fired and caught.
1810+ Y.Assert.isTrue(fired);
1811+ ev.detach();
1812 },
1813
1814 // Selecting a public info type using the legacy radio buttons
1815 // turns off the privacy banner.
1816 test_legacy_select_public_info_type: function () {
1817+ var fired = false;
1818+ var ev = Y.on(info_type.EV_ISPUBLIC, function (ev) {
1819+ fired = true;
1820+ });
1821+
1822 window.LP.cache.bug_private_by_default = true;
1823 this.setupForm(true);
1824+
1825+ // This will fire ISPRIVATE and a banner shows.
1826 Y.one('[id="field.information_type.2"]').simulate('click');
1827- var banner_hidden = Y.one('.yui3-privacybanner-hidden');
1828- Y.Assert.isNull(banner_hidden);
1829+
1830+ // The second one will fire ISPUBLIC and the banner disappears.
1831 Y.one('[id="field.information_type.0"]').simulate('click');
1832- banner_hidden = Y.one('.yui3-privacybanner-hidden');
1833- Y.Assert.isNotNull(banner_hidden);
1834+ Y.Assert.isTrue(fired);
1835 },
1836
1837 // When non bug supervisors select a security related bug the privacy
1838 // banner is turned on.
1839 test_select_security_related: function () {
1840+ var fired = false;
1841+ var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) {
1842+ fired = true;
1843+ Y.Assert.areEqual(
1844+ 'This report will be private because it is a security ' +
1845+ 'vulnerability. You can disclose it later.', ev.text);
1846+ });
1847+
1848 this.setupForm(false);
1849- var banner_hidden = Y.one('.yui3-privacybanner-hidden');
1850- Y.Assert.isNotNull(banner_hidden);
1851+ Y.Assert.isFalse(fired);
1852+
1853 Y.one('[id="field.security_related"]').simulate('click');
1854- banner_hidden = Y.one('.yui3-privacybanner-hidden');
1855- Y.Assert.isNull(banner_hidden);
1856- var banner_text = Y.one('.banner-text').get('text');
1857- Y.Assert.areEqual(
1858- 'This report will be private because it is a ' +
1859- 'security vulnerability. You can disclose it later.',
1860- banner_text);
1861+ // And the event should be fired and caught.
1862+ Y.Assert.isTrue(fired);
1863+ ev.detach();
1864 },
1865
1866 // When non bug supervisors unselect a security related bug the privacy
1867 // banner is turned off.
1868 test_unselect_security_related: function () {
1869+ var fired = false;
1870+ var ev = Y.on(info_type.EV_ISPUBLIC, function (ev) {
1871+ fired = true;
1872+ });
1873+
1874 this.setupForm(false);
1875- Y.one('[id="field.security_related"]').simulate('click');
1876- var banner_hidden = Y.one('.yui3-privacybanner-hidden');
1877- Y.Assert.isNull(banner_hidden);
1878- Y.one('[id="field.security_related"]').simulate('click');
1879- banner_hidden = Y.one('.yui3-privacybanner-hidden');
1880- Y.Assert.isNotNull(banner_hidden);
1881+
1882+ Y.one('[id="field.security_related"]').simulate('click');
1883+ Y.Assert.isFalse(fired);
1884+
1885+ Y.one('[id="field.security_related"]').simulate('click');
1886+ Y.Assert.isTrue(fired);
1887 },
1888
1889 // When non bug supervisors unselect a security related bug the privacy
1890 // banner remains on for private_by_default bugs.
1891 test_unselect_security_related_default_private: function () {
1892 window.LP.cache.bug_private_by_default = true;
1893+ var public = 0;
1894+ var private = 0;
1895+ var ev = Y.on(info_type.EV_ISPUBLIC, function (ev) {
1896+ public = public + 1;
1897+ });
1898+
1899+ var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) {
1900+ private = private + 1;
1901+ });
1902+
1903+
1904 this.setupForm(false);
1905- Y.one('[id="field.security_related"]').simulate('click');
1906- var banner_hidden = Y.one('.yui3-privacybanner-hidden');
1907- Y.Assert.isNull(banner_hidden);
1908- Y.one('[id="field.security_related"]').simulate('click');
1909- banner_hidden = Y.one('.yui3-privacybanner-hidden');
1910- Y.Assert.isNull(banner_hidden);
1911- var banner_text = Y.one('.banner-text').get('text');
1912+ Y.Assert.areEqual(1, private, 'Private is the default state.');
1913+
1914+ Y.one('[id="field.security_related"]').simulate('click');
1915+ Y.Assert.areEqual(2, private, 'The first click fires ISPRIVATE');
1916+
1917+ Y.one('[id="field.security_related"]').simulate('click');
1918+ Y.Assert.areEqual(1, public, 'The second click fires ISPUBLIC');
1919 Y.Assert.areEqual(
1920- 'This report will be private. ' +
1921- 'You can disclose it later.',
1922- banner_text);
1923+ 3, private,
1924+ "It also fires an ISPRIVATE since that's the default state.");
1925 },
1926
1927 // The dupe finder functionality is setup.
1928@@ -280,44 +322,59 @@
1929 // Selecting a private info type using the popup choice widget
1930 // turns on the privacy banner.
1931 test_select_private_info_type: function () {
1932+ var fired = false;
1933+ var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) {
1934+ fired = true;
1935+ Y.Assert.areEqual(
1936+ 'This report contains Private information. ' +
1937+ 'You can change the information type later.', ev.text);
1938+ });
1939+
1940 this.setupForm(true);
1941- var banner_hidden = Y.one('.yui3-privacybanner-hidden');
1942- Y.Assert.isNotNull(banner_hidden);
1943+ Y.Assert.isFalse(fired);
1944+
1945 var information_type_popup = Y.one('.information_type-content a');
1946 information_type_popup.simulate('click');
1947 var information_type_choice = Y.one(
1948 '.yui3-ichoicelist-content a[href="#USERDATA"]');
1949 information_type_choice.simulate('click');
1950- banner_hidden = Y.one('.yui3-privacybanner-hidden');
1951- Y.Assert.isNull(banner_hidden);
1952- var banner_text = Y.one('.banner-text').get('text');
1953- Y.Assert.areEqual(
1954- 'This report contains Private information. ' +
1955- 'You can change the information type later.', banner_text);
1956+
1957+ // And the event should be fired and caught.
1958+ Y.Assert.isTrue(fired);
1959+ ev.detach();
1960 },
1961
1962 // Selecting a public info type using the popup choice widget
1963 // turns off the privacy banner.
1964 test_select_public_info_type: function () {
1965+ var fired = false;
1966+ var ev = Y.on(info_type.EV_ISPUBLIC, function (ev) {
1967+ fired = true;
1968+ });
1969+
1970 window.LP.cache.bug_private_by_default = true;
1971 this.setupForm(true);
1972+
1973+ // This will fire ISPRIVATE and a banner shows.
1974 var information_type_popup = Y.one('.information_type-content a');
1975 information_type_popup.simulate('click');
1976 var information_type_choice = Y.one(
1977 '.yui3-ichoicelist-content a[href="#USERDATA"]');
1978 information_type_choice.simulate('click');
1979- var banner_hidden = Y.one('.yui3-privacybanner-hidden');
1980- Y.Assert.isNull(banner_hidden);
1981+
1982+ // The second one will fire ISPUBLIC and the banner disappears.
1983 information_type_popup.simulate('click');
1984 information_type_choice = Y.one(
1985 '.yui3-ichoicelist-content a[href="#PUBLIC"]');
1986 information_type_choice.simulate('click');
1987- banner_hidden = Y.one('.yui3-privacybanner-hidden');
1988- Y.Assert.isNotNull(banner_hidden);
1989+
1990+ Y.Assert.isTrue(fired);
1991 }
1992 }));
1993
1994-}, '0.1', {'requires': ['test', 'test-console', 'event', 'node-event-simulate',
1995- 'lp.app.banner.privacy', 'lp.app.choice',
1996- 'lp.bugs.filebug_dupefinder', 'lp.bugs.filebug'
1997- ]});
1998+}, '0.1', {
1999+ requires: [
2000+ 'test', 'test-console', 'event', 'node-event-simulate',
2001+ 'lp.app.banner.privacy', 'lp.app.choice', 'lp.app.information_type',
2002+ 'lp.bugs.filebug_dupefinder', 'lp.bugs.filebug' ]
2003+});
2004
2005=== modified file 'lib/lp/code/javascript/branch.information_type_choice.js'
2006--- lib/lp/code/javascript/branch.information_type_choice.js 2012-09-21 15:39:22 +0000
2007+++ lib/lp/code/javascript/branch.information_type_choice.js 2012-11-13 15:23:21 +0000
2008@@ -105,7 +105,9 @@
2009 LP.cache.context.information_type =
2010 information_type.get_cache_data_from_key(
2011 value, 'value', 'name');
2012- information_type.update_privacy_banner(value);
2013+ Y.fire(information_type.EV_CHANGE, {
2014+ value: value
2015+ });
2016 if (this.get('use_animation')) {
2017 this.information_type_edit._showSucceeded();
2018 }
2019@@ -119,7 +121,8 @@
2020 }
2021 });
2022
2023-}, "0.1", {"requires": ["base", "oop", "node", "event", "io-base",
2024- "lp.ui.choiceedit", "lp.app.banner.privacy",
2025- "lp.app.errors", "lp.app.choice",
2026- "lp.app.information_type"]});
2027+}, "0.1", {
2028+ requires: [
2029+ "base", "oop", "node", "event", "io-base", "lp.ui.choiceedit",
2030+ "lp.app.errors", "lp.app.choice", "lp.app.information_type"]
2031+});
2032
2033=== modified file 'lib/lp/code/javascript/tests/test_information_type_choice.js'
2034--- lib/lp/code/javascript/tests/test_information_type_choice.js 2012-10-26 10:00:20 +0000
2035+++ lib/lp/code/javascript/tests/test_information_type_choice.js 2012-11-13 15:23:21 +0000
2036@@ -4,6 +4,8 @@
2037
2038 var tests = Y.namespace('lp.code.branch.information_type_choice.test');
2039 var ns = Y.lp.code.branch.information_type_choice;
2040+ var info_type = Y.lp.app.information_type;
2041+
2042 tests.suite = new Y.Test.Suite(
2043 'lp.code.branch.information_type_choice Tests');
2044
2045@@ -62,22 +64,6 @@
2046 this.widget.render();
2047 },
2048
2049- _shim_privacy_banner: function () {
2050- var old_func = Y.lp.app.banner.privacy.getPrivacyBanner;
2051- Y.lp.app.banner.privacy.getPrivacyBanner = function () {
2052- return {
2053- show: function () { Y.fire('test:banner:show'); },
2054- hide: function () { Y.fire('test:banner:hide'); },
2055- updateText: function () { Y.fire('test:banner:update'); }
2056- };
2057- };
2058- return old_func;
2059- },
2060-
2061- _unshim_privacy_banner: function (old_func) {
2062- Y.lp.app.banner.privacy.getPrivacyBanner = old_func;
2063- },
2064-
2065 test_library_exists: function () {
2066 Y.Assert.isObject(Y.lp.code.branch.information_type_choice,
2067 "Cannot locate the " +
2068@@ -118,44 +104,31 @@
2069
2070 // Setting a private type shows the privacy banner.
2071 test_information_type_save_success_private: function() {
2072+ var fired = false;
2073+ Y.on(info_type.EV_ISPRIVATE, function (ev) {
2074+ fired = true;
2075+ });
2076+
2077 this.makeWidget();
2078- var old_func = this._shim_privacy_banner();
2079- var hide_flag = false;
2080- var update_flag = false;
2081- Y.on('test:banner:show', function() {
2082- hide_flag = true;
2083- });
2084- Y.on('test:banner:update', function() {
2085- update_flag = true;
2086- });
2087
2088 this.widget._information_type_save_success('PROPRIETARY');
2089- var body = Y.one('body');
2090- Y.Assert.isTrue(body.hasClass('private'));
2091- Y.Assert.isTrue(hide_flag);
2092- Y.Assert.isTrue(update_flag);
2093+ Y.Assert.isTrue(fired);
2094 Y.Assert.areEqual(
2095 'Proprietary', LP.cache.context.information_type);
2096- this._unshim_privacy_banner(old_func);
2097 },
2098
2099 // Setting a private type hides the privacy banner.
2100 test_information_type_save_success_public: function() {
2101+ var fired = false;
2102+ Y.on(info_type.EV_ISPUBLIC, function (ev) {
2103+ fired = true;
2104+ });
2105+
2106 this.makeWidget();
2107- var old_func = this._shim_privacy_banner();
2108- var flag = false;
2109- Y.on('test:banner:hide', function() {
2110- flag = true;
2111- });
2112- var summary = Y.one('#information-type-summary');
2113- summary.replaceClass('public', 'private');
2114
2115 this.widget._information_type_save_success('PUBLIC');
2116- var body = Y.one('body');
2117- Y.Assert.isTrue(body.hasClass('public'));
2118- Y.Assert.isTrue(flag);
2119+ Y.Assert.isTrue(fired);
2120 Y.Assert.areEqual('Public', LP.cache.context.information_type);
2121- this._unshim_privacy_banner(old_func);
2122 },
2123
2124 // Test error handling when a save fails.
2125
2126=== modified file 'lib/lp/registry/javascript/product_views.js'
2127--- lib/lp/registry/javascript/product_views.js 2012-10-26 06:59:14 +0000
2128+++ lib/lp/registry/javascript/product_views.js 2012-11-13 15:23:21 +0000
2129@@ -95,6 +95,9 @@
2130 */
2131 information_type_change: function (value) {
2132 toggle_license_field(value);
2133+ Y.fire(info_type.EV_CHANGE, {
2134+ value: value
2135+ });
2136 },
2137
2138 /**
2139@@ -349,6 +352,9 @@
2140 */
2141 information_type_change: function (value) {
2142 toggle_license_field(value);
2143+ Y.fire(info_type.EV_CHANGE, {
2144+ value: value
2145+ });
2146 var driver_cont =
2147 Y.one('input[name="field.driver"]').ancestor('td');
2148 var bug_super_cont =
2149
2150=== modified file 'lib/lp/services/features/flags.py'
2151--- lib/lp/services/features/flags.py 2012-11-08 06:06:22 +0000
2152+++ lib/lp/services/features/flags.py 2012-11-13 15:23:21 +0000
2153@@ -236,7 +236,7 @@
2154 'boolean',
2155 'If true, enabled access to private project registration features.',
2156 'disabled',
2157- '',
2158+ 'Allow registering a non-public project.',
2159 'http://blog.launchpad.net/general/private-projects-beta'),
2160 ('disclosure.private_project.traversal_override',
2161 'boolean',