Merge lp:~jcsackett/launchpad/simplify-everything into lp:launchpad

Proposed by j.c.sackett
Status: Merged
Approved by: Curtis Hovey
Approved revision: no longer in the source branch.
Merged at revision: 15304
Proposed branch: lp:~jcsackett/launchpad/simplify-everything
Merge into: lp:launchpad
Diff against target: 353 lines (+96/-92)
7 files modified
lib/lp/app/javascript/banners/banner.js (+14/-22)
lib/lp/app/javascript/banners/beta-notification.js (+14/-14)
lib/lp/app/javascript/banners/privacy.js (+7/-4)
lib/lp/app/javascript/banners/tests/test_banner.js (+10/-19)
lib/lp/app/javascript/banners/tests/test_privacy.js (+14/-0)
lib/lp/app/templates/banner-macros.pt (+27/-23)
lib/lp/bugs/templates/bugtarget-macros-filebug.pt (+10/-10)
To merge this branch: bzr merge lp:~jcsackett/launchpad/simplify-everything
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code Approve
Review via email: mp+107240@code.launchpad.net

Commit message

Simplifies the progressive enhancement and other uses of the global-notification banners.

Description of the change

Summary
=======
The previous work to make the banners work without js involved using an overly
complicated renderUI sequence that would replace existing HTML with the new
banner, but would have multiple banner objects. This branch massively
simplifies things by removing that bit of goofiness and using YUI's widget
srcNode attribute to safely reuse the html.

UPDATE: This also fixes a regression introduced by earlier banner work; after
the first banner.js branch landed +filebug was special cased in such a way that
it failed to work properly with private-by-default projects. Since this removes
the special casing, it has restored the functionality.

Preimp
======
Continuation of earlier work discussed with Curtis Hovey and Rick Harding.

Implementation
==============
The _createBanner and _updateBanner methods are discarded. _createBanner is
merged with renderUI; _updateBanner becomes updateText, since that's really
all it does.

The banner_id attribute and its uses are removed, most notably in the template
banner.

The beta banner is switched to using the same singleton banner as the privacy
banner, since it too exists as only one instance per page.

Both the beta banner and privacy banner are updated to get srcNode within
their wrapper functions. This can be null, b/c Y.Widget handles null srcNodes,
which just indicates that there's no html to update.

The privacy banner wrapper has been updated to use updateText to set new
banner texts instead of the config on the initializer. All calls to the
PrivacyBanner now use the wrapper.

test_only_one_banner is deleted, b/c it's not needed.

test_updateText is added.

test_privacy gets a test_only_one banner, which uses the wrapper function to
verify that only banner is created.

The html in banner-macros is updated to correspond exactly to the html
generated by the widgets, less the dynamically generated IDs from YUI.

Tests
=====
bin/test -vvc -t beta -t banner -t privacy -t type_choice --layer=YUI

QA
==
Confirm that no-js and js use of privacy and beta banners doesn't change.

Confirm that the banner shows up on +filebug for private-by-default projects.

LoC
===
This is part of disclosure work.

Lint
====

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/app/javascript/banners/beta-notification.js
  lib/lp/app/javascript/banners/tests/test_banner.js
  lib/lp/app/javascript/banners/banner.js
  lib/lp/bugs/templates/bugtarget-macros-filebug.pt
  lib/lp/app/templates/banner-macros.pt
  lib/lp/app/javascript/banners/privacy.js
  lib/lp/app/javascript/banners/tests/test_privacy.js

./lib/lp/app/templates/banner-macros.pt
      41: mismatched tag

I believe this lint error is wrong; line 41 is a closing div that looks
matched. The reviewr is invited to tell me I'm wrong if they can see the
issue, in which case I'll fix it. I just don't see it, and macro compilation
still works.

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

Lovely thank you.

review: Approve (code)
Revision history for this message
Curtis Hovey (sinzui) wrote :

Oh, I see the link error. the second to last <span> tag is OPEN. It should be CLOSED.

Revision history for this message
j.c.sackett (jcsackett) wrote :

Thanks, fixed that!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/app/javascript/banners/banner.js'
--- lib/lp/app/javascript/banners/banner.js 2012-05-18 20:10:14 +0000
+++ lib/lp/app/javascript/banners/banner.js 2012-05-24 20:50:26 +0000
@@ -93,30 +93,15 @@
93 login_space.run();93 login_space.run();
94 },94 },
9595
96 _createBanner: function () {96 renderUI: function () {
97 var banner_data = {97 var banner_data = {
98 badge: this.get('banner_icon'),98 badge: this.get('banner_icon'),
99 text: this.get('notification_text'),99 text: this.get('notification_text'),
100 banner_id: this.get('banner_id')
101 };100 };
102 return Y.lp.mustache.to_html(101 var banner_html = Y.lp.mustache.to_html(
103 this.get('banner_template'),102 this.get('banner_template'),
104 banner_data);103 banner_data);
105 },104 this.get('contentBox').append(banner_html);
106
107 _updateBanner: function (banner_node) {
108 text_node = banner_node.one('.banner-text');
109 text_node.set('innerText', this.get('notification_text'));
110 },
111
112 renderUI: function() {
113 var existing_banner = Y.one('#' + this.get('banner_id'));
114 if (existing_banner) {
115 this._updateBanner(existing_banner);
116 } else {
117 var banner_html = this._createBanner();
118 this.get('contentBox').append(banner_html);
119 }
120 },105 },
121106
122 bindUI: function() {107 bindUI: function() {
@@ -127,17 +112,24 @@
127 this._hideBanner(); 112 this._hideBanner();
128 }113 }
129 }); 114 });
130 }115 },
116
117 updateText: function (new_text) {
118 if (!Y.Lang.isValue(new_text)) {
119 new_text = this.get('notification_text');
120 }
121 text_node = this.get('contentBox').one('.banner-text');
122 text_node.set('innerText', new_text);
123 },
124
131}, {125}, {
132 ATTRS: {126 ATTRS: {
133 banner_id: { value: "base-banner" },
134 notification_text: { value: "" },127 notification_text: { value: "" },
135 banner_icon: { value: "<span></span>" },128 banner_icon: { value: "<span></span>" },
136 banner_template: {129 banner_template: {
137 valueFn: function() {130 valueFn: function() {
138 return [131 return [
139 '<div id="{{ banner_id }}"', 132 '<div class="global-notification transparent hidden">',
140 'class="global-notification transparent hidden">',
141 '{{{ badge }}}',133 '{{{ badge }}}',
142 '<span class="banner-text">{{ text }}</span>',134 '<span class="banner-text">{{ text }}</span>',
143 "</div>"].join('')135 "</div>"].join('')
144136
=== modified file 'lib/lp/app/javascript/banners/beta-notification.js'
--- lib/lp/app/javascript/banners/beta-notification.js 2012-05-18 22:26:44 +0000
+++ lib/lp/app/javascript/banners/beta-notification.js 2012-05-24 20:50:26 +0000
@@ -5,20 +5,16 @@
55
6ns.BetaBanner = Y.Base.create('betaBanner', baseBanner, [], {6ns.BetaBanner = Y.Base.create('betaBanner', baseBanner, [], {
77
8 _createBanner: function () {8 renderUI: function () {
9 var banner_data = {9 var banner_data = {
10 badge: this.get('banner_icon'),10 badge: this.get('banner_icon'),
11 text: this.get('notification_text'),11 text: this.get('notification_text'),
12 features: this.get('features'),12 features: this.get('features'),
13 banner_id: this.get('banner_id')
14 };13 };
15 return Y.lp.mustache.to_html(14 var banner_html = Y.lp.mustache.to_html(
16 this.get('banner_template'),15 this.get('banner_template'),
17 banner_data);16 banner_data);
18 },17 this.get('contentBox').append(banner_html);
19
20 renderUI: function () {
21 baseBanner.prototype.renderUI.apply(this, arguments);
22 var beta_node = Y.one('.global-notification');18 var beta_node = Y.one('.global-notification');
23 var close_box = Y.Node.create(19 var close_box = Y.Node.create(
24 '<a href="#" class="global-notification-close">Hide' +20 '<a href="#" class="global-notification-close">Hide' +
@@ -38,14 +34,12 @@
3834
39}, {35}, {
40 ATTRS: {36 ATTRS: {
41 banner_id: { value: "beta-banner" },
42 notification_text: { value: "Some parts of this page are in beta: " },37 notification_text: { value: "Some parts of this page are in beta: " },
43 banner_icon: { value: '<span class="beta-warning">BETA!</span>' },38 banner_icon: { value: '<span class="beta-warning">BETA!</span>' },
44 banner_template: {39 banner_template: {
45 valueFn: function() {40 valueFn: function() {
46 return [41 return [
47 '<div id="{{ banner_id }}"', 42 '<div class="global-notification transparent hidden">',
48 'class="global-notification transparent hidden">',
49 '{{{ badge }}}',43 '{{{ badge }}}',
50 '<span class="banner-text">',44 '<span class="banner-text">',
51 '{{ text }}{{{ features }}}',45 '{{ text }}{{{ features }}}',
@@ -72,11 +66,17 @@
72 }66 }
73});67});
7468
69// For the beta banner to work, it needs to have one instance, and one
70// instance only.
71_singleton_beta_banner = null;
75ns.show_beta_if_needed = function () {72ns.show_beta_if_needed = function () {
76 var banner = new ns.BetaBanner();73 if (_singleton_beta_banner === null) {
77 if (banner.get('features').length !== 0) {74 var src = Y.one('.yui3-betabanner')
78 banner.render();75 _singleton_beta_banner = new ns.BetaBanner({ srcNode: src });
79 banner.show();76 }
77 if (_singleton_beta_banner.get('features').length !== 0) {
78 _singleton_beta_banner.render();
79 _singleton_beta_banner.show();
80 }80 }
81}81}
8282
8383
=== modified file 'lib/lp/app/javascript/banners/privacy.js'
--- lib/lp/app/javascript/banners/privacy.js 2012-05-17 21:04:18 +0000
+++ lib/lp/app/javascript/banners/privacy.js 2012-05-24 20:50:26 +0000
@@ -5,7 +5,6 @@
55
6ns.PrivacyBanner = Y.Base.create('privacyBanner', baseBanner, [], {}, {6ns.PrivacyBanner = Y.Base.create('privacyBanner', baseBanner, [], {}, {
7 ATTRS: {7 ATTRS: {
8 banner_id: { value: "privacy-banner" },
9 notification_text: {8 notification_text: {
10 value: "The information on this page is private."9 value: "The information on this page is private."
11 },10 },
@@ -18,12 +17,16 @@
18// For the privacy banner to work, it needs to have one instance, and one17// For the privacy banner to work, it needs to have one instance, and one
19// instance only.18// instance only.
20var _singleton_privacy_banner = null;19var _singleton_privacy_banner = null;
2120ns.getPrivacyBanner = function (banner_text) {
22ns.getPrivacyBanner = function () {21
23 if (_singleton_privacy_banner === null) {22 if (_singleton_privacy_banner === null) {
24 _singleton_privacy_banner = new ns.PrivacyBanner();23 var src = Y.one('.yui3-privacybanner')
24 _singleton_privacy_banner = new ns.PrivacyBanner({ srcNode: src });
25 _singleton_privacy_banner.render();25 _singleton_privacy_banner.render();
26 }26 }
27 if (Y.Lang.isValue(banner_text)) {
28 _singleton_privacy_banner.updateText(banner_text);
29 }
27 return _singleton_privacy_banner;30 return _singleton_privacy_banner;
28}31}
2932
3033
=== modified file 'lib/lp/app/javascript/banners/tests/test_banner.js'
--- lib/lp/app/javascript/banners/tests/test_banner.js 2012-05-22 21:31:04 +0000
+++ lib/lp/app/javascript/banners/tests/test_banner.js 2012-05-24 20:50:26 +0000
@@ -62,7 +62,6 @@
62 banner.render();62 banner.render();
6363
64 var banner_node = Y.one(".global-notification");64 var banner_node = Y.one(".global-notification");
65 console.log(banner_node);
66 var badge = banner_node.one('.sprite');65 var badge = banner_node.one('.sprite');
67 Y.Assert.isObject(banner_node);66 Y.Assert.isObject(banner_node);
68 Y.Assert.areEqual(cfg.notification_text, banner_node.get('text'));67 Y.Assert.areEqual(cfg.notification_text, banner_node.get('text'));
@@ -72,8 +71,7 @@
72 test_show: function() {71 test_show: function() {
73 var banner = new Y.lp.app.banner.Banner({ skip_animation: true });72 var banner = new Y.lp.app.banner.Banner({ skip_animation: true });
74 banner.render();73 banner.render();
75 banner.show();74 banner.show();
76
77 var banner_node = Y.one(".global-notification");75 var banner_node = Y.one(".global-notification");
78 Y.Assert.isFalse(banner_node.hasClass('hidden'));76 Y.Assert.isFalse(banner_node.hasClass('hidden'));
79 },77 },
@@ -94,25 +92,18 @@
94 this.wait(check, wait_for_anim);92 this.wait(check, wait_for_anim);
95 },93 },
9694
97 test_only_one_banner: function () {95 test_updateText: function() {
98 // There can only be one banner node for a given type of banner.
99 var banner = new Y.lp.app.banner.Banner({ skip_animation: true });96 var banner = new Y.lp.app.banner.Banner({ skip_animation: true });
100 banner.render();97 banner.render();
101 banner.show();98 var new_text = 'some new text';
102 Y.Assert.areEqual(1, Y.all('.global-notification').size());99 banner.updateText(new_text);
100 var banner_node = Y.one(".global-notification");
101 Y.Assert.areEqual(new_text, banner_node.get('text'));
103102
104 var new_text = 'This is new text';103 banner.updateText();
105 var banner2 = new Y.lp.app.banner.Banner({104 var banner_node = Y.one(".global-notification");
106 notification_text: new_text,105 Y.Assert.areEqual("", banner_node.get('text'));
107 skip_animation: true
108 });
109 banner2.render();
110 banner2.show();
111 Y.Assert.areEqual(1, Y.all('.global-notification').size());
112 var banner_node = Y.one('.global-notification');
113 Y.Assert.areEqual(
114 new_text,
115 Y.one('.global-notification').get('text'));
116 }106 }
117 }));107 }));
108
118}, '0.1', {'requires': ['test', 'console', 'lp.app.banner']});109}, '0.1', {'requires': ['test', 'console', 'lp.app.banner']});
119110
=== modified file 'lib/lp/app/javascript/banners/tests/test_privacy.js'
--- lib/lp/app/javascript/banners/tests/test_privacy.js 2012-05-22 21:31:04 +0000
+++ lib/lp/app/javascript/banners/tests/test_privacy.js 2012-05-24 20:50:26 +0000
@@ -36,6 +36,20 @@
36 '<span class="sprite notification-private"></span>',36 '<span class="sprite notification-private"></span>',
37 banner.get('banner_icon'));37 banner.get('banner_icon'));
38 },38 },
39
40 test_only_one_banner: function () {
41 // getPrivacyBanner only returns one banner.
42 var banner = Y.lp.app.banner.privacy.getPrivacyBanner();
43 Y.Assert.areEqual(1, Y.all('.global-notification').size());
44
45 var new_text = 'This is new text';
46 var banner = Y.lp.app.banner.privacy.getPrivacyBanner(new_text);
47 Y.Assert.areEqual(1, Y.all('.global-notification').size());
48 var banner_node = Y.one('.global-notification');
49 Y.Assert.areEqual(
50 new_text,
51 Y.one('.global-notification').get('text'));
52 }
39 }));53 }));
4054
41}, '0.1', {'requires': ['test', 'console', 'lp.app.banner.privacy']});55}, '0.1', {'requires': ['test', 'console', 'lp.app.banner.privacy']});
4256
=== modified file 'lib/lp/app/templates/banner-macros.pt'
--- lib/lp/app/templates/banner-macros.pt 2012-05-21 20:12:08 +0000
+++ lib/lp/app/templates/banner-macros.pt 2012-05-24 20:50:26 +0000
@@ -9,35 +9,39 @@
99
10<metal:privacy define-macro="privacy-banner">10<metal:privacy define-macro="privacy-banner">
11 <tal:show-banner condition="view/private">11 <tal:show-banner condition="view/private">
12 <div class="yui3-privacybanner-content">12 <div class="yui3-widget yui3-banner yui3-privacybanner">
13 <div id="privacy-banner" class="global-notification">13 <div class="yui3-privacybanner-content">
14 <span class="sprite notification-private"></span>14 <div class="global-notification">
15 <span class="banner-text">The information on this page is private.</span>15 <span class="sprite notification-private"></span>
16 <span class="banner-text">The information on this page is private.</span>
17 </div>
16 </div>18 </div>
17 </div>19 </div>
18 </tal:show-banner>20 </tal:show-banner>
19</metal:privacy>21</metal:privacy>
2022
21<metal:beta define-macro="beta-banner">23<metal:beta define-macro="beta-banner">
22<tal:show-banner condition="view/beta_features">24 <tal:show-banner condition="view/beta_features">
23<div class="yui3-betabanner-content">25 <div class="yui3-widget yui3-banner yui3-betabanner">
24 <div id="beta-banner" class="global-notification">26 <div class="yui3-betabanner-content">
25 <span class="beta-warning">BETA!</span>27 <div class="global-notification">
26 <span class="banner-text">28 <span class="beta-warning">BETA!</span>
27 Some parts of this page are in beta:&nbsp;29 <span class="banner-text">
28 <span class="beta-feature">30 Some parts of this page are in beta:&nbsp;
29 <tal:features31 <span class="beta-feature">
30 repeat="feature view/beta_features">32 <tal:features
31 <tal:feature replace="feature/title" />33 repeat="feature view/beta_features">
32 <tal:link condition="feature/url">34 <tal:feature replace="feature/title" />
33 (<a tal:attributes="href feature/url" class="info-link">read more</a>)35 <tal:link condition="feature/url">
34 </tal:link>36 (<a tal:attributes="href feature/url" class="info-link">read more</a>)
35 </tal:features>37 </tal:link>
36 <span>38 </tal:features>
37 </span>39 </span>
38 </div>40 </span>
39</div>41 </div>
40</tal:show-banner>42 </div>
43 </div>
44 </tal:show-banner>
41</metal:beta>45</metal:beta>
4246
43</macros>47</macros>
4448
=== modified file 'lib/lp/bugs/templates/bugtarget-macros-filebug.pt'
--- lib/lp/bugs/templates/bugtarget-macros-filebug.pt 2012-05-14 19:38:34 +0000
+++ lib/lp/bugs/templates/bugtarget-macros-filebug.pt 2012-05-24 20:50:26 +0000
@@ -330,11 +330,10 @@
330 <script type="text/javascript">330 <script type="text/javascript">
331 LPJS.use('lp.app.banner.privacy', function(Y) {331 LPJS.use('lp.app.banner.privacy', function(Y) {
332 Y.on('domready', function() {332 Y.on('domready', function() {
333 var cfg = {333 var notification_text = "This report will be private. " +
334 notification_text: "This report will be private. "334 "You can disclose it later.";
335 + "You can disclose it later."335 var banner = Y.lp.app.banner.privacy.getPrivacyBanner(
336 };336 notification_text);
337 var banner = new Y.lp.app.banner.privacy.PrivacyBanner(cfg);
338 banner.show();337 banner.show();
339 });338 });
340 });339 });
@@ -358,13 +357,14 @@
358 }, "input[name='field.information_type']");357 }, "input[name='field.information_type']");
359 };358 };
360 var setup_security_related = function() {359 var setup_security_related = function() {
361 var cfg = {360 var notification_text: "This report will be private " +
362 notification_text: "This report will be private "361 "because it is a security " +
363 + "because it is a security vulnerability. You "362 "vulnerability. You can " +
364 + "can disclose it later."363 "disclose it later.";
365 };364 };
366 var privacy_ns = Y.lp.app.banner.privacy;365 var privacy_ns = Y.lp.app.banner.privacy;
367 var banner = new privacy_ns.PrivacyBanner(cfg);366 var banner = privacy_ns.getPrivacyBanner(
367 notification_text);
368 banner.render();368 banner.render();
369 var sec = Y.one('[id="field.security_related"]');369 var sec = Y.one('[id="field.security_related"]');
370 sec.on('change', function() {370 sec.on('change', function() {