Merge lp:~rharding/launchpad/new_banner_stage1 into lp:launchpad
- new_banner_stage1
- Merge into devel
Status: | Work in progress |
---|---|
Proposed branch: | lp:~rharding/launchpad/new_banner_stage1 |
Merge into: | lp:launchpad |
Diff against target: |
4858 lines (+495/-2431) 43 files modified
buildout-templates/bin/combine-css.in (+1/-0) lib/canonical/launchpad/icing/css/components/beta_banner.css (+0/-48) lib/lp/app/browser/launchpad.py (+29/-23) lib/lp/app/browser/tales.py (+4/-3) lib/lp/app/browser/tests/test_launchpad.py (+13/-0) 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 (+47/-28) lib/lp/app/javascript/tests/test_information_type.js (+0/-61) lib/lp/app/javascript/ui/assets/skins/sam/banner.css (+0/-109) lib/lp/app/javascript/ui/banner.js (+0/-315) lib/lp/app/javascript/ui/tests/test_banner.html (+0/-49) lib/lp/app/javascript/ui/tests/test_banner.js (+0/-287) lib/lp/app/javascript/views/global.js (+0/-142) lib/lp/app/javascript/views/tests/test_global.html (+0/-62) lib/lp/app/javascript/views/tests/test_global.js (+0/-164) lib/lp/app/templates/base-layout-macros.pt (+5/-7) lib/lp/app/templates/base-layout.pt (+8/-4) lib/lp/archivepublisher/scripts/generate_contents_files.py (+13/-3) lib/lp/archivepublisher/scripts/generate_extra_overrides.py (+1/-1) lib/lp/archivepublisher/tests/test_generate_contents_files.py (+35/-7) lib/lp/archivepublisher/tests/test_generate_extra_overrides.py (+0/-16) lib/lp/blueprints/javascript/addspec.js (+15/-2) lib/lp/bugs/browser/tests/test_bug_views.py (+23/-0) lib/lp/bugs/javascript/bugtask_index.js (+0/-1) lib/lp/bugs/javascript/filebug.js (+66/-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/browser/product.py (+1/-0) lib/lp/registry/configure.zcml (+31/-1) lib/lp/registry/interfaces/product.py (+40/-41) lib/lp/registry/javascript/product_views.js (+6/-0) lib/lp/registry/model/product.py (+2/-1) lib/lp/registry/tests/test_product.py (+14/-13) lib/lp/services/features/flags.py (+1/-1) |
To merge this branch: | bzr merge lp:~rharding/launchpad/new_banner_stage1 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Launchpad code reviewers | Pending | ||
Review via email: mp+132957@code.launchpad.net |
Commit message
Description of the change
TBD
- 16203. By Richard Harding
-
Lots of updates in the style/setup for multiple beta features
- 16204. By Richard Harding
-
Garden
- 16205. By Richard Harding
-
Work on updating the banner to work via css vs manual style
- 16206. By Richard Harding
-
Add docs strings yay
- 16207. By Richard Harding
-
Bwuhahahaha two banners on one page
- 16208. By Richard Harding
-
Clean debug
- 16209. By Richard Harding
-
Fix the css on the private banner
- 16210. By Richard Harding
-
Update to override the show/hide method and provide a brief pause to get the css animation to kick in
- 16211. By Richard Harding
-
Get rid of the timeout and use load to show the banners
- 16212. By Richard Harding
-
Add more tests to the banner code
- 16213. By Richard Harding
-
Add docs and XXX for body class crap
- 16214. By Richard Harding
-
Add XXX to tales.py that it affects
- 16215. By Richard Harding
-
Global tests added
- 16216. By Richard Harding
-
Broken the dippy things
- 16217. By Richard Harding
-
Fix animation and full width issue
- 16218. By Richard Harding
-
Update with trunk and resolve conflicts
- 16219. By Richard Harding
-
Make sure the edit fires the information type change event
- 16220. By Richard Harding
-
Shorten the animation time since you get it on every page load
- 16221. By Richard Harding
-
get the banners working on the blueprints UI
- 16222. By Richard Harding
-
fix the filebug use case and handle security as private
- 16223. By Richard Harding
-
Add the content watch event to update the banner when the content is changed
- 16224. By Richard Harding
-
Fix information type tests
- 16225. By Richard Harding
-
Fix the filebug tests
- 16226. By Richard Harding
-
Update tests for the information type choice
- 16227. By Richard Harding
-
Update from trunk
- 16228. By Richard Harding
-
Add some docs
- 16229. By Richard Harding
-
Remove the old banners code
- 16230. By Richard Harding
-
Remove the old banner css
- 16231. By Richard Harding
-
Update upstream
- 16232. By Richard Harding
-
Lint
Unmerged revisions
- 16232. By Richard Harding
-
Lint
- 16231. By Richard Harding
-
Update upstream
- 16230. By Richard Harding
-
Remove the old banner css
- 16229. By Richard Harding
-
Remove the old banners code
- 16228. By Richard Harding
-
Add some docs
- 16227. By Richard Harding
-
Update from trunk
- 16226. By Richard Harding
-
Update tests for the information type choice
- 16225. By Richard Harding
-
Fix the filebug tests
- 16224. By Richard Harding
-
Fix information type tests
- 16223. By Richard Harding
-
Add the content watch event to update the banner when the content is changed
Preview Diff
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-12 13:21:28 +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 | === modified file 'lib/lp/app/browser/launchpad.py' |
67 | --- lib/lp/app/browser/launchpad.py 2012-11-11 23:39:34 +0000 |
68 | +++ lib/lp/app/browser/launchpad.py 2012-11-12 13:21:28 +0000 |
69 | @@ -766,29 +766,35 @@ |
70 | pillar = getUtility(IPillarNameSet).getByName( |
71 | name, ignore_inactive=False) |
72 | |
73 | - if (pillar is not None and IProduct.providedBy(pillar) and |
74 | - not pillar.active): |
75 | - # Emergency brake for public but inactive products: |
76 | - # These products should not be shown to ordinary users. |
77 | - # The root problem is that many views iterate over products, |
78 | - # inactive products included, and access attributes like |
79 | - # name, displayname or call canonical_url(product) -- |
80 | - # and finally throw the data away, if the product is |
81 | - # inactive. So we cannot make these attributes inaccessible |
82 | - # for inactive public products. On the other hand, we |
83 | - # require the permission launchpad.View to protect private |
84 | - # products. |
85 | - # This means that we cannot simply check if the current |
86 | - # user has the permission launchpad.View for an inactive |
87 | - # product. |
88 | - user = getUtility(ILaunchBag).user |
89 | - if user is None: |
90 | - return None |
91 | - user = IPersonRoles(user) |
92 | - if (not user.in_commercial_admin and not user.in_admin and |
93 | - not user.in_registry_experts): |
94 | - return None |
95 | - if pillar is not None and check_permission('launchpad.View', pillar): |
96 | + if pillar is None: |
97 | + return None |
98 | + |
99 | + if IProduct.providedBy(pillar): |
100 | + if not pillar.active: |
101 | + # Emergency brake for public but inactive products: |
102 | + # These products should not be shown to ordinary users. |
103 | + # The root problem is that many views iterate over products, |
104 | + # inactive products included, and access attributes like |
105 | + # name, displayname or call canonical_url(product) -- |
106 | + # and finally throw the data away, if the product is |
107 | + # inactive. So we cannot make these attributes inaccessible |
108 | + # for inactive public products. On the other hand, we |
109 | + # require the permission launchpad.View to protect private |
110 | + # products. |
111 | + # This means that we cannot simply check if the current |
112 | + # user has the permission launchpad.View for an inactive |
113 | + # product. |
114 | + user = getUtility(ILaunchBag).user |
115 | + if user is None: |
116 | + return None |
117 | + user = IPersonRoles(user) |
118 | + if (not user.in_commercial_admin and not user.in_admin and |
119 | + not user.in_registry_experts): |
120 | + return None |
121 | + permitted = check_permission('launchpad.LimitedView', pillar) |
122 | + else: |
123 | + permitted = check_permission('launchpad.View', pillar) |
124 | + if permitted: |
125 | if pillar.name != name: |
126 | # This pillar was accessed through one of its aliases, so we |
127 | # must redirect to its canonical URL. |
128 | |
129 | === modified file 'lib/lp/app/browser/tales.py' |
130 | --- lib/lp/app/browser/tales.py 2012-09-28 06:15:58 +0000 |
131 | +++ lib/lp/app/browser/tales.py 2012-11-12 13:21:28 +0000 |
132 | @@ -663,15 +663,16 @@ |
133 | def global_css(self): |
134 | css_classes = set([]) |
135 | view = self._context |
136 | + |
137 | + # XXX: Bug #1076074 |
138 | private = getattr(view, 'private', False) |
139 | if private: |
140 | css_classes.add('private') |
141 | - css_classes.add('global-notification-visible') |
142 | else: |
143 | css_classes.add('public') |
144 | beta = getattr(view, 'beta_features', []) |
145 | - if beta != []: |
146 | - css_classes.add('global-notification-visible') |
147 | + if beta: |
148 | + css_classes.add('beta') |
149 | return ' '.join(list(css_classes)) |
150 | |
151 | def _getSaneBreadcrumbDetail(self, breadcrumb): |
152 | |
153 | === modified file 'lib/lp/app/browser/tests/test_launchpad.py' |
154 | --- lib/lp/app/browser/tests/test_launchpad.py 2012-11-11 23:39:34 +0000 |
155 | +++ lib/lp/app/browser/tests/test_launchpad.py 2012-11-12 13:21:28 +0000 |
156 | @@ -554,6 +554,19 @@ |
157 | self.assertRaises( |
158 | NotFound, self.traverse_to_inactive_proprietary_product) |
159 | |
160 | + def test_access_for_persons_with_artifact_grant(self): |
161 | + # Persons with an artifact grant related to a private product |
162 | + # can traverse the product. |
163 | + user = self.factory.makePerson() |
164 | + with person_logged_in(self.proprietary_product_owner): |
165 | + bug = self.factory.makeBug( |
166 | + target=self.active_proprietary_product, |
167 | + information_type=InformationType.PROPRIETARY) |
168 | + getUtility(IService, 'sharing').ensureAccessGrants( |
169 | + [user], self.proprietary_product_owner, bugs=[bug]) |
170 | + with person_logged_in(user): |
171 | + self.traverse_to_active_proprietary_product() |
172 | + |
173 | def check_admin_access(self): |
174 | self.traverse_to_active_public_product() |
175 | self.traverse_to_inactive_public_product() |
176 | |
177 | === removed directory 'lib/lp/app/javascript/banners' |
178 | === removed file 'lib/lp/app/javascript/banners/banner.js' |
179 | --- lib/lp/app/javascript/banners/banner.js 2012-10-04 14:17:23 +0000 |
180 | +++ lib/lp/app/javascript/banners/banner.js 1970-01-01 00:00:00 +0000 |
181 | @@ -1,156 +0,0 @@ |
182 | -/* |
183 | - * Copyright 2012 Canonical Ltd. This software is licensed under the |
184 | - * GNU Affero General Public License version 3 (see the file LICENSE). |
185 | - * |
186 | - * Notification banner widget |
187 | - * |
188 | - * @module lp.app.banner |
189 | - */ |
190 | - |
191 | -YUI.add('lp.app.banner', function (Y) { |
192 | -var ns = Y.namespace('lp.app.banner'); |
193 | - |
194 | -ns.Banner = Y.Base.create('banner', Y.Widget, [], { |
195 | - |
196 | - _getAnimTimes: function() { |
197 | - var anim_times; |
198 | - if (this.get('skip_animation')) { |
199 | - anim_times = { |
200 | - fade: 0.0, |
201 | - slide_out: 0.0 |
202 | - }; |
203 | - } else { |
204 | - anim_times = { |
205 | - fade: 0.3, |
206 | - slide_out: 0.2 |
207 | - }; |
208 | - } |
209 | - return anim_times; |
210 | - }, |
211 | - |
212 | - _showBanner: function () { |
213 | - var body = Y.one('body'); |
214 | - var global_notification = Y.one('.global-notification'); |
215 | - var anim_times = this._getAnimTimes(); |
216 | - |
217 | - body.addClass('global-notification-visible'); |
218 | - global_notification.removeClass('hidden'); |
219 | - |
220 | - var fade_in = new Y.Anim({ |
221 | - node: global_notification, |
222 | - to: {opacity: 1}, |
223 | - duration: anim_times.fade |
224 | - }); |
225 | - var body_space = new Y.Anim({ |
226 | - node: body, |
227 | - to: {'paddingTop': '40px'}, |
228 | - duration: anim_times.slide_out, |
229 | - easing: Y.Easing.easeOut |
230 | - }); |
231 | - var login_space = new Y.Anim({ |
232 | - node: '.login-logout', |
233 | - to: {'top': '45px'}, |
234 | - duration: anim_times.slide_out, |
235 | - easing: Y.Easing.easeOut |
236 | - }); |
237 | - // For testing, we don't do the animations or else the tests will fail. |
238 | - if (anim_times.fade > 0) { |
239 | - fade_in.run(); |
240 | - } |
241 | - if (anim_times.slide_out > 0) { |
242 | - body_space.run(); |
243 | - login_space.run(); |
244 | - } |
245 | - }, |
246 | - |
247 | - _hideBanner: function () { |
248 | - var body = Y.one('body'); |
249 | - var global_notification = Y.one('.global-notification'); |
250 | - var anim_times = this._getAnimTimes(); |
251 | - |
252 | - global_notification.addClass('transparent'); |
253 | - |
254 | - var fade_out = new Y.Anim({ |
255 | - node: global_notification, |
256 | - to: {opacity: 0}, |
257 | - duration: anim_times.fade |
258 | - }); |
259 | - var body_space = new Y.Anim({ |
260 | - node: body, |
261 | - to: {'paddingTop': 0}, |
262 | - duration: anim_times.slide_out, |
263 | - easing: Y.Easing.easeOut |
264 | - }); |
265 | - var login_space = new Y.Anim({ |
266 | - node: '.login-logout', |
267 | - to: {'top': '6px'}, |
268 | - duration: anim_times.slide_out, |
269 | - easing: Y.Easing.easeOut |
270 | - }); |
271 | - fade_out.on('end', function() { |
272 | - global_notification.addClass('hidden'); |
273 | - }); |
274 | - body_space.on('end', function() { |
275 | - body.removeClass('global-notification-visible'); |
276 | - }); |
277 | - |
278 | - fade_out.run(); |
279 | - body_space.run(); |
280 | - login_space.run(); |
281 | - }, |
282 | - |
283 | - bindUI: function() { |
284 | - this.after('visibleChange', function() { |
285 | - if (this.get('visible')) { |
286 | - this._showBanner(); |
287 | - } else { |
288 | - this._hideBanner(); |
289 | - } |
290 | - }); |
291 | - }, |
292 | - |
293 | - renderUI: function () { |
294 | - var banner_data = { |
295 | - badge: this.get('banner_icon'), |
296 | - text: this.get('notification_text') |
297 | - }; |
298 | - var banner_html = Y.lp.mustache.to_html( |
299 | - this.get('banner_template'), |
300 | - banner_data); |
301 | - this.get('contentBox').append(banner_html); |
302 | - }, |
303 | - |
304 | - updateText: function (new_text) { |
305 | - var text_node = this.get('contentBox').one('.banner-text'); |
306 | - if (!Y.Lang.isValue(new_text)) { |
307 | - new_text = this.get('notification_text'); |
308 | - } |
309 | - |
310 | - if (text_node) { |
311 | - text_node.set('text', new_text); |
312 | - } else { |
313 | - Y.log('No text node to update banner text.', 'error'); |
314 | - } |
315 | - } |
316 | - |
317 | -}, { |
318 | - ATTRS: { |
319 | - banner_icon: { value: "<span></span>" }, |
320 | - banner_template: { |
321 | - valueFn: function() { |
322 | - return [ |
323 | - '<div class="global-notification transparent hidden">', |
324 | - '{{{ badge }}}', |
325 | - '<span class="banner-text">{{ text }}</span>', |
326 | - "</div>"].join(''); |
327 | - } |
328 | - }, |
329 | - notification_text: { value: "" }, |
330 | - skip_animation: { value: false }, |
331 | - visible: { value: false } |
332 | - } |
333 | -}); |
334 | - |
335 | -}, '0.1', { |
336 | - requires: ['base', 'node', 'anim', 'widget', 'lp.mustache', 'yui-log'] |
337 | -}); |
338 | |
339 | === removed file 'lib/lp/app/javascript/banners/beta-notification.js' |
340 | --- lib/lp/app/javascript/banners/beta-notification.js 2012-09-25 18:47:19 +0000 |
341 | +++ lib/lp/app/javascript/banners/beta-notification.js 1970-01-01 00:00:00 +0000 |
342 | @@ -1,104 +0,0 @@ |
343 | -/** |
344 | - * Add a BetaBanner widget for use. |
345 | - * |
346 | - * @namespace lp.app.banner |
347 | - * @module beta |
348 | - * |
349 | - */ |
350 | -YUI.add('lp.app.banner.beta', function(Y) { |
351 | - |
352 | -var ns = Y.namespace('lp.app.banner.beta'); |
353 | -var Banner = Y.lp.app.banner.Banner; |
354 | - |
355 | -// For the beta banner to work, it needs to have one instance, and one |
356 | -// instance only. |
357 | -window._singleton_beta_banner = null; |
358 | - |
359 | -ns.show_beta_if_needed = function () { |
360 | - if (window._singleton_beta_banner === null) { |
361 | - var src = Y.one('.yui3-betabanner'); |
362 | - window._singleton_beta_banner = new ns.BetaBanner({ srcNode: src }); |
363 | - } |
364 | - if (window._singleton_beta_banner.get('features').length !== 0) { |
365 | - window._singleton_beta_banner.render(); |
366 | - window._singleton_beta_banner.show(); |
367 | - } |
368 | -}; |
369 | - |
370 | - |
371 | -/** |
372 | - * Banner to display for beta features. |
373 | - * |
374 | - * @class BetaBanner |
375 | - * @extends Banner |
376 | - * |
377 | - */ |
378 | -ns.BetaBanner = Y.Base.create('betaBanner', Banner, [], { |
379 | - |
380 | - bindUI: function () { |
381 | - Banner.prototype.bindUI.apply(this, arguments); |
382 | - var close_box = Y.one('.global-notification-close'); |
383 | - var that = this; |
384 | - close_box.on('click', function(e) { |
385 | - e.halt(); |
386 | - that.hide(); |
387 | - }); |
388 | - }, |
389 | - |
390 | - renderUI: function () { |
391 | - var banner_data = { |
392 | - badge: this.get('banner_icon'), |
393 | - text: this.get('notification_text'), |
394 | - features: this.get('features'), |
395 | - }; |
396 | - var banner_html = Y.lp.mustache.to_html( |
397 | - this.get('banner_template'), |
398 | - banner_data); |
399 | - this.get('contentBox').append(banner_html); |
400 | - var beta_node = Y.one('.global-notification'); |
401 | - var close_box = Y.Node.create( |
402 | - '<a href="#" class="global-notification-close">Hide' + |
403 | - '<span class="notification-close sprite" /></a>'); |
404 | - beta_node.appendChild(close_box); |
405 | - } |
406 | - |
407 | -}, { |
408 | - ATTRS: { |
409 | - banner_icon: { value: '<span class="beta-warning">BETA!</span>' }, |
410 | - |
411 | - banner_template: { |
412 | - valueFn: function() { |
413 | - return [ |
414 | - '<div class="global-notification transparent hidden">', |
415 | - '{{{ badge }}}', |
416 | - '<span class="banner-text">', |
417 | - '{{ text }}{{{ features }}}', |
418 | - '</span>', |
419 | - "</div>"].join(''); |
420 | - } |
421 | - }, |
422 | - |
423 | - features: { |
424 | - valueFn: function () { |
425 | - var features_template = [ |
426 | - '{{#features}}{{#is_beta}}', |
427 | - '<span class="beta-feature"> {{title}}', |
428 | - '{{#url}}', |
429 | - ' (<a href="{{url}}" class="info-link">read more</a>)', |
430 | - '{{/url}}', |
431 | - '</span>', |
432 | - '{{/is_beta}}{{/features}}'].join(''); |
433 | - var feature_data = { |
434 | - features: Y.Object.values(LP.cache.related_features) |
435 | - }; |
436 | - return Y.lp.mustache.to_html(features_template, feature_data); |
437 | - } |
438 | - }, |
439 | - |
440 | - notification_text: { value: "Some parts of this page are in beta: " } |
441 | - } |
442 | -}); |
443 | - |
444 | - |
445 | -}, '0.1', {'requires': ['base', 'node', 'anim', 'lp.mustache', |
446 | - 'lp.app.banner']}); |
447 | |
448 | === removed file 'lib/lp/app/javascript/banners/privacy.js' |
449 | --- lib/lp/app/javascript/banners/privacy.js 2012-10-04 14:17:23 +0000 |
450 | +++ lib/lp/app/javascript/banners/privacy.js 1970-01-01 00:00:00 +0000 |
451 | @@ -1,119 +0,0 @@ |
452 | -/** |
453 | - * Add a PrivacyBanner widget for use. |
454 | - * |
455 | - * @namespace lp.app.banner |
456 | - * @module privacy |
457 | - * |
458 | - */ |
459 | -YUI.add('lp.app.banner.privacy', function(Y) { |
460 | -var ns = Y.namespace('lp.app.banner.privacy'); |
461 | -var Banner = Y.lp.app.banner.Banner; |
462 | - |
463 | -ns.EV_SHOW = 'privacy_banner:show'; |
464 | -ns.EV_HIDE = 'privacy_banner:hide'; |
465 | - |
466 | -/** |
467 | - * Allow for adjusting the global instance of the Privacy Banner via events. |
468 | - * |
469 | - * @event privacy_banner:show |
470 | - * @param text The message to show |
471 | - */ |
472 | -Y.publish(ns.EV_SHOW, { |
473 | - emitFacade: true |
474 | -}); |
475 | - |
476 | -/** |
477 | - * Hide the global instance of the banner via events. |
478 | - * |
479 | - * @event privacy_banner:hide |
480 | - */ |
481 | -Y.publish(ns.EV_HIDE, { |
482 | - emitFacade: true |
483 | -}); |
484 | - |
485 | - |
486 | -// For the privacy banner to work, it needs to have one instance, and one |
487 | -// instance only. |
488 | -window._singleton_privacy_banner = null; |
489 | -ns.getPrivacyBanner = function (banner_text, skip_animation) { |
490 | - if (window._singleton_privacy_banner === null) { |
491 | - var src = Y.one('.yui3-privacybanner'); |
492 | - window._singleton_privacy_banner = new ns.PrivacyBanner( |
493 | - { srcNode: src, skip_animation: skip_animation }); |
494 | - window._singleton_privacy_banner.render(); |
495 | - } |
496 | - if (Y.Lang.isValue(banner_text)) { |
497 | - window._singleton_privacy_banner.updateText(banner_text); |
498 | - } |
499 | - return window._singleton_privacy_banner; |
500 | -}; |
501 | - |
502 | - |
503 | -/** |
504 | - * Banner to display when page contains private information. |
505 | - * |
506 | - * @class PrivacyBanner |
507 | - * @extends Banner |
508 | - * |
509 | - */ |
510 | -ns.PrivacyBanner = Y.Base.create('privacyBanner', Banner, [], { |
511 | - _custom_message: function (ev) { |
512 | - var body = Y.one('body'); |
513 | - body.replaceClass('public', 'private'); |
514 | - if (!ev.text) { |
515 | - throw('A custom privacy banner must have a text attribute'); |
516 | - } |
517 | - this.updateText(ev.text); |
518 | - this.show(); |
519 | - }, |
520 | - |
521 | - _make_public: function (ev) { |
522 | - var body = Y.one('body'); |
523 | - body.replaceClass('private', 'public'); |
524 | - this.hide(); |
525 | - }, |
526 | - |
527 | - _make_private: function (ev) { |
528 | - // Update the text in the banner before we show it. |
529 | - var body = Y.one('body'); |
530 | - body.replaceClass('public', 'private'); |
531 | - |
532 | - if (!ev.text) { |
533 | - throw('Showing a privacy banner must supply text for the banner'); |
534 | - } |
535 | - this.updateText(ev.text); |
536 | - this.show(); |
537 | - }, |
538 | - |
539 | - bindUI: function () { |
540 | - var that = this; |
541 | - var info_type = Y.lp.app.information_type; |
542 | - Banner.prototype.bindUI.apply(this, arguments); |
543 | - |
544 | - // We care about changes to Information Type in the UI. |
545 | - Y.on(info_type.EV_ISPUBLIC, that._make_public, that); |
546 | - Y.on(info_type.EV_ISPRIVATE, that._make_private, that); |
547 | - |
548 | - // And provide our own manual events for the Security banner usage. |
549 | - Y.on(ns.EV_SHOW, that._custom_message, that); |
550 | - Y.on(ns.EV_HIDE, function (ev) { |
551 | - that.hide(); |
552 | - }, that); |
553 | - } |
554 | - |
555 | -}, { |
556 | - ATTRS: { |
557 | - banner_icon: { |
558 | - value: '<span class="sprite notification-private"></span>' |
559 | - }, |
560 | - notification_text: { |
561 | - value: "The information on this page is private." |
562 | - } |
563 | - } |
564 | -}); |
565 | - |
566 | -}, "0.1", { |
567 | - requires: [ |
568 | - "base", "node", "anim", "lp.app.banner", |
569 | - "lp.app.information_type"] |
570 | -}); |
571 | |
572 | === removed directory 'lib/lp/app/javascript/banners/tests' |
573 | === removed file 'lib/lp/app/javascript/banners/tests/test_banner.html' |
574 | --- lib/lp/app/javascript/banners/tests/test_banner.html 2012-10-26 09:54:28 +0000 |
575 | +++ lib/lp/app/javascript/banners/tests/test_banner.html 1970-01-01 00:00:00 +0000 |
576 | @@ -1,46 +0,0 @@ |
577 | -<!DOCTYPE html> |
578 | -<!-- |
579 | -Copyright 2012 Canonical Ltd. This software is licensed under the |
580 | -GNU Affero General Public License version 3 (see the file LICENSE). |
581 | ---> |
582 | - |
583 | -<html> |
584 | - <head> |
585 | - <title>lp.app.banner Tests</title> |
586 | - |
587 | - <!-- YUI and test setup --> |
588 | - <script type="text/javascript" |
589 | - src="../../../../../../build/js/yui/yui/yui.js"> |
590 | - </script> |
591 | - <link rel="stylesheet" |
592 | - href="../../../../../../build/js/yui/console/assets/console-core.css" /> |
593 | - <link rel="stylesheet" |
594 | - href="../../../../../../build/js/yui/test-console/assets/skins/sam/test-console.css" /> |
595 | - <link rel="stylesheet" |
596 | - href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" /> |
597 | - |
598 | - <script type="text/javascript" |
599 | - src="../../../../../../build/js/lp/app/testing/testrunner.js"></script> |
600 | - |
601 | - <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" /> |
602 | - |
603 | - <!-- Dependencies --> |
604 | - <script type="text/javascript" |
605 | - src="../../../../../../build/js/lp/app/mustache.js"></script> |
606 | - |
607 | - <!-- The module under test. --> |
608 | - <script type="text/javascript" src="../banner.js"></script> |
609 | - |
610 | - <!-- Placeholder for any css asset for this module. --> |
611 | - <!-- <link rel="stylesheet" href="../assets/${LIBRARY}-core.css" /> --> |
612 | - |
613 | - <!-- The test suite --> |
614 | - <script type="text/javascript" src="test_banner.js"></script> |
615 | - |
616 | - </head> |
617 | - <body class="yui3-skin-sam"> |
618 | - <ul id="suites"> |
619 | - <li>lp.app.banner.test</li> |
620 | - </ul> |
621 | - </body> |
622 | -</html> |
623 | |
624 | === removed file 'lib/lp/app/javascript/banners/tests/test_banner.js' |
625 | --- lib/lp/app/javascript/banners/tests/test_banner.js 2012-10-26 10:00:20 +0000 |
626 | +++ lib/lp/app/javascript/banners/tests/test_banner.js 1970-01-01 00:00:00 +0000 |
627 | @@ -1,110 +0,0 @@ |
628 | -/* Copyright (c) 2012, Canonical Ltd. All rights reserved. */ |
629 | - |
630 | -YUI.add('lp.app.banner.test', function (Y) { |
631 | - |
632 | - var tests = Y.namespace('lp.app.banner.test'); |
633 | - tests.suite = new Y.Test.Suite('lp.app.banner Tests'); |
634 | - |
635 | - tests.suite.add(new Y.Test.Case({ |
636 | - name: 'banner_tests', |
637 | - |
638 | - setUp: function () { |
639 | - var main = Y.Node.create('<div id="maincontent"></div>'); |
640 | - var login_logout = Y.Node.create('<div></div>') |
641 | - .addClass('login-logout'); |
642 | - main.appendChild(login_logout); |
643 | - Y.one('body').appendChild(main); |
644 | - }, |
645 | - |
646 | - tearDown: function () { |
647 | - Y.one('#maincontent').remove(true); |
648 | - Y.all('.yui3-banner').remove(true); |
649 | - }, |
650 | - |
651 | - test_library_exists: function () { |
652 | - Y.Assert.isObject(Y.lp.app.banner, |
653 | - "Could not locate the lp.app.banner module"); |
654 | - }, |
655 | - |
656 | - test_init_without_config: function () { |
657 | - var banner = new Y.lp.app.banner.Banner(); |
658 | - Y.Assert.areEqual("", banner.get('notification_text')); |
659 | - Y.Assert.areEqual("<span></span>", banner.get('banner_icon')); |
660 | - }, |
661 | - |
662 | - test_init_with_config: function () { |
663 | - var cfg = { |
664 | - notification_text: "Some text.", |
665 | - banner_icon: '<span class="sprite"></span>' |
666 | - }; |
667 | - var banner = new Y.lp.app.banner.Banner(cfg); |
668 | - Y.Assert.areEqual( |
669 | - cfg.notification_text, |
670 | - banner.get('notification_text')); |
671 | - Y.Assert.areEqual(cfg.banner_icon, banner.get('banner_icon')); |
672 | - }, |
673 | - |
674 | - test_render_no_config: function () { |
675 | - var banner = new Y.lp.app.banner.Banner({ skip_animation: true }); |
676 | - banner.render(); |
677 | - |
678 | - var banner_node = Y.one(".global-notification"); |
679 | - Y.Assert.isObject(banner_node); |
680 | - Y.Assert.isTrue(banner_node.hasClass('hidden')); |
681 | - }, |
682 | - |
683 | - test_render_with_config: function () { |
684 | - var cfg = { |
685 | - notification_text: "Some text.", |
686 | - banner_icon: '<span class="sprite"></span>', |
687 | - skip_animation: true |
688 | - }; |
689 | - var banner = new Y.lp.app.banner.Banner(cfg); |
690 | - banner.render(); |
691 | - |
692 | - var banner_node = Y.one(".global-notification"); |
693 | - var badge = banner_node.one('.sprite'); |
694 | - Y.Assert.isObject(banner_node); |
695 | - Y.Assert.areEqual(cfg.notification_text, banner_node.get('text')); |
696 | - Y.Assert.isObject(badge); |
697 | - }, |
698 | - |
699 | - test_show: function() { |
700 | - var banner = new Y.lp.app.banner.Banner({ skip_animation: true }); |
701 | - banner.render(); |
702 | - banner.show(); |
703 | - var banner_node = Y.one(".global-notification"); |
704 | - Y.Assert.isFalse(banner_node.hasClass('hidden')); |
705 | - }, |
706 | - |
707 | - test_hide: function() { |
708 | - var banner = new Y.lp.app.banner.Banner({ skip_animation: true }); |
709 | - banner.render(); |
710 | - banner.show(); |
711 | - |
712 | - // Even with animation times set to 0, this test needs a slight |
713 | - // delay in order for the animation end events to fire. |
714 | - var banner_node = Y.one(".global-notification"); |
715 | - var wait_for_anim = 20; |
716 | - var check = function () { |
717 | - Y.Assert.isTrue(banner_node.hasClass('hidden')); |
718 | - }; |
719 | - banner.hide(); |
720 | - this.wait(check, wait_for_anim); |
721 | - }, |
722 | - |
723 | - test_updateText: function() { |
724 | - var banner = new Y.lp.app.banner.Banner({ skip_animation: true }); |
725 | - banner.render(); |
726 | - var new_text = 'some new text'; |
727 | - banner.updateText(new_text); |
728 | - var banner_node = Y.one(".global-notification"); |
729 | - Y.Assert.areEqual(new_text, banner_node.get('text')); |
730 | - |
731 | - banner.updateText(); |
732 | - banner_node = Y.one(".global-notification"); |
733 | - Y.Assert.areEqual("", banner_node.get('text')); |
734 | - } |
735 | - })); |
736 | - |
737 | -}, '0.1', {'requires': ['test', 'test-console', 'lp.app.banner']}); |
738 | |
739 | === removed file 'lib/lp/app/javascript/banners/tests/test_beta_notification.html' |
740 | --- lib/lp/app/javascript/banners/tests/test_beta_notification.html 2012-10-26 09:54:28 +0000 |
741 | +++ lib/lp/app/javascript/banners/tests/test_beta_notification.html 1970-01-01 00:00:00 +0000 |
742 | @@ -1,51 +0,0 @@ |
743 | -<!DOCTYPE html> |
744 | -<!-- |
745 | -Copyright 2012 Canonical Ltd. This software is licensed under the |
746 | -GNU Affero General Public License version 3 (see the file LICENSE). |
747 | ---> |
748 | - |
749 | -<html> |
750 | - <head> |
751 | - <title>Test beta-notification</title> |
752 | - |
753 | - <!-- YUI and test setup --> |
754 | - <script type="text/javascript" |
755 | - src="../../../../../../build/js/yui/yui/yui.js"> |
756 | - </script> |
757 | - <link rel="stylesheet" |
758 | - href="../../../../../../build/js/yui/console/assets/console-core.css" /> |
759 | - <link rel="stylesheet" |
760 | - href="../../../../../../build/js/yui/test-console/assets/skins/sam/test-console.css" /> |
761 | - <link rel="stylesheet" |
762 | - href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" /> |
763 | - |
764 | - <script type="text/javascript" |
765 | - src="../../../../../../build/js/lp/app/testing/testrunner.js"></script> |
766 | - |
767 | - <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" /> |
768 | - |
769 | - <!-- Dependencies --> |
770 | - <script type="text/javascript" |
771 | - src="../../../../../../build/js/lp/app/banners/banner.js"></script> |
772 | - <script type="text/javascript" |
773 | - src="../../../../../../build/js/lp/app/mustache.js"></script> |
774 | - |
775 | - <!-- The module under test. --> |
776 | - <script type="text/javascript" src="../beta-notification.js"></script> |
777 | - |
778 | - <!-- Placeholder for any css asset for this module. --> |
779 | - <!-- <link rel="stylesheet" href="../assets/beta-notification-core.css" /> --> |
780 | - |
781 | - <!-- The test suite. --> |
782 | - <script type="text/javascript" src="test_beta_notification.js"></script> |
783 | - |
784 | - </head> |
785 | - <body class="yui3-skin-sam"> |
786 | - <ul id="suites"> |
787 | - <!-- <li>lp.large_indicator.test</li> --> |
788 | - <li>lp.app.banner.beta.test</li> |
789 | - </ul> |
790 | - <!-- The example markup required by the script to run. --> |
791 | - <div id="maincontent"></div> |
792 | - </body> |
793 | -</html> |
794 | |
795 | === removed file 'lib/lp/app/javascript/banners/tests/test_beta_notification.js' |
796 | --- lib/lp/app/javascript/banners/tests/test_beta_notification.js 2012-10-26 10:00:20 +0000 |
797 | +++ lib/lp/app/javascript/banners/tests/test_beta_notification.js 1970-01-01 00:00:00 +0000 |
798 | @@ -1,140 +0,0 @@ |
799 | -/* Copyright (c) 2012, Canonical Ltd. All rights reserved. */ |
800 | - |
801 | -// Set the "enabled" variable, normally set by base-layout-macros. |
802 | -// This must be a global variable for the code being tested to work. |
803 | -var privacy_notification_enabled = true; |
804 | - |
805 | -YUI.add('lp.app.banner.beta.test', function (Y) { |
806 | - |
807 | - var tests = Y.namespace('lp.app.banner.beta.test'); |
808 | - tests.suite = new Y.Test.Suite('lp.app.banner.beta Tests'); |
809 | - |
810 | - tests.suite.add(new Y.Test.Case({ |
811 | - name: 'beta-notification', |
812 | - |
813 | - setUp: function () { |
814 | - var main = Y.Node.create('<div id="maincontent"></div>'); |
815 | - var login_logout = Y.Node.create('<div></div>') |
816 | - .addClass('login-logout'); |
817 | - main.appendChild(login_logout); |
818 | - Y.one('body').append(main); |
819 | - window.LP = { |
820 | - cache: {} |
821 | - }; |
822 | - }, |
823 | - |
824 | - tearDown: function () { |
825 | - Y.one('#maincontent').remove(true); |
826 | - Y.all('.yui3-banner').remove(true); |
827 | - }, |
828 | - |
829 | - test_library_exists: function () { |
830 | - Y.Assert.isObject(Y.lp.app.banner.beta, |
831 | - "Could not locate the lp.app.banner.beta module"); |
832 | - }, |
833 | - |
834 | - test_beta_banner_one_beta_feature: function() { |
835 | - LP.cache.related_features = { |
836 | - '': { |
837 | - is_beta: true, |
838 | - title: 'A beta feature', |
839 | - url: 'http://lp.dev/LEP/one' |
840 | - }}; |
841 | - var betabanner = new Y.lp.app.banner.beta.BetaBanner( |
842 | - {skip_animation: true}); |
843 | - betabanner.render(); |
844 | - betabanner.show(); |
845 | - |
846 | - var body = Y.one('body'); |
847 | - // The <body> node has the class global-notification-visible, |
848 | - // so that the element has enough padding for the beta banner. |
849 | - Y.Assert.isTrue(body.hasClass('global-notification-visible')); |
850 | - |
851 | - feature_info = Y.one('.beta-feature'); |
852 | - // The message about a beta feature consists of the feature |
853 | - // title and a link to a page with more information about |
854 | - // the feature. |
855 | - Y.Assert.areEqual( |
856 | - ' A beta feature (read more)', feature_info.get('text')); |
857 | - info_link = feature_info.get('children').item(0); |
858 | - Y.Assert.areEqual('http://lp.dev/LEP/one', info_link.get('href')); |
859 | - }, |
860 | - |
861 | - test_beta_banner_two_beta_features: function() { |
862 | - LP.cache.related_features = { |
863 | - '1': { |
864 | - is_beta: true, |
865 | - title: 'Beta feature 1', |
866 | - url: 'http://lp.dev/LEP/one' |
867 | - }, |
868 | - '2': { |
869 | - is_beta: true, |
870 | - title: 'Beta feature 2', |
871 | - url: '' |
872 | - }}; |
873 | - var betabanner = new Y.lp.app.banner.beta.BetaBanner( |
874 | - {skip_animation: true}); |
875 | - betabanner.render(); |
876 | - betabanner.show(); |
877 | - |
878 | - var body = Y.one('body'); |
879 | - Y.Assert.isTrue(body.hasClass('global-notification-visible')); |
880 | - |
881 | - // Notifications about several features can be displayed. |
882 | - feature_info = Y.all('.beta-feature').item(0); |
883 | - Y.Assert.areEqual( |
884 | - ' Beta feature 1 (read more)', feature_info.get('text')); |
885 | - info_link = feature_info.get('children').item(0); |
886 | - Y.Assert.areEqual('http://lp.dev/LEP/one', info_link.get('href')); |
887 | - |
888 | - // If an entry in LP.cache.related_features does not provide a |
889 | - // "read more" link, the corrsponding node is not added. |
890 | - feature_info = Y.all('.beta-feature').item(1); |
891 | - Y.Assert.areEqual( |
892 | - ' Beta feature 2', feature_info.get('text')); |
893 | - Y.Assert.isNull(feature_info.get('children').item(0)); |
894 | - }, |
895 | - |
896 | - test_beta_banner_no_beta_features_defined: function() { |
897 | - LP.cache.related_features = { |
898 | - foo_feature: { |
899 | - is_beta: false, |
900 | - title: 'Non-beta feature', |
901 | - url: 'http://example.org' |
902 | - }}; |
903 | - Y.lp.app.banner.beta.show_beta_if_needed(); |
904 | - Y.Assert.isNull(Y.one('.global-notification')); |
905 | - }, |
906 | - |
907 | - test_hide_beta_banner: function() { |
908 | - LP.cache.related_features = { |
909 | - '': { |
910 | - is_beta: true, |
911 | - title: 'A beta feature', |
912 | - url: 'http://lp.dev/LEP/one' |
913 | - }}; |
914 | - var betabanner = new Y.lp.app.banner.beta.BetaBanner( |
915 | - {skip_animation: true}); |
916 | - betabanner.render(); |
917 | - betabanner.show(); |
918 | - var body = Y.one('body'); |
919 | - var banner = Y.one('.global-notification'); |
920 | - Y.Assert.isFalse(banner.hasClass('hidden')); |
921 | - |
922 | - // Even with animation times set to 0, this test needs a slight |
923 | - // delay in order for the animation end events to fire. |
924 | - var check = function() { |
925 | - Y.Assert.isTrue(banner.hasClass('hidden')); |
926 | - Y.Assert.isFalse( |
927 | - body.hasClass('global-notification-visible')); |
928 | - }; |
929 | - close_link = Y.one('.global-notification-close'); |
930 | - close_link.simulate('click'); |
931 | - var wait_time = 20; |
932 | - this.wait(check, wait_time); |
933 | - } |
934 | - })); |
935 | - |
936 | -}, '0.1', { 'requires': ['test', 'test-console', 'node', 'lp.app.banner.beta', |
937 | - 'node-event-simulate'] |
938 | -}); |
939 | |
940 | === removed file 'lib/lp/app/javascript/banners/tests/test_privacy.html' |
941 | --- lib/lp/app/javascript/banners/tests/test_privacy.html 2012-10-26 09:54:28 +0000 |
942 | +++ lib/lp/app/javascript/banners/tests/test_privacy.html 1970-01-01 00:00:00 +0000 |
943 | @@ -1,47 +0,0 @@ |
944 | -<!DOCTYPE html> |
945 | -<!-- |
946 | -Copyright 2012 Canonical Ltd. This software is licensed under the |
947 | -GNU Affero General Public License version 3 (see the file LICENSE). |
948 | ---> |
949 | - |
950 | -<html> |
951 | - <head> |
952 | - <title>lp.app.banner.privacy Tests</title> |
953 | - |
954 | - <!-- YUI and test setup --> |
955 | - <script type="text/javascript" |
956 | - src="../../../../../../build/js/yui/yui/yui.js"> |
957 | - </script> |
958 | - <link rel="stylesheet" |
959 | - href="../../../../../../build/js/yui/console/assets/console-core.css" /> |
960 | - <link rel="stylesheet" |
961 | - href="../../../../../../build/js/yui/test-console/assets/skins/sam/test-console.css" /> |
962 | - <link rel="stylesheet" |
963 | - href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" /> |
964 | - |
965 | - <script type="text/javascript" |
966 | - src="../../../../../../build/js/lp/app/testing/testrunner.js"></script> |
967 | - |
968 | - <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" /> |
969 | - |
970 | - <!-- Dependencies --> |
971 | - <script type="text/javascript" |
972 | - src="../../../../../../build/js/lp/app/mustache.js"></script> |
973 | - <script type="text/javascript" |
974 | - src="../../../../../../build/js/lp/app/banners/banner.js"></script> |
975 | - <script type="text/javascript" |
976 | - src="../../../../../../build/js/lp/app/information_type.js"></script> |
977 | - |
978 | - <!-- The module under test. --> |
979 | - <script type="text/javascript" src="../privacy.js"></script> |
980 | - |
981 | - <!-- The test suite. --> |
982 | - <script type="text/javascript" src="test_privacy.js"></script> |
983 | - |
984 | - </head> |
985 | - <body class="yui3-skin-sam"> |
986 | - <ul id="suites"> |
987 | - <li>lp.app.banner.privacy.test</li> |
988 | - </ul> |
989 | - </body> |
990 | -</html> |
991 | |
992 | === removed file 'lib/lp/app/javascript/banners/tests/test_privacy.js' |
993 | --- lib/lp/app/javascript/banners/tests/test_privacy.js 2012-10-26 10:00:20 +0000 |
994 | +++ lib/lp/app/javascript/banners/tests/test_privacy.js 1970-01-01 00:00:00 +0000 |
995 | @@ -1,117 +0,0 @@ |
996 | -/* Copyright 2011-2012 Canonical Ltd. This software is licensed under the |
997 | - * GNU Affero General Public License version 3 (see the file LICENSE). |
998 | - */ |
999 | - |
1000 | -YUI.add('lp.app.banner.privacy.test', function (Y) { |
1001 | - |
1002 | - var tests = Y.namespace('lp.app.banner.privacy.test'); |
1003 | - tests.suite = new Y.Test.Suite('lp.app.banner.privacy Tests'); |
1004 | - |
1005 | - tests.suite.add(new Y.Test.Case({ |
1006 | - name: 'privacy_tests', |
1007 | - |
1008 | - setUp: function () { |
1009 | - var main = Y.Node.create('<div id="maincontent"></div>'); |
1010 | - var login_logout = Y.Node.create('<div></div>') |
1011 | - .addClass('login-logout'); |
1012 | - main.appendChild(login_logout); |
1013 | - |
1014 | - var banner_node = Y.Node.create('<div></div>') |
1015 | - .addClass('yui3-privacybanner'); |
1016 | - main.appendChild(banner_node); |
1017 | - Y.one('body').appendChild(main); |
1018 | - }, |
1019 | - |
1020 | - tearDown: function () { |
1021 | - Y.one('#maincontent').remove(true); |
1022 | - window._singleton_privacy_banner = null; |
1023 | - delete window.LP; |
1024 | - }, |
1025 | - |
1026 | - test_library_exists: function () { |
1027 | - Y.Assert.isObject(Y.lp.app.banner.privacy, |
1028 | - "Could not locate the lp.app.banner.privacy module"); |
1029 | - }, |
1030 | - test_init: function () { |
1031 | - var banner = new Y.lp.app.banner.privacy.PrivacyBanner(); |
1032 | - Y.Assert.areEqual( |
1033 | - "The information on this page is private.", |
1034 | - banner.get('notification_text')); |
1035 | - Y.Assert.areEqual( |
1036 | - '<span class="sprite notification-private"></span>', |
1037 | - banner.get('banner_icon')); |
1038 | - }, |
1039 | - |
1040 | - test_only_one_banner: function () { |
1041 | - // getPrivacyBanner only returns one banner. |
1042 | - var banner = Y.lp.app.banner.privacy.getPrivacyBanner(); |
1043 | - Y.Assert.areEqual(1, Y.all('.global-notification').size()); |
1044 | - |
1045 | - var new_text = 'This is new text'; |
1046 | - banner = Y.lp.app.banner.privacy.getPrivacyBanner(new_text); |
1047 | - Y.Assert.areEqual(1, Y.all('.global-notification').size()); |
1048 | - var banner_node = Y.one('.global-notification'); |
1049 | - Y.Assert.areEqual( |
1050 | - new_text, |
1051 | - Y.one('.global-notification').get('text')); |
1052 | - }, |
1053 | - |
1054 | - test_banner_with_custom_text: function () { |
1055 | - var banner = Y.lp.app.banner.privacy.getPrivacyBanner(); |
1056 | - var new_text = 'New custom text'; |
1057 | - |
1058 | - Y.fire('privacy_banner:show', { |
1059 | - text: new_text |
1060 | - }); |
1061 | - Y.Assert.areEqual( |
1062 | - new_text, |
1063 | - Y.one('.global-notification').get('text')); |
1064 | - Y.Assert.isTrue(banner.get('visible'), |
1065 | - 'Banner should be visible.'); |
1066 | - }, |
1067 | - |
1068 | - test_banner_hide_event: function () { |
1069 | - var banner = Y.lp.app.banner.privacy.getPrivacyBanner(); |
1070 | - var new_text = 'New custom text'; |
1071 | - |
1072 | - Y.fire('privacy_banner:show', { |
1073 | - text: new_text |
1074 | - }); |
1075 | - Y.fire('privacy_banner:hide'); |
1076 | - Y.Assert.isFalse(banner.get('visible'), |
1077 | - 'Banner should not be visible.'); |
1078 | - }, |
1079 | - |
1080 | - test_info_type_private_event: function () { |
1081 | - var banner = Y.lp.app.banner.privacy.getPrivacyBanner(); |
1082 | - var body = Y.one('body'); |
1083 | - var msg = 'Some private message'; |
1084 | - Y.fire('information_type:is_private', { |
1085 | - text: msg, |
1086 | - value: 'PROPRIETARY' |
1087 | - }); |
1088 | - Y.Assert.areEqual( |
1089 | - msg, |
1090 | - Y.one('.global-notification').get('text')); |
1091 | - Y.Assert.isTrue(body.hasClass('private'), |
1092 | - 'Body should be private'); |
1093 | - Y.Assert.isTrue(banner.get('visible'), |
1094 | - 'Banner should be visible.'); |
1095 | - }, |
1096 | - |
1097 | - test_info_type_public_event: function () { |
1098 | - var banner = Y.lp.app.banner.privacy.getPrivacyBanner(); |
1099 | - var new_text = 'New custom text'; |
1100 | - |
1101 | - Y.fire('privacy_banner:show', { |
1102 | - text: new_text |
1103 | - }); |
1104 | - Y.fire('information_type:is_public'); |
1105 | - var body = Y.one('body'); |
1106 | - Y.Assert.isTrue(body.hasClass('public'), 'Body should be public'); |
1107 | - Y.Assert.isFalse(banner.get('visible'), |
1108 | - 'Banner should not be visible.'); |
1109 | - } |
1110 | - })); |
1111 | - |
1112 | -}, '0.1', {'requires': ['test', 'test-console', 'lp.app.banner.privacy']}); |
1113 | |
1114 | === modified file 'lib/lp/app/javascript/information_type.js' |
1115 | --- lib/lp/app/javascript/information_type.js 2012-10-04 14:17:23 +0000 |
1116 | +++ lib/lp/app/javascript/information_type.js 2012-11-12 13:21:28 +0000 |
1117 | @@ -44,6 +44,29 @@ |
1118 | emitFacade: true |
1119 | }); |
1120 | |
1121 | + |
1122 | +/** |
1123 | + * Provide some logic to check if this is a private inducing event. This could |
1124 | + * be due to a non-public information type or as security related information |
1125 | + * type/value. |
1126 | + */ |
1127 | +var is_private_event = function (value) { |
1128 | + var is_private = false; |
1129 | + if (ns.get_cache_data_from_key(value, |
1130 | + 'value', |
1131 | + 'is_private')) { |
1132 | + |
1133 | + is_private = true; |
1134 | + } |
1135 | + |
1136 | + if (value.indexOf('SECURITY') !== -1) { |
1137 | + is_private = true; |
1138 | + } |
1139 | + |
1140 | + return is_private; |
1141 | +}; |
1142 | + |
1143 | + |
1144 | /** |
1145 | * Wire up a helper event so that if someone changes the event, we take care |
1146 | * of also firing any is_private/is_public event shortcuts others want to |
1147 | @@ -53,14 +76,13 @@ |
1148 | * instead of having each module needing to know the location in the LP.cache |
1149 | * and such. |
1150 | */ |
1151 | + |
1152 | Y.on(ns.EV_CHANGE, function (ev) { |
1153 | if (!ev.value) { |
1154 | throw('Information type change event without new value'); |
1155 | } |
1156 | |
1157 | - if (ns.get_cache_data_from_key(ev.value, |
1158 | - 'value', |
1159 | - 'is_private')) { |
1160 | + if (is_private_event(ev.value)) { |
1161 | Y.fire(ns.EV_ISPRIVATE, { |
1162 | text: ns.get_banner_text(ev.value), |
1163 | value: ev.value |
1164 | @@ -155,16 +177,33 @@ |
1165 | }; |
1166 | |
1167 | ns.get_banner_text = function(value) { |
1168 | - var text_template = "This page contains {info_type} information."; |
1169 | - var info_type = ns.get_cache_data_from_key(value, 'value', 'name'); |
1170 | - return Y.Lang.sub(text_template, {'info_type': info_type}); |
1171 | + // Construct a different message for security related banner content. |
1172 | + var text; |
1173 | + if (value.indexOf('SECURITY') !== -1) { |
1174 | + var security_text = "This report will be private " + |
1175 | + "because it is a security " + |
1176 | + "vulnerability. You can " + |
1177 | + "disclose it later."; |
1178 | + text = security_text; |
1179 | + } else { |
1180 | + var text_template = "This page contains {info_type} information."; |
1181 | + var info_type = ns.get_cache_data_from_key(value, 'value', 'name'); |
1182 | + text = Y.Lang.sub(text_template, {'info_type': info_type}); |
1183 | + } |
1184 | + return text; |
1185 | }; |
1186 | |
1187 | ns.save_success = function(widget, context, value, subscribers_list, |
1188 | result_data) { |
1189 | context.information_type = |
1190 | ns.get_cache_data_from_key(value, 'value', 'name'); |
1191 | - ns.update_privacy_banner(value); |
1192 | + |
1193 | + // Let the world know the information type has been updated. Allows |
1194 | + // banners to update. |
1195 | + Y.fire(ns.EV_CHANGE, { |
1196 | + value: value |
1197 | + }); |
1198 | + |
1199 | widget._showSucceeded(); |
1200 | if (Y.Lang.isObject(result_data)) { |
1201 | var subscribers = result_data.subscription_data; |
1202 | @@ -344,27 +383,7 @@ |
1203 | } |
1204 | }; |
1205 | |
1206 | -/** |
1207 | - * Update the privacy banner to display the specified information type value. |
1208 | - * |
1209 | - * @param value |
1210 | - */ |
1211 | -ns.update_privacy_banner = function(value) { |
1212 | - var body = Y.one('body'); |
1213 | - var privacy_banner = Y.lp.app.banner.privacy.getPrivacyBanner( |
1214 | - undefined, skip_animation); |
1215 | - var private_type = LP.cache.information_type_data[value].is_private; |
1216 | - if (private_type) { |
1217 | - body.replaceClass('public', 'private'); |
1218 | - var banner_text = ns.get_banner_text(value); |
1219 | - privacy_banner.updateText(banner_text); |
1220 | - privacy_banner.show(); |
1221 | - } else { |
1222 | - body.replaceClass('private', 'public'); |
1223 | - privacy_banner.hide(); |
1224 | - } |
1225 | -}; |
1226 | |
1227 | }, "0.1", {"requires": [ |
1228 | "base", "oop", "node", "event", "io-base", "lp.mustache", "lp.app.choice", |
1229 | - "lp.bugs.bugtask_index", "lp.app.banner.privacy", "lp.ui.choiceedit"]}); |
1230 | + "lp.bugs.bugtask_index", "lp.ui.choiceedit"]}); |
1231 | |
1232 | === modified file 'lib/lp/app/javascript/tests/test_information_type.js' |
1233 | --- lib/lp/app/javascript/tests/test_information_type.js 2012-10-26 10:00:20 +0000 |
1234 | +++ lib/lp/app/javascript/tests/test_information_type.js 2012-11-12 13:21:28 +0000 |
1235 | @@ -84,22 +84,6 @@ |
1236 | privacy_link, this.lp_client, LP.cache.bug, null, true); |
1237 | }, |
1238 | |
1239 | - _shim_privacy_banner: function () { |
1240 | - var old_func = Y.lp.app.banner.privacy.getPrivacyBanner; |
1241 | - Y.lp.app.banner.privacy.getPrivacyBanner = function () { |
1242 | - return { |
1243 | - show: function () { Y.fire('test:banner:show'); }, |
1244 | - hide: function () { Y.fire('test:banner:hide'); }, |
1245 | - updateText: function () { Y.fire('test:banner:update'); } |
1246 | - }; |
1247 | - }; |
1248 | - return old_func; |
1249 | - }, |
1250 | - |
1251 | - _unshim_privacy_banner: function (old_func) { |
1252 | - Y.lp.app.banner.privacy.getPrivacyBanner = old_func; |
1253 | - }, |
1254 | - |
1255 | test_library_exists: function () { |
1256 | Y.Assert.isObject(Y.lp.app.information_type, |
1257 | "Cannot locate the lp.app.information_type module"); |
1258 | @@ -142,53 +126,9 @@ |
1259 | ns.save_success = orig_save_success; |
1260 | }, |
1261 | |
1262 | - // Setting a private type shows the privacy banner. |
1263 | - test_save_success_private: function() { |
1264 | - this.makeWidget(); |
1265 | - var old_func = this._shim_privacy_banner(); |
1266 | - var hide_flag = false; |
1267 | - var update_flag = false; |
1268 | - Y.on('test:banner:show', function() { |
1269 | - hide_flag = true; |
1270 | - }); |
1271 | - Y.on('test:banner:update', function() { |
1272 | - update_flag = true; |
1273 | - }); |
1274 | - |
1275 | - ns.save_success(this.widget, LP.cache.bug, |
1276 | - 'PROPRIETARY'); |
1277 | - var body = Y.one('body'); |
1278 | - Y.Assert.isTrue(body.hasClass('private')); |
1279 | - Y.Assert.isTrue(hide_flag); |
1280 | - Y.Assert.isTrue(update_flag); |
1281 | - Y.Assert.areEqual( |
1282 | - 'Proprietary', LP.cache.bug.information_type); |
1283 | - this._unshim_privacy_banner(old_func); |
1284 | - }, |
1285 | - |
1286 | - // Setting a public type hides the privacy banner. |
1287 | - test_save_success_public: function() { |
1288 | - this.makeWidget(); |
1289 | - var old_func = this._shim_privacy_banner(); |
1290 | - var flag = false; |
1291 | - Y.on('test:banner:hide', function() { |
1292 | - flag = true; |
1293 | - }); |
1294 | - var summary = Y.one('#information-type-summary'); |
1295 | - summary.replaceClass('public', 'private'); |
1296 | - |
1297 | - ns.save_success(this.widget, 'PUBLIC', 'PUBLIC'); |
1298 | - var body = Y.one('body'); |
1299 | - Y.Assert.isTrue(body.hasClass('public')); |
1300 | - Y.Assert.isTrue(flag); |
1301 | - Y.Assert.areEqual('Public', LP.cache.bug.information_type); |
1302 | - this._unshim_privacy_banner(old_func); |
1303 | - }, |
1304 | - |
1305 | // A successful save updates the subscribers portlet. |
1306 | test_save_success_with_subscribers_data: function() { |
1307 | this.makeWidget(); |
1308 | - var old_func = this._shim_privacy_banner(); |
1309 | var flag = false; |
1310 | Y.on('test:banner:hide', function() { |
1311 | flag = true; |
1312 | @@ -216,7 +156,6 @@ |
1313 | Y.Assert.isTrue(load_subscribers_called); |
1314 | Y.Assert.areEqual('value1', window.LP.cache.item1); |
1315 | Y.Assert.areEqual('value2', window.LP.cache.item2); |
1316 | - this._unshim_privacy_banner(old_func); |
1317 | }, |
1318 | |
1319 | // A successful save updates the task actions. |
1320 | |
1321 | === added file 'lib/lp/app/javascript/ui/assets/skins/sam/banner.css' |
1322 | --- lib/lp/app/javascript/ui/assets/skins/sam/banner.css 1970-01-01 00:00:00 +0000 |
1323 | +++ lib/lp/app/javascript/ui/assets/skins/sam/banner.css 2012-11-12 13:21:28 +0000 |
1324 | @@ -0,0 +1,109 @@ |
1325 | +/* JS Banner styling */ |
1326 | +.yui3-banner { |
1327 | + /* Default to not visible so we can fade in */ |
1328 | + opacity: 1; |
1329 | + |
1330 | + /* Animations for fade-in/out */ |
1331 | + -webkit-transition: opacity 0.3s ease-in; |
1332 | + -moz-transition: opacity 0.3s ease-in; |
1333 | + transition: opacity 0.3s ease-in; |
1334 | + |
1335 | + width: 100%; |
1336 | +} |
1337 | + |
1338 | +.yui3-banner.yui3-banner-hidden { |
1339 | + opacity: 0; |
1340 | +} |
1341 | + |
1342 | +/* Nasty hack to get the bar moved since it's absolutely positioned |
1343 | + * This also needs to be updated |
1344 | + * */ |
1345 | +body.beta #locationbar, body.private #locationbar { |
1346 | + top: 47px; |
1347 | +} |
1348 | + |
1349 | +/* If we have both classes make room for two banners height */ |
1350 | +body.beta.private #locationbar { |
1351 | + top: 94px; |
1352 | +} |
1353 | + |
1354 | +/* If the container exists make sure we start out with the rest of the page |
1355 | + * bumped down the starting distance to reduce flash effect |
1356 | + */ |
1357 | +.beta_banner_container, .private_banner_container { |
1358 | + min-height: 45px; |
1359 | +} |
1360 | + |
1361 | +.yui3-banner-content { |
1362 | + box-shadow: 0 0 5px #333; |
1363 | + background-color: #666; |
1364 | + color: #fff; |
1365 | + display: block; |
1366 | + font-size: 14px; |
1367 | + font-weight: bold; |
1368 | + line-height: 21px; |
1369 | + padding: 8px 20px; |
1370 | + text-align: left; |
1371 | + text-shadow: 0 -1px 0 #631616; |
1372 | + z-index: 10; |
1373 | +} |
1374 | + |
1375 | +.yui3-banner-content .badge { |
1376 | + display: inline-block; |
1377 | + height: 21px; |
1378 | + margin-right: 10px; |
1379 | + padding: 0; |
1380 | + vertical-align: middle; |
1381 | + width: 20px; |
1382 | +} |
1383 | +.yui3-banner-content .banner-content {} |
1384 | + |
1385 | +.yui3-banner-content.beta { |
1386 | + /* Some of these are required to override .beta CSS */ |
1387 | + |
1388 | + /* Defined for browsers that don't support transparency */ |
1389 | + background-color: #606060; |
1390 | + /* Transparent background for browsers that support it */ |
1391 | + background-color: rgba(64, 64, 64, 0.9); |
1392 | + height: auto; |
1393 | + margin-top: 0px; |
1394 | + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.5); |
1395 | + width: auto; |
1396 | +} |
1397 | +.yui3-banner-content.beta .yui3-banner-content-content {} |
1398 | +.yui3-banner-content.beta .badge { |
1399 | + /* sprite-ref: icon-sprites */ |
1400 | + background-color: #c10000; |
1401 | + background: linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%); |
1402 | + background: -moz-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%); |
1403 | + background: -ms-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%); |
1404 | + background: -o-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%); |
1405 | + background: -webkit-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%); |
1406 | + border-radius: 5px; |
1407 | + border-top: 1px solid #e20000; |
1408 | + font-size: 12px; |
1409 | + font-weight: bold; |
1410 | + margin-right: 12px; |
1411 | + padding: 3px 6px 4px 6px; |
1412 | + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); |
1413 | + width: auto; |
1414 | +} |
1415 | + |
1416 | +.yui3-banner-content.beta .beta-feature { |
1417 | + font-weight: bold; |
1418 | +} |
1419 | +.yui3-banner-content.beta .info-link { |
1420 | + color: #4884ef; |
1421 | +} |
1422 | + |
1423 | +.yui3-banner-content.private { |
1424 | + /* Define colour for browsers that don't support transparency */ |
1425 | + background: #8d1f1f; |
1426 | + /* Set transparent background for browsers that support it */ |
1427 | + background: rgba(125,0,0,0.9); |
1428 | +} |
1429 | +.yui3-banner-content.private .banner-content {} |
1430 | +.yui3-banner-content.private .badge { |
1431 | + background: url(/@@/notification-private.png); /* sprite-ref: icon-sprites */ |
1432 | + background-repeat: no-repeat; |
1433 | +} |
1434 | |
1435 | === removed file 'lib/lp/app/javascript/ui/assets/skins/sam/banner.css' |
1436 | --- lib/lp/app/javascript/ui/assets/skins/sam/banner.css 2012-11-09 19:06:16 +0000 |
1437 | +++ lib/lp/app/javascript/ui/assets/skins/sam/banner.css 1970-01-01 00:00:00 +0000 |
1438 | @@ -1,109 +0,0 @@ |
1439 | -/* JS Banner styling */ |
1440 | -.yui3-banner { |
1441 | - /* Default to not visible so we can fade in */ |
1442 | - opacity: 1; |
1443 | - |
1444 | - /* Animations for fade-in/out */ |
1445 | - -webkit-transition: opacity 0.3s ease-in; |
1446 | - -moz-transition: opacity 0.3s ease-in; |
1447 | - transition: opacity 0.3s ease-in; |
1448 | - |
1449 | - width: 100%; |
1450 | -} |
1451 | - |
1452 | -.yui3-banner.yui3-banner-hidden { |
1453 | - opacity: 0; |
1454 | -} |
1455 | - |
1456 | -/* Nasty hack to get the bar moved since it's absolutely positioned |
1457 | - * This also needs to be updated |
1458 | - */ |
1459 | -body.beta #locationbar, body.private #locationbar { |
1460 | - top: 47px; |
1461 | -} |
1462 | - |
1463 | -/* If we have both classes make room for two banners height */ |
1464 | -body.beta.private #locationbar { |
1465 | - top: 94px; |
1466 | -} |
1467 | - |
1468 | -/* If the container exists make sure we start out with the rest of the page |
1469 | - * bumped down the starting distance to reduce flash effect |
1470 | - */ |
1471 | -.beta_banner_container, .private_banner_container { |
1472 | - min-height: 45px; |
1473 | -} |
1474 | - |
1475 | -.yui3-banner-content { |
1476 | - box-shadow: 0 0 5px #333; |
1477 | - background-color: #666; |
1478 | - color: #fff; |
1479 | - display: block; |
1480 | - font-size: 14px; |
1481 | - font-weight: bold; |
1482 | - line-height: 21px; |
1483 | - padding: 8px 20px; |
1484 | - text-align: left; |
1485 | - text-shadow: 0 -1px 0 #631616; |
1486 | - z-index: 10; |
1487 | -} |
1488 | - |
1489 | -.yui3-banner-content .badge { |
1490 | - display: inline-block; |
1491 | - height: 21px; |
1492 | - margin-right: 10px; |
1493 | - padding: 0; |
1494 | - vertical-align: middle; |
1495 | - width: 20px; |
1496 | -} |
1497 | -.yui3-banner-content .banner-content {} |
1498 | - |
1499 | -.yui3-banner-content.beta { |
1500 | - /* Some of these are required to override .beta CSS */ |
1501 | - |
1502 | - /* Defined for browsers that don't support transparency */ |
1503 | - background-color: #606060; |
1504 | - /* Transparent background for browsers that support it */ |
1505 | - background-color: rgba(64, 64, 64, 0.9); |
1506 | - height: auto; |
1507 | - margin-top: 0px; |
1508 | - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.5); |
1509 | - width: auto; |
1510 | -} |
1511 | -.yui3-banner-content.beta .yui3-banner-content-content {} |
1512 | -.yui3-banner-content.beta .badge { |
1513 | - /* sprite-ref: icon-sprites */ |
1514 | - background-color: #c10000; |
1515 | - background: linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%); |
1516 | - background: -moz-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%); |
1517 | - background: -ms-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%); |
1518 | - background: -o-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%); |
1519 | - background: -webkit-linear-gradient(bottom, rgb(158,0,0) 0%, rgb(193,0,0) 70%); |
1520 | - border-radius: 5px; |
1521 | - border-top: 1px solid #e20000; |
1522 | - font-size: 12px; |
1523 | - font-weight: bold; |
1524 | - margin-right: 12px; |
1525 | - padding: 3px 6px 4px 6px; |
1526 | - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); |
1527 | - width: auto; |
1528 | -} |
1529 | - |
1530 | -.yui3-banner-content.beta .beta-feature { |
1531 | - font-weight: bold; |
1532 | -} |
1533 | -.yui3-banner-content.beta .info-link { |
1534 | - color: #4884ef; |
1535 | -} |
1536 | - |
1537 | -.yui3-banner-content.private { |
1538 | - /* Define colour for browsers that don't support transparency */ |
1539 | - background: #8d1f1f; |
1540 | - /* Set transparent background for browsers that support it */ |
1541 | - background: rgba(125,0,0,0.9); |
1542 | -} |
1543 | -.yui3-banner-content.private .banner-content {} |
1544 | -.yui3-banner-content.private .badge { |
1545 | - background: url(/@@/notification-private.png); |
1546 | - background-repeat: no-repeat; |
1547 | -} |
1548 | |
1549 | === added file 'lib/lp/app/javascript/ui/banner.js' |
1550 | --- lib/lp/app/javascript/ui/banner.js 1970-01-01 00:00:00 +0000 |
1551 | +++ lib/lp/app/javascript/ui/banner.js 2012-11-12 13:21:28 +0000 |
1552 | @@ -0,0 +1,316 @@ |
1553 | +/* |
1554 | + * Copyright 2012 Canonical Ltd. This software is licensed under the |
1555 | + * GNU Affero General Public License version 3 (see the file LICENSE). |
1556 | + * |
1557 | + * Notification banner widget |
1558 | + * |
1559 | + * @module lp.ui.banner |
1560 | + * @namespace lp.ui |
1561 | + * @module banner |
1562 | + */ |
1563 | +YUI.add('lp.ui.banner', function (Y) { |
1564 | + |
1565 | + var ns = Y.namespace('lp.ui.banner'); |
1566 | + |
1567 | + // GLOBALS |
1568 | + ns.PRIVATE = 'private'; |
1569 | + ns.BETA = 'beta'; |
1570 | + |
1571 | + /** |
1572 | + * Banner widget base class |
1573 | + * |
1574 | + * This is the base Banner, you're supposed to supply some message data to |
1575 | + * generate the banner in the proper method. |
1576 | + * |
1577 | + * This banner provides all shared functionality between the Privacy and |
1578 | + * Beta banners. |
1579 | + * |
1580 | + * @class Banner |
1581 | + * @extends Y.Widget |
1582 | + * |
1583 | + */ |
1584 | + ns.Banner = Y.Base.create('banner', Y.Widget, [], { |
1585 | + template: [ |
1586 | + '<div class="banner">', |
1587 | + '<span class="badge {{ banner_type }}">{{ badge_text }}</span>', |
1588 | + '<span class="banner-content">{{{ content }}}</span>', |
1589 | + '</div>' |
1590 | + ].join(''), |
1591 | + |
1592 | + |
1593 | + /** |
1594 | + * Bind events that our widget supports such as closing the banner. |
1595 | + * |
1596 | + * We also watch the destroy event to clean up side effect css we |
1597 | + * created. |
1598 | + * |
1599 | + * @method bindUI |
1600 | + */ |
1601 | + bindUI: function () { |
1602 | + this.on('destroy', function (ev) { |
1603 | + // XXX: Bug #1076074 |
1604 | + var body = Y.one('body'); |
1605 | + var banner_type = this.get('banner_type'); |
1606 | + body.removeClass(banner_type); |
1607 | + |
1608 | + // Remove any container the page might have provided for us to |
1609 | + // start out with. |
1610 | + var container_class = '.' + banner_type + '_banner_container'; |
1611 | + var container = Y.one(container_class); |
1612 | + if (container) { |
1613 | + Y.one(container_class).remove(); |
1614 | + } |
1615 | + }); |
1616 | + |
1617 | + this.after('contentChange', function () { |
1618 | + this.renderUI(); |
1619 | + }); |
1620 | + }, |
1621 | + |
1622 | + /** |
1623 | + * Default initialize method. |
1624 | + * |
1625 | + * @method initialize |
1626 | + * @param {Object} cfg |
1627 | + */ |
1628 | + initialize: function (cfg) { |
1629 | + }, |
1630 | + |
1631 | + /** |
1632 | + * Widget render method to generate the html of the widget. |
1633 | + * |
1634 | + * @method renderUI |
1635 | + */ |
1636 | + renderUI: function () { |
1637 | + var contentBox = this.get('contentBox'); |
1638 | + contentBox.addClass(this.get('banner_type')); |
1639 | + var html = Y.lp.mustache.to_html(this.template, this.getAttrs()); |
1640 | + contentBox.setHTML(html); |
1641 | + |
1642 | + // XXX: Bug #1076074 |
1643 | + // Needs to get cleaned up. Only applies to the global |
1644 | + // banners and not to other ones which we're working to allow. |
1645 | + // This is currently required because the #locationbar is |
1646 | + // absolutely located and needs to be moved as banners change. |
1647 | + var body = Y.one('body'); |
1648 | + body.addClass(this.get('banner_type')); |
1649 | + |
1650 | + if (this.get('visible')) { |
1651 | + this.show(); |
1652 | + } |
1653 | + }, |
1654 | + |
1655 | + /** |
1656 | + * We need to override show so that we force a browser repaint which |
1657 | + * allows our CSS3 animation to run. Otherwise the browser sees we |
1658 | + * added new DOM elements and jumps straight to the finished animation |
1659 | + * point. |
1660 | + * |
1661 | + * @method show |
1662 | + */ |
1663 | + show: function () { |
1664 | + var _node = this.get('boundingBox')._node; |
1665 | + var getComputedStyle = document.defaultView.getComputedStyle; |
1666 | + _node.style.display = getComputedStyle(_node).display; |
1667 | + return this.set('visible', true); |
1668 | + } |
1669 | + |
1670 | + }, { |
1671 | + ATTRS: { |
1672 | + /** |
1673 | + * Instead of a sprite we might have text such as the Beta banner. |
1674 | + * |
1675 | + * @attribute badge_text |
1676 | + * @default undefined |
1677 | + * @type {String} |
1678 | + */ |
1679 | + badge_text: {}, |
1680 | + |
1681 | + /** |
1682 | + * The Banner is meant to house some message to the user provided |
1683 | + * by this content. It can be html and is not escaped for that |
1684 | + * reason. |
1685 | + * |
1686 | + * @attribute content |
1687 | + * @default undefined |
1688 | + * @type {String} |
1689 | + */ |
1690 | + content: {}, |
1691 | + |
1692 | + /** |
1693 | + * This is listed to help aid in discovery of how the container |
1694 | + * node for the widget is determined. It's passed into the |
1695 | + * render() method and the Widget constructs itself inside of |
1696 | + * there. |
1697 | + * |
1698 | + * @attribute boundingBox |
1699 | + * @default undefined |
1700 | + * @type {Node} |
1701 | + */ |
1702 | + boundingBox: { |
1703 | + |
1704 | + }, |
1705 | + |
1706 | + /** |
1707 | + * Much of the Widget is determined by the type of banner it is. |
1708 | + * See the constants defined PRIVATE and BETA for two known types. |
1709 | + * If you set this manually you'll be able to provide custom |
1710 | + * styling as required because the type is used as a css class |
1711 | + * property. |
1712 | + * |
1713 | + * @attribute banner_type |
1714 | + * @default undefined |
1715 | + * @type {String} |
1716 | + */ |
1717 | + banner_type: {}, |
1718 | + |
1719 | + /** |
1720 | + * Start out as not visible which should render as opacity 0, then |
1721 | + * we update it and it animates due to our css3. |
1722 | + * |
1723 | + * @attribute visible |
1724 | + * @default false |
1725 | + * @type {Bool} |
1726 | + */ |
1727 | + visible: { |
1728 | + value: false |
1729 | + } |
1730 | + } |
1731 | + }); |
1732 | + |
1733 | + /** |
1734 | + * Beta Banner widget |
1735 | + * |
1736 | + * This is the Beta feature banner which needs to know about the title and |
1737 | + * url of the feature to construct the content correctly. Features are |
1738 | + * meant to be matched to the current LP.cache.related_features data |
1739 | + * available. |
1740 | + * |
1741 | + * @class BetaBanner |
1742 | + * @extends Banner |
1743 | + * |
1744 | + */ |
1745 | + ns.BetaBanner = Y.Base.create('banner', ns.Banner, [], { |
1746 | + |
1747 | + }, { |
1748 | + ATTRS: { |
1749 | + /** |
1750 | + * @attribute badge_text |
1751 | + * @default "BETA!" |
1752 | + * @type {String} |
1753 | + */ |
1754 | + badge_text: { |
1755 | + value: 'BETA!' |
1756 | + }, |
1757 | + |
1758 | + /** |
1759 | + * The content for the beta banner is constructed from hard coded |
1760 | + * content and the list of enabled beta features currently |
1761 | + * relevant to the page. |
1762 | + * |
1763 | + * @attribute content |
1764 | + * @default {generated} |
1765 | + * @type {String} |
1766 | + */ |
1767 | + content: { |
1768 | + getter: function () { |
1769 | + var content = "Some parts of this page are in beta: "; |
1770 | + var key; |
1771 | + // We need to process the features to build the features |
1772 | + // that apply. |
1773 | + var features = this.get('features'); |
1774 | + for (key in features) { |
1775 | + if (features.hasOwnProperty(key)) { |
1776 | + var obj = features[key]; |
1777 | + if (obj.is_beta) { |
1778 | + content = content + [ |
1779 | + '<span class="beta-feature">', |
1780 | + obj.title, |
1781 | + ' <a class="info-link" href="', |
1782 | + obj.url + '">(read more)</a>', |
1783 | + '</span>' |
1784 | + ].join(''); |
1785 | + } |
1786 | + } |
1787 | + } |
1788 | + return content; |
1789 | + } |
1790 | + }, |
1791 | + |
1792 | + /** |
1793 | + * features is a nested object of the beta features going. See |
1794 | + * LP.cache.related_features for the list of features. We only |
1795 | + * want those related features that are in beta. |
1796 | + * Ex: { |
1797 | + * disclosure.private_projects.enabled: { |
1798 | + * is_beta: true, |
1799 | + * title: "", |
1800 | + * url: "http://blog.ld.net/general/private-projects-beta", |
1801 | + * value: "true" |
1802 | + * } |
1803 | + * } |
1804 | + * @attribute features |
1805 | + * @default {} |
1806 | + * @type {Object} |
1807 | + */ |
1808 | + features: {}, |
1809 | + |
1810 | + /** |
1811 | + * Manually force the banner type so users don't need to set it. |
1812 | + * This is a beta banner class. |
1813 | + * |
1814 | + * @attribute banner_type |
1815 | + * @default BETA |
1816 | + * @type {String} |
1817 | + */ |
1818 | + banner_type: { |
1819 | + value: ns.BETA |
1820 | + } |
1821 | + |
1822 | + } |
1823 | + }); |
1824 | + |
1825 | + /** |
1826 | + * Private Banner widget |
1827 | + * |
1828 | + * This is the Private feature banner which is pretty basic. |
1829 | + * |
1830 | + * Note that this doesn't automatically follow the information type code. |
1831 | + * Nor does it listen to the choice widgets and try to update. It's purely |
1832 | + * meant to function as told to do so. Most of the work around making sure |
1833 | + * the banner shows and works properly is in the View code in global.js. |
1834 | + * |
1835 | + * @class PrivateBanner |
1836 | + * @extends Banner |
1837 | + * |
1838 | + */ |
1839 | + ns.PrivateBanner = Y.Base.create('banner', ns.Banner, [], { |
1840 | + |
1841 | + }, { |
1842 | + ATTRS: { |
1843 | + badge_text: { |
1844 | + value: '' |
1845 | + }, |
1846 | + |
1847 | + content: { |
1848 | + value: 'The information on this page is private.' |
1849 | + }, |
1850 | + |
1851 | + /** |
1852 | + * Manually force the banner type so users don't need to set it. |
1853 | + * This is a beta banner class. |
1854 | + * |
1855 | + * @attribute banner_type |
1856 | + * @default BETA |
1857 | + * @type {String} |
1858 | + */ |
1859 | + banner_type: { |
1860 | + value: ns.PRIVATE |
1861 | + }, |
1862 | + |
1863 | + } |
1864 | + }); |
1865 | + |
1866 | +}, '0.1', { |
1867 | + requires: ['base', 'node', 'anim', 'widget', 'lp.mustache', 'yui-log'] |
1868 | +}); |
1869 | |
1870 | === removed file 'lib/lp/app/javascript/ui/banner.js' |
1871 | --- lib/lp/app/javascript/ui/banner.js 2012-11-09 18:55:02 +0000 |
1872 | +++ lib/lp/app/javascript/ui/banner.js 1970-01-01 00:00:00 +0000 |
1873 | @@ -1,315 +0,0 @@ |
1874 | -/* |
1875 | - * Copyright 2012 Canonical Ltd. This software is licensed under the |
1876 | - * GNU Affero General Public License version 3 (see the file LICENSE). |
1877 | - * |
1878 | - * Notification banner widget |
1879 | - * |
1880 | - * @module lp.ui.banner |
1881 | - * @namespace lp.ui |
1882 | - * @module banner |
1883 | - */ |
1884 | -YUI.add('lp.ui.banner', function (Y) { |
1885 | - |
1886 | - var ns = Y.namespace('lp.ui.banner'); |
1887 | - |
1888 | - // GLOBALS |
1889 | - ns.PRIVATE = 'private'; |
1890 | - ns.BETA = 'beta'; |
1891 | - |
1892 | - /** |
1893 | - * Banner widget base class |
1894 | - * |
1895 | - * This is the base Banner, you're supposed to supply some message data to |
1896 | - * generate the banner in the proper method. |
1897 | - * |
1898 | - * This banner provides all shared functionality between the Privacy and |
1899 | - * Beta banners. |
1900 | - * |
1901 | - * @class Banner |
1902 | - * @extends Y.Widget |
1903 | - * |
1904 | - */ |
1905 | - ns.Banner = Y.Base.create('banner', Y.Widget, [], { |
1906 | - template: [ |
1907 | - '<div class="banner">', |
1908 | - '<span class="badge {{ banner_type }}">{{ badge_text }}</span>', |
1909 | - '<span class="banner-content">{{{ content }}}</span>', |
1910 | - '</div>' |
1911 | - ].join(''), |
1912 | - |
1913 | - |
1914 | - /** |
1915 | - * Bind events that our widget supports such as closing the banner. |
1916 | - * |
1917 | - * We also watch the destroy event to clean up side effect css we |
1918 | - * created. |
1919 | - * |
1920 | - * @method bindUI |
1921 | - */ |
1922 | - bindUI: function () { |
1923 | - this.on('destroy', function (ev) { |
1924 | - // XXX: Bug #1076074 |
1925 | - var body = Y.one('body'); |
1926 | - var banner_type = this.get('banner_type'); |
1927 | - body.removeClass(banner_type); |
1928 | - |
1929 | - // Remove any container the page might have provided for us to |
1930 | - // start out with. |
1931 | - var container_class = '.' + banner_type + '_banner_container'; |
1932 | - var container = Y.one(container_class); |
1933 | - if (container) { |
1934 | - Y.one(container_class).remove(); |
1935 | - } |
1936 | - }); |
1937 | - |
1938 | - this.after('contentChange', function () { |
1939 | - this.renderUI(); |
1940 | - }); |
1941 | - }, |
1942 | - |
1943 | - /** |
1944 | - * Default initialize method. |
1945 | - * |
1946 | - * @method initialize |
1947 | - * @param {Object} cfg |
1948 | - */ |
1949 | - initialize: function (cfg) { |
1950 | - }, |
1951 | - |
1952 | - /** |
1953 | - * Widget render method to generate the html of the widget. |
1954 | - * |
1955 | - * @method renderUI |
1956 | - */ |
1957 | - renderUI: function () { |
1958 | - var contentBox = this.get('contentBox'); |
1959 | - contentBox.addClass(this.get('banner_type')); |
1960 | - var html = Y.lp.mustache.to_html(this.template, this.getAttrs()); |
1961 | - contentBox.setHTML(html); |
1962 | - |
1963 | - // XXX: Bug #1076074 |
1964 | - // Needs to get cleaned up. Only applies to the global |
1965 | - // banners and not to other ones which we're working to allow. |
1966 | - // This is currently required because the #locationbar is |
1967 | - // absolutely located and needs to be moved as banners change. |
1968 | - var body = Y.one('body'); |
1969 | - body.addClass(this.get('banner_type')); |
1970 | - |
1971 | - if (this.get('visible')) { |
1972 | - this.show(); |
1973 | - } |
1974 | - }, |
1975 | - |
1976 | - /** |
1977 | - * We need to override show so that we force a browser repaint which |
1978 | - * allows our CSS3 animation to run. Otherwise the browser sees we |
1979 | - * added new DOM elements and jumps straight to the finished animation |
1980 | - * point. |
1981 | - * |
1982 | - * @method show |
1983 | - */ |
1984 | - show: function () { |
1985 | - var _node = this.get('boundingBox')._node; |
1986 | - var getComputedStyle = document.defaultView.getComputedStyle; |
1987 | - _node.style.display = getComputedStyle(_node).display; |
1988 | - return this.set('visible', true); |
1989 | - } |
1990 | - |
1991 | - }, { |
1992 | - ATTRS: { |
1993 | - /** |
1994 | - * Instead of a sprite we might have text such as the Beta banner. |
1995 | - * |
1996 | - * @attribute badge_text |
1997 | - * @default undefined |
1998 | - * @type {String} |
1999 | - */ |
2000 | - badge_text: {}, |
2001 | - |
2002 | - /** |
2003 | - * The Banner is meant to house some message to the user provided |
2004 | - * by this content. It can be html and is not escaped for that |
2005 | - * reason. |
2006 | - * |
2007 | - * @attribute content |
2008 | - * @default undefined |
2009 | - * @type {String} |
2010 | - */ |
2011 | - content: {}, |
2012 | - |
2013 | - /** |
2014 | - * This is listed to help aid in discovery of how the container |
2015 | - * node for the widget is determined. It's passed into the |
2016 | - * render() method and the Widget constructs itself inside of |
2017 | - * there. |
2018 | - * |
2019 | - * @attribute boundingBox |
2020 | - * @default undefined |
2021 | - * @type {Node} |
2022 | - */ |
2023 | - boundingBox: { |
2024 | - |
2025 | - }, |
2026 | - |
2027 | - /** |
2028 | - * Much of the Widget is determined by the type of banner it is. |
2029 | - * See the constants defined PRIVATE and BETA for two known types. |
2030 | - * If you set this manually you'll be able to provide custom |
2031 | - * styling as required because the type is used as a css class |
2032 | - * property. |
2033 | - * |
2034 | - * @attribute banner_type |
2035 | - * @default undefined |
2036 | - * @type {String} |
2037 | - */ |
2038 | - banner_type: {}, |
2039 | - |
2040 | - /** |
2041 | - * Start out as not visible which should render as opacity 0, then |
2042 | - * we update it and it animates due to our css3. |
2043 | - * |
2044 | - * @attribute visible |
2045 | - * @default false |
2046 | - * @type {Bool} |
2047 | - */ |
2048 | - visible: { |
2049 | - value: false |
2050 | - } |
2051 | - } |
2052 | - }); |
2053 | - |
2054 | - /** |
2055 | - * Beta Banner widget |
2056 | - * |
2057 | - * This is the Beta feature banner which needs to know about the title and |
2058 | - * url of the feature to construct the content correctly. Features are |
2059 | - * meant to be matched to the current LP.cache.related_features data |
2060 | - * available. |
2061 | - * |
2062 | - * @class BetaBanner |
2063 | - * @extends Banner |
2064 | - * |
2065 | - */ |
2066 | - ns.BetaBanner = Y.Base.create('banner', ns.Banner, [], { |
2067 | - |
2068 | - }, { |
2069 | - ATTRS: { |
2070 | - /** |
2071 | - * @attribute badge_text |
2072 | - * @default "BETA!" |
2073 | - * @type {String} |
2074 | - */ |
2075 | - badge_text: { |
2076 | - value: 'BETA!' |
2077 | - }, |
2078 | - |
2079 | - /** |
2080 | - * The content for the beta banner is constructed from hard coded |
2081 | - * content and the list of enabled beta features currently |
2082 | - * relevant to the page. |
2083 | - * |
2084 | - * @attribute content |
2085 | - * @default {generated} |
2086 | - * @type {String} |
2087 | - */ |
2088 | - content: { |
2089 | - getter: function () { |
2090 | - var content = "Some parts of this page are in beta: "; |
2091 | - var key; |
2092 | - // We need to process the features to build the features |
2093 | - // that apply. |
2094 | - var features = this.get('features'); |
2095 | - for (key in features) { |
2096 | - if (features.hasOwnProperty(key)) { |
2097 | - var obj = features[key]; |
2098 | - if (obj.is_beta) { |
2099 | - content = content + [ |
2100 | - '<span class="beta-feature">', |
2101 | - obj.title, |
2102 | - ' <a class="info-link" href="', |
2103 | - obj.url + '">(read more)</a>', |
2104 | - '</span>' |
2105 | - ].join(''); |
2106 | - } |
2107 | - } |
2108 | - } |
2109 | - return content; |
2110 | - } |
2111 | - }, |
2112 | - |
2113 | - /** |
2114 | - * features is a nested object of the beta features going. See |
2115 | - * LP.cache.related_features for the list of features. We only |
2116 | - * want those related features that are in beta. |
2117 | - * Ex: { |
2118 | - * disclosure.private_projects.enabled: { |
2119 | - * is_beta: true, |
2120 | - * title: "", |
2121 | - * url: "http://blog.ld.net/general/private-projects-beta", |
2122 | - * value: "true" |
2123 | - * } |
2124 | - * } |
2125 | - * @attribute features |
2126 | - * @default {} |
2127 | - * @type {Object} |
2128 | - */ |
2129 | - features: {}, |
2130 | - |
2131 | - /** |
2132 | - * Manually force the banner type so users don't need to set it. |
2133 | - * This is a beta banner class. |
2134 | - * |
2135 | - * @attribute banner_type |
2136 | - * @default BETA |
2137 | - * @type {String} |
2138 | - */ |
2139 | - banner_type: { |
2140 | - value: ns.BETA |
2141 | - } |
2142 | - |
2143 | - } |
2144 | - }); |
2145 | - |
2146 | - /** |
2147 | - * Private Banner widget |
2148 | - * |
2149 | - * This is the Private feature banner which is pretty basic. |
2150 | - * |
2151 | - * Note that this doesn't automatically follow the information type code. |
2152 | - * Nor does it listen to the choice widgets and try to update. It's purely |
2153 | - * meant to function as told to do so. Most of the work around making sure |
2154 | - * the banner shows and works properly is in the View code in global.js. |
2155 | - * |
2156 | - * @class PrivateBanner |
2157 | - * @extends Banner |
2158 | - * |
2159 | - */ |
2160 | - ns.PrivateBanner = Y.Base.create('banner', ns.Banner, [], { |
2161 | - |
2162 | - }, { |
2163 | - ATTRS: { |
2164 | - badge_text: { |
2165 | - value: '' |
2166 | - }, |
2167 | - |
2168 | - content: { |
2169 | - value: 'The information on this page is private.' |
2170 | - }, |
2171 | - |
2172 | - /** |
2173 | - * Manually force the banner type so users don't need to set it. |
2174 | - * This is a beta banner class. |
2175 | - * |
2176 | - * @attribute banner_type |
2177 | - * @default BETA |
2178 | - * @type {String} |
2179 | - */ |
2180 | - banner_type: { |
2181 | - value: ns.PRIVATE |
2182 | - } |
2183 | - } |
2184 | - }); |
2185 | - |
2186 | -}, '0.1', { |
2187 | - requires: ['base', 'node', 'anim', 'widget', 'lp.mustache', 'yui-log'] |
2188 | -}); |
2189 | |
2190 | === added directory 'lib/lp/app/javascript/ui/tests' |
2191 | === removed directory 'lib/lp/app/javascript/ui/tests' |
2192 | === added file 'lib/lp/app/javascript/ui/tests/test_banner.html' |
2193 | --- lib/lp/app/javascript/ui/tests/test_banner.html 1970-01-01 00:00:00 +0000 |
2194 | +++ lib/lp/app/javascript/ui/tests/test_banner.html 2012-11-12 13:21:28 +0000 |
2195 | @@ -0,0 +1,49 @@ |
2196 | +<!DOCTYPE html> |
2197 | +<!-- |
2198 | +Copyright 2012 Canonical Ltd. This software is licensed under the |
2199 | +GNU Affero General Public License version 3 (see the file LICENSE). |
2200 | +--> |
2201 | + |
2202 | +<html> |
2203 | + <head> |
2204 | + <title>lp.ui.banner Tests</title> |
2205 | + |
2206 | + <!-- YUI and test setup --> |
2207 | + <script type="text/javascript" |
2208 | + src="../../../../../../build/js/yui/yui/yui.js"> |
2209 | + </script> |
2210 | + <link rel="stylesheet" |
2211 | + href="../../../../../../build/js/yui/console/assets/console-core.css" /> |
2212 | + <link rel="stylesheet" |
2213 | + href="../../../../../../build/js/yui/test-console/assets/skins/sam/test-console.css" /> |
2214 | + <link rel="stylesheet" |
2215 | + href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" /> |
2216 | + |
2217 | + <script type="text/javascript" |
2218 | + src="../../../../../../build/js/lp/app/testing/testrunner.js"></script> |
2219 | + <script type="text/javascript" |
2220 | + src="../../../../../build/js/lp/app/testing/helpers.js"></script> |
2221 | + |
2222 | + <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" /> |
2223 | + |
2224 | + <!-- Dependencies --> |
2225 | + <script type="text/javascript" |
2226 | + src="../../../../../../build/js/lp/app/mustache.js"></script> |
2227 | + |
2228 | + <!-- The module under test. --> |
2229 | + <script type="text/javascript" src="../banner.js"></script> |
2230 | + |
2231 | + <!-- Placeholder for any css asset for this module. --> |
2232 | + <link rel="stylesheet" href="../assets/skins/sam/banner.css" /> |
2233 | + |
2234 | + <!-- The test suite --> |
2235 | + <script type="text/javascript" src="test_banner.js"></script> |
2236 | + |
2237 | + </head> |
2238 | + <body class="yui3-skin-sam"> |
2239 | + <ul id="suites"> |
2240 | + <li>lp.ui.banner.test</li> |
2241 | + </ul> |
2242 | + <div id="fixture"></div> |
2243 | + </body> |
2244 | +</html> |
2245 | |
2246 | === removed file 'lib/lp/app/javascript/ui/tests/test_banner.html' |
2247 | --- lib/lp/app/javascript/ui/tests/test_banner.html 2012-11-09 18:46:31 +0000 |
2248 | +++ lib/lp/app/javascript/ui/tests/test_banner.html 1970-01-01 00:00:00 +0000 |
2249 | @@ -1,49 +0,0 @@ |
2250 | -<!DOCTYPE html> |
2251 | -<!-- |
2252 | -Copyright 2012 Canonical Ltd. This software is licensed under the |
2253 | -GNU Affero General Public License version 3 (see the file LICENSE). |
2254 | ---> |
2255 | - |
2256 | -<html> |
2257 | - <head> |
2258 | - <title>lp.ui.banner Tests</title> |
2259 | - |
2260 | - <!-- YUI and test setup --> |
2261 | - <script type="text/javascript" |
2262 | - src="../../../../../../build/js/yui/yui/yui.js"> |
2263 | - </script> |
2264 | - <link rel="stylesheet" |
2265 | - href="../../../../../../build/js/yui/console/assets/console-core.css" /> |
2266 | - <link rel="stylesheet" |
2267 | - href="../../../../../../build/js/yui/test-console/assets/skins/sam/test-console.css" /> |
2268 | - <link rel="stylesheet" |
2269 | - href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" /> |
2270 | - |
2271 | - <script type="text/javascript" |
2272 | - src="../../../../../../build/js/lp/app/testing/testrunner.js"></script> |
2273 | - <script type="text/javascript" |
2274 | - src="../../../../../build/js/lp/app/testing/helpers.js"></script> |
2275 | - |
2276 | - <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" /> |
2277 | - |
2278 | - <!-- Dependencies --> |
2279 | - <script type="text/javascript" |
2280 | - src="../../../../../../build/js/lp/app/mustache.js"></script> |
2281 | - |
2282 | - <!-- The module under test. --> |
2283 | - <script type="text/javascript" src="../banner.js"></script> |
2284 | - |
2285 | - <!-- Placeholder for any css asset for this module. --> |
2286 | - <link rel="stylesheet" href="../assets/skins/sam/banner.css" /> |
2287 | - |
2288 | - <!-- The test suite --> |
2289 | - <script type="text/javascript" src="test_banner.js"></script> |
2290 | - |
2291 | - </head> |
2292 | - <body class="yui3-skin-sam"> |
2293 | - <ul id="suites"> |
2294 | - <li>lp.ui.banner.test</li> |
2295 | - </ul> |
2296 | - <div id="fixture"></div> |
2297 | - </body> |
2298 | -</html> |
2299 | |
2300 | === added file 'lib/lp/app/javascript/ui/tests/test_banner.js' |
2301 | --- lib/lp/app/javascript/ui/tests/test_banner.js 1970-01-01 00:00:00 +0000 |
2302 | +++ lib/lp/app/javascript/ui/tests/test_banner.js 2012-11-12 13:21:28 +0000 |
2303 | @@ -0,0 +1,287 @@ |
2304 | +/* Copyright (c) 2012 Canonical Ltd. All rights reserved. */ |
2305 | + |
2306 | +YUI.add('lp.ui.banner.test', function (Y) { |
2307 | + |
2308 | + var tests = Y.namespace('lp.ui.banner.test'); |
2309 | + tests.suite = new Y.Test.Suite('ui.banner Tests'); |
2310 | + |
2311 | + var ns = Y.lp.ui.banner; |
2312 | + |
2313 | + tests.suite.add(new Y.Test.Case({ |
2314 | + name: 'ui.banner_tests', |
2315 | + |
2316 | + setUp: function () { |
2317 | + this.container = Y.one('#fixture'); |
2318 | + }, |
2319 | + |
2320 | + tearDown: function () { |
2321 | + this.container.empty(); |
2322 | + }, |
2323 | + |
2324 | + test_library_exists: function () { |
2325 | + Y.Assert.isObject(Y.lp.ui.banner, |
2326 | + "Could not locate the lp.ui.banner module"); |
2327 | + }, |
2328 | + |
2329 | + test_render: function () { |
2330 | + var b = new ns.Banner(); |
2331 | + b.render(this.container); |
2332 | + |
2333 | + var banners = Y.all('.banner'); |
2334 | + Y.Assert.areEqual( |
2335 | + 1, |
2336 | + banners._nodes.length, |
2337 | + 'We have one banner node'); |
2338 | + |
2339 | + // The banner should make sure it's in the container as well. |
2340 | + var contained_banners = Y.all('#fixture .banner'); |
2341 | + Y.Assert.areEqual( |
2342 | + 1, |
2343 | + contained_banners._nodes.length, |
2344 | + 'Banner node is placed.'); |
2345 | + }, |
2346 | + |
2347 | + test_render_content: function () { |
2348 | + var msg = 'This is a banner message. Fear me.', |
2349 | + b = new ns.Banner({ |
2350 | + content: msg |
2351 | + }); |
2352 | + |
2353 | + b.render(this.container); |
2354 | + |
2355 | + var banner = Y.one('.banner'); |
2356 | + Y.Assert.areEqual( |
2357 | + msg, |
2358 | + banner.one('.banner-content').get('text') |
2359 | + ); |
2360 | + }, |
2361 | + |
2362 | + test_render_private_type: function () { |
2363 | + var msg = 'Private!', |
2364 | + b = new ns.Banner({ |
2365 | + content: msg, |
2366 | + banner_type: ns.PRIVATE |
2367 | + }); |
2368 | + |
2369 | + b.render(this.container); |
2370 | + |
2371 | + var banner = Y.one('.banner'); |
2372 | + Y.Assert.areEqual( |
2373 | + msg, |
2374 | + banner.one('.banner-content').get('text'), |
2375 | + 'The banner should have the private message.' |
2376 | + ); |
2377 | + |
2378 | + var badge = banner.one('.badge'); |
2379 | + |
2380 | + Y.Assert.isTrue( |
2381 | + badge.hasClass('private'), |
2382 | + 'The badge should have a private class on it.'); |
2383 | + |
2384 | + }, |
2385 | + |
2386 | + test_render_beta_type: function () { |
2387 | + var msg = 'BETA!', |
2388 | + b = new ns.Banner({ |
2389 | + content: msg, |
2390 | + banner_type: ns.BETA |
2391 | + }); |
2392 | + |
2393 | + b.render(this.container); |
2394 | + |
2395 | + var banner = Y.one('.banner'); |
2396 | + Y.Assert.areEqual( |
2397 | + msg, |
2398 | + banner.one('.banner-content').get('text'), |
2399 | + 'The banner should have the beta message.' |
2400 | + ); |
2401 | + |
2402 | + var badge = banner.one('.badge'); |
2403 | + |
2404 | + Y.Assert.isTrue( |
2405 | + badge.hasClass('beta'), |
2406 | + 'The badge should have a beta class on it.'); |
2407 | + }, |
2408 | + |
2409 | + test_render_badge_text: function () { |
2410 | + // We can set the badge to contain text. |
2411 | + var badge = 'BETA!', |
2412 | + b = new ns.Banner({ |
2413 | + badge_text: badge, |
2414 | + banner_type: ns.BETA |
2415 | + }); |
2416 | + |
2417 | + b.render(this.container); |
2418 | + var banner = Y.one('.banner'); |
2419 | + Y.Assert.areEqual( |
2420 | + badge, |
2421 | + banner.one('.badge').get('text'), |
2422 | + 'The badge should have the beta message.' |
2423 | + ); |
2424 | + }, |
2425 | + |
2426 | + test_banner_text_update: function () { |
2427 | + // The banner should update the rendered text when the content |
2428 | + // ATTR is changed. |
2429 | + var msg = 'This is a banner message. Fear me.', |
2430 | + b = new ns.Banner({ |
2431 | + content: msg |
2432 | + }); |
2433 | + |
2434 | + b.render(this.container); |
2435 | + |
2436 | + var banner = Y.one('.banner'); |
2437 | + Y.Assert.areEqual( |
2438 | + msg, |
2439 | + banner.one('.banner-content').get('text') |
2440 | + ); |
2441 | + |
2442 | + // Now change the content on the widget and check again. |
2443 | + var new_msg = 'Updated me!'; |
2444 | + b.set('content', new_msg); |
2445 | + banner = Y.one('.banner'); |
2446 | + Y.Assert.areEqual( |
2447 | + new_msg, |
2448 | + banner.one('.banner-content').get('text') |
2449 | + ); |
2450 | + } |
2451 | + })); |
2452 | + |
2453 | + |
2454 | + tests.suite.add(new Y.Test.Case({ |
2455 | + name: 'ui.beta_banner_tests', |
2456 | + |
2457 | + setUp: function () { |
2458 | + this.container = Y.one('#fixture'); |
2459 | + }, |
2460 | + |
2461 | + tearDown: function () { |
2462 | + this.container.empty(); |
2463 | + }, |
2464 | + |
2465 | + test_base_beta_banner: function () { |
2466 | + // The beta banner is auto set to the right type, has the right |
2467 | + // badge text. |
2468 | + var badge = 'BETA!', |
2469 | + msg = 'are in beta:', |
2470 | + b = new ns.BetaBanner({ |
2471 | + }); |
2472 | + |
2473 | + b.render(this.container); |
2474 | + var banner = Y.one('.banner'); |
2475 | + Y.Assert.areEqual( |
2476 | + badge, |
2477 | + banner.one('.badge').get('text'), |
2478 | + 'The badge should have the beta message.' |
2479 | + ); |
2480 | + |
2481 | + Y.Assert.areEqual( |
2482 | + ns.BETA, |
2483 | + b.get('banner_type'), |
2484 | + 'The banner should be the right type.' |
2485 | + ); |
2486 | + |
2487 | + Y.Assert.areNotEqual( |
2488 | + -1, |
2489 | + banner.one('.banner-content').get('text').indexOf(msg), |
2490 | + 'The badge should have beta content.' |
2491 | + ); |
2492 | + }, |
2493 | + |
2494 | + test_beta_features: function () { |
2495 | + // The features fed to the banner effect display of the messages. |
2496 | + var features = { |
2497 | + private_projects: { |
2498 | + is_beta: true, |
2499 | + title: "Private Projects", |
2500 | + url: "http://blog.ld.net/general/private-projects-beta", |
2501 | + value: "true" |
2502 | + }, |
2503 | + test_projects: { |
2504 | + is_beta: true, |
2505 | + title: "Test Projects", |
2506 | + url: "http://blog.ld.net/general/private-projects-beta", |
2507 | + value: "true" |
2508 | + }, |
2509 | + no_beta: { |
2510 | + is_beta: false, |
2511 | + title: "Better not see me", |
2512 | + url: "http://blog.ld.net/general/private-projects-beta", |
2513 | + value: "true" |
2514 | + } |
2515 | + }; |
2516 | + |
2517 | + var b = new ns.BetaBanner({ |
2518 | + features: features |
2519 | + }); |
2520 | + |
2521 | + b.render(this.container); |
2522 | + |
2523 | + var banner = Y.one('.banner'), |
2524 | + banner_content = banner.one('.banner-content').get('text'); |
2525 | + |
2526 | + Y.Assert.areNotEqual( |
2527 | + -1, |
2528 | + banner_content.indexOf(features.private_projects.title), |
2529 | + 'The private projects feature should be displayed.' |
2530 | + ); |
2531 | + |
2532 | + Y.Assert.areNotEqual( |
2533 | + -1, |
2534 | + banner_content.indexOf(features.test_projects.title), |
2535 | + 'Also test projects since we support multiple features.' |
2536 | + ); |
2537 | + |
2538 | + Y.Assert.areEqual( |
2539 | + -1, |
2540 | + banner_content.indexOf(features.no_beta.title), |
2541 | + 'But not no beta since we only support beta features.' |
2542 | + ); |
2543 | + } |
2544 | + })); |
2545 | + |
2546 | + |
2547 | + tests.suite.add(new Y.Test.Case({ |
2548 | + name: 'ui.private_banner_tests', |
2549 | + |
2550 | + setUp: function () { |
2551 | + this.container = Y.one('#fixture'); |
2552 | + }, |
2553 | + |
2554 | + tearDown: function () { |
2555 | + this.container.empty(); |
2556 | + }, |
2557 | + |
2558 | + test_base_private_banner: function () { |
2559 | + // The private banner is auto set to the right type, has the right |
2560 | + // badge text. |
2561 | + var badge = '', |
2562 | + msg = 'page is private', |
2563 | + b = new ns.PrivateBanner({ |
2564 | + }); |
2565 | + |
2566 | + b.render(this.container); |
2567 | + var banner = Y.one('.banner'); |
2568 | + Y.Assert.areEqual( |
2569 | + badge, |
2570 | + banner.one('.badge').get('text'), |
2571 | + 'The badge should be empty' |
2572 | + ); |
2573 | + |
2574 | + Y.Assert.areEqual( |
2575 | + ns.PRIVATE, |
2576 | + b.get('banner_type'), |
2577 | + 'The banner should be the right type.' |
2578 | + ); |
2579 | + |
2580 | + Y.Assert.areNotEqual( |
2581 | + -1, |
2582 | + banner.one('.banner-content').get('text').indexOf(msg), |
2583 | + 'The badge should have a private warning.' |
2584 | + ); |
2585 | + } |
2586 | + })); |
2587 | + |
2588 | +}, '0.1', { |
2589 | + requires: ['test', 'lp.testing.helpers', 'lp.ui.banner'] |
2590 | +}); |
2591 | |
2592 | === removed file 'lib/lp/app/javascript/ui/tests/test_banner.js' |
2593 | --- lib/lp/app/javascript/ui/tests/test_banner.js 2012-11-09 18:55:02 +0000 |
2594 | +++ lib/lp/app/javascript/ui/tests/test_banner.js 1970-01-01 00:00:00 +0000 |
2595 | @@ -1,287 +0,0 @@ |
2596 | -/* Copyright (c) 2012 Canonical Ltd. All rights reserved. */ |
2597 | - |
2598 | -YUI.add('lp.ui.banner.test', function (Y) { |
2599 | - |
2600 | - var tests = Y.namespace('lp.ui.banner.test'); |
2601 | - tests.suite = new Y.Test.Suite('ui.banner Tests'); |
2602 | - |
2603 | - var ns = Y.lp.ui.banner; |
2604 | - |
2605 | - tests.suite.add(new Y.Test.Case({ |
2606 | - name: 'ui.banner_tests', |
2607 | - |
2608 | - setUp: function () { |
2609 | - this.container = Y.one('#fixture'); |
2610 | - }, |
2611 | - |
2612 | - tearDown: function () { |
2613 | - this.container.empty(); |
2614 | - }, |
2615 | - |
2616 | - test_library_exists: function () { |
2617 | - Y.Assert.isObject(Y.lp.ui.banner, |
2618 | - "Could not locate the lp.ui.banner module"); |
2619 | - }, |
2620 | - |
2621 | - test_render: function () { |
2622 | - var b = new ns.Banner(); |
2623 | - b.render(this.container); |
2624 | - |
2625 | - var banners = Y.all('.banner'); |
2626 | - Y.Assert.areEqual( |
2627 | - 1, |
2628 | - banners._nodes.length, |
2629 | - 'We have one banner node'); |
2630 | - |
2631 | - // The banner should make sure it's in the container as well. |
2632 | - var contained_banners = Y.all('#fixture .banner'); |
2633 | - Y.Assert.areEqual( |
2634 | - 1, |
2635 | - contained_banners._nodes.length, |
2636 | - 'Banner node is placed.'); |
2637 | - }, |
2638 | - |
2639 | - test_render_content: function () { |
2640 | - var msg = 'This is a banner message. Fear me.', |
2641 | - b = new ns.Banner({ |
2642 | - content: msg |
2643 | - }); |
2644 | - |
2645 | - b.render(this.container); |
2646 | - |
2647 | - var banner = Y.one('.banner'); |
2648 | - Y.Assert.areEqual( |
2649 | - msg, |
2650 | - banner.one('.banner-content').get('text') |
2651 | - ); |
2652 | - }, |
2653 | - |
2654 | - test_render_private_type: function () { |
2655 | - var msg = 'Private!', |
2656 | - b = new ns.Banner({ |
2657 | - content: msg, |
2658 | - banner_type: ns.PRIVATE |
2659 | - }); |
2660 | - |
2661 | - b.render(this.container); |
2662 | - |
2663 | - var banner = Y.one('.banner'); |
2664 | - Y.Assert.areEqual( |
2665 | - msg, |
2666 | - banner.one('.banner-content').get('text'), |
2667 | - 'The banner should have the private message.' |
2668 | - ); |
2669 | - |
2670 | - var badge = banner.one('.badge'); |
2671 | - |
2672 | - Y.Assert.isTrue( |
2673 | - badge.hasClass('private'), |
2674 | - 'The badge should have a private class on it.'); |
2675 | - |
2676 | - }, |
2677 | - |
2678 | - test_render_beta_type: function () { |
2679 | - var msg = 'BETA!', |
2680 | - b = new ns.Banner({ |
2681 | - content: msg, |
2682 | - banner_type: ns.BETA |
2683 | - }); |
2684 | - |
2685 | - b.render(this.container); |
2686 | - |
2687 | - var banner = Y.one('.banner'); |
2688 | - Y.Assert.areEqual( |
2689 | - msg, |
2690 | - banner.one('.banner-content').get('text'), |
2691 | - 'The banner should have the beta message.' |
2692 | - ); |
2693 | - |
2694 | - var badge = banner.one('.badge'); |
2695 | - |
2696 | - Y.Assert.isTrue( |
2697 | - badge.hasClass('beta'), |
2698 | - 'The badge should have a beta class on it.'); |
2699 | - }, |
2700 | - |
2701 | - test_render_badge_text: function () { |
2702 | - // We can set the badge to contain text. |
2703 | - var badge = 'BETA!', |
2704 | - b = new ns.Banner({ |
2705 | - badge_text: badge, |
2706 | - banner_type: ns.BETA |
2707 | - }); |
2708 | - |
2709 | - b.render(this.container); |
2710 | - var banner = Y.one('.banner'); |
2711 | - Y.Assert.areEqual( |
2712 | - badge, |
2713 | - banner.one('.badge').get('text'), |
2714 | - 'The badge should have the beta message.' |
2715 | - ); |
2716 | - }, |
2717 | - |
2718 | - test_banner_text_update: function () { |
2719 | - // The banner should update the rendered text when the content |
2720 | - // ATTR is changed. |
2721 | - var msg = 'This is a banner message. Fear me.', |
2722 | - b = new ns.Banner({ |
2723 | - content: msg |
2724 | - }); |
2725 | - |
2726 | - b.render(this.container); |
2727 | - |
2728 | - var banner = Y.one('.banner'); |
2729 | - Y.Assert.areEqual( |
2730 | - msg, |
2731 | - banner.one('.banner-content').get('text') |
2732 | - ); |
2733 | - |
2734 | - // Now change the content on the widget and check again. |
2735 | - var new_msg = 'Updated me!'; |
2736 | - b.set('content', new_msg); |
2737 | - banner = Y.one('.banner'); |
2738 | - Y.Assert.areEqual( |
2739 | - new_msg, |
2740 | - banner.one('.banner-content').get('text') |
2741 | - ); |
2742 | - } |
2743 | - })); |
2744 | - |
2745 | - |
2746 | - tests.suite.add(new Y.Test.Case({ |
2747 | - name: 'ui.beta_banner_tests', |
2748 | - |
2749 | - setUp: function () { |
2750 | - this.container = Y.one('#fixture'); |
2751 | - }, |
2752 | - |
2753 | - tearDown: function () { |
2754 | - this.container.empty(); |
2755 | - }, |
2756 | - |
2757 | - test_base_beta_banner: function () { |
2758 | - // The beta banner is auto set to the right type, has the right |
2759 | - // badge text. |
2760 | - var badge = 'BETA!', |
2761 | - msg = 'are in beta:', |
2762 | - b = new ns.BetaBanner({ |
2763 | - }); |
2764 | - |
2765 | - b.render(this.container); |
2766 | - var banner = Y.one('.banner'); |
2767 | - Y.Assert.areEqual( |
2768 | - badge, |
2769 | - banner.one('.badge').get('text'), |
2770 | - 'The badge should have the beta message.' |
2771 | - ); |
2772 | - |
2773 | - Y.Assert.areEqual( |
2774 | - ns.BETA, |
2775 | - b.get('banner_type'), |
2776 | - 'The banner should be the right type.' |
2777 | - ); |
2778 | - |
2779 | - Y.Assert.areNotEqual( |
2780 | - -1, |
2781 | - banner.one('.banner-content').get('text').indexOf(msg), |
2782 | - 'The badge should have beta content.' |
2783 | - ); |
2784 | - }, |
2785 | - |
2786 | - test_beta_features: function () { |
2787 | - // The features fed to the banner effect display of the messages. |
2788 | - var features = { |
2789 | - private_projects: { |
2790 | - is_beta: true, |
2791 | - title: "Private Projects", |
2792 | - url: "http://blog.ld.net/general/private-projects-beta", |
2793 | - value: "true" |
2794 | - }, |
2795 | - test_projects: { |
2796 | - is_beta: true, |
2797 | - title: "Test Projects", |
2798 | - url: "http://blog.ld.net/general/private-projects-beta", |
2799 | - value: "true" |
2800 | - }, |
2801 | - no_beta: { |
2802 | - is_beta: false, |
2803 | - title: "Better not see me", |
2804 | - url: "http://blog.ld.net/general/private-projects-beta", |
2805 | - value: "true" |
2806 | - } |
2807 | - }; |
2808 | - |
2809 | - var b = new ns.BetaBanner({ |
2810 | - features: features |
2811 | - }); |
2812 | - |
2813 | - b.render(this.container); |
2814 | - |
2815 | - var banner = Y.one('.banner'), |
2816 | - banner_content = banner.one('.banner-content').get('text'); |
2817 | - |
2818 | - Y.Assert.areNotEqual( |
2819 | - -1, |
2820 | - banner_content.indexOf(features.private_projects.title), |
2821 | - 'The private projects feature should be displayed.' |
2822 | - ); |
2823 | - |
2824 | - Y.Assert.areNotEqual( |
2825 | - -1, |
2826 | - banner_content.indexOf(features.test_projects.title), |
2827 | - 'Also test projects since we support multiple features.' |
2828 | - ); |
2829 | - |
2830 | - Y.Assert.areEqual( |
2831 | - -1, |
2832 | - banner_content.indexOf(features.no_beta.title), |
2833 | - 'But not no beta since we only support beta features.' |
2834 | - ); |
2835 | - } |
2836 | - })); |
2837 | - |
2838 | - |
2839 | - tests.suite.add(new Y.Test.Case({ |
2840 | - name: 'ui.private_banner_tests', |
2841 | - |
2842 | - setUp: function () { |
2843 | - this.container = Y.one('#fixture'); |
2844 | - }, |
2845 | - |
2846 | - tearDown: function () { |
2847 | - this.container.empty(); |
2848 | - }, |
2849 | - |
2850 | - test_base_private_banner: function () { |
2851 | - // The private banner is auto set to the right type, has the right |
2852 | - // badge text. |
2853 | - var badge = '', |
2854 | - msg = 'page is private', |
2855 | - b = new ns.PrivateBanner({ |
2856 | - }); |
2857 | - |
2858 | - b.render(this.container); |
2859 | - var banner = Y.one('.banner'); |
2860 | - Y.Assert.areEqual( |
2861 | - badge, |
2862 | - banner.one('.badge').get('text'), |
2863 | - 'The badge should be empty' |
2864 | - ); |
2865 | - |
2866 | - Y.Assert.areEqual( |
2867 | - ns.PRIVATE, |
2868 | - b.get('banner_type'), |
2869 | - 'The banner should be the right type.' |
2870 | - ); |
2871 | - |
2872 | - Y.Assert.areNotEqual( |
2873 | - -1, |
2874 | - banner.one('.banner-content').get('text').indexOf(msg), |
2875 | - 'The badge should have a private warning.' |
2876 | - ); |
2877 | - } |
2878 | - })); |
2879 | - |
2880 | -}, '0.1', { |
2881 | - requires: ['test', 'lp.testing.helpers', 'lp.ui.banner'] |
2882 | -}); |
2883 | |
2884 | === added directory 'lib/lp/app/javascript/views' |
2885 | === removed directory 'lib/lp/app/javascript/views' |
2886 | === added file 'lib/lp/app/javascript/views/global.js' |
2887 | --- lib/lp/app/javascript/views/global.js 1970-01-01 00:00:00 +0000 |
2888 | +++ lib/lp/app/javascript/views/global.js 2012-11-12 13:21:28 +0000 |
2889 | @@ -0,0 +1,142 @@ |
2890 | +/* |
2891 | + * Copyright 2012 Canonical Ltd. This software is licensed under the |
2892 | + * GNU Affero General Public License version 3 (see the file LICENSE). |
2893 | + * |
2894 | + * Global View handler for Launchpad |
2895 | + * |
2896 | + * @module lp.views.Global |
2897 | + * @namespace lp.views |
2898 | + * @module global |
2899 | + */ |
2900 | +YUI.add('lp.views.global', function (Y) { |
2901 | + |
2902 | + var ns = Y.namespace('lp.views'), |
2903 | + ui = Y.namespace('lp.ui'), |
2904 | + info_type = Y.namespace('lp.app.information_type'); |
2905 | + |
2906 | + /** |
2907 | + * Provides a Y.View that controls all of the things that need handling on |
2908 | + * every single request. All code currently in the base-layout-macros |
2909 | + * should eventually moved into here to be loaded via the render() method. |
2910 | + * Events bound as required, etc. |
2911 | + * |
2912 | + * @class Global |
2913 | + * @extends Y.View |
2914 | + */ |
2915 | + ns.Global = Y.Base.create('lp-views-global', Y.View, [], { |
2916 | + _events: [], |
2917 | + |
2918 | + /** |
2919 | + * Watch for page level events in all pages. |
2920 | + * |
2921 | + * @method _bind_events |
2922 | + */ |
2923 | + _bind_events: function () { |
2924 | + var that = this; |
2925 | + |
2926 | + // Watch for any changes in information type. |
2927 | + this._events.push(Y.on(info_type.EV_ISPUBLIC, function (ev) { |
2928 | + // Remove the banner if there is one. |
2929 | + if (that._private_banner) { |
2930 | + that._private_banner.hide(); |
2931 | + that._private_banner.destroy(true); |
2932 | + that._private_banner = null; |
2933 | + // XXX: Bug #1076074 |
2934 | + var body = Y.one('body'); |
2935 | + body.addClass('public'); |
2936 | + } |
2937 | + })); |
2938 | + |
2939 | + // If the information type is changed to private, and we don't |
2940 | + // currently have a privacy banner, then create a new one and set |
2941 | + // it up. |
2942 | + this._events.push(Y.on(info_type.EV_ISPRIVATE, function (ev) { |
2943 | + // Create a Private banner if there is not currently one. |
2944 | + if (!that._private_banner) { |
2945 | + that._private_banner = new ui.banner.PrivateBanner({ |
2946 | + content: ev.text |
2947 | + }); |
2948 | + |
2949 | + // There is no current container for the banner since |
2950 | + // we're creating it on the fly. |
2951 | + var container = Y.Node.create('<div>'); |
2952 | + |
2953 | + // XXX: Bug #1076074 |
2954 | + var body = Y.one('body'); |
2955 | + body.removeClass('public'); |
2956 | + that._private_banner.render(container); |
2957 | + // Only append the content to the DOM after the rest is |
2958 | + // one to avoid any repaints on the browser end. |
2959 | + body.prepend(container); |
2960 | + that._private_banner.show(); |
2961 | + } else { |
2962 | + // The banner is there but we need to update text. |
2963 | + that._private_banner.set('content', ev.text); |
2964 | + } |
2965 | + })); |
2966 | + }, |
2967 | + |
2968 | + /** |
2969 | + * Clean up the view and its event bindings when destroyed. |
2970 | + * |
2971 | + * @method _destroy |
2972 | + * @param {Event} ev |
2973 | + * @private |
2974 | + */ |
2975 | + _destroy: function (ev) { |
2976 | + var index; |
2977 | + for (index in this._events) { |
2978 | + event = this._events[index]; |
2979 | + event.detach(); |
2980 | + } |
2981 | + }, |
2982 | + |
2983 | + _init_banners: function () { |
2984 | + var that = this; |
2985 | + |
2986 | + // On page load the banner container already exists. This is so |
2987 | + // that the height of the page is already determined. |
2988 | + var is_beta = Y.one('.beta_banner_container'); |
2989 | + if (is_beta) { |
2990 | + that._beta_banner = new ui.banner.BetaBanner({ |
2991 | + features: LP.cache.related_features |
2992 | + }); |
2993 | + that._beta_banner.render(is_beta); |
2994 | + // We delay the show until the page is ready so we get our |
2995 | + // pretty css3 animation that distracts the user a bit. |
2996 | + Y.after('load', function (ev) { |
2997 | + that._beta_banner.show(); |
2998 | + }); |
2999 | + } |
3000 | + |
3001 | + // On page load the banner container already exists. This is so |
3002 | + // that the height of the page is already determined. |
3003 | + var is_private = Y.one('.private_banner_container'); |
3004 | + if (is_private) { |
3005 | + that._private_banner = new ui.banner.PrivateBanner(); |
3006 | + that._private_banner.render(is_private); |
3007 | + // We delay the show until the page is ready so we get our |
3008 | + // pretty css3 animation that distracts the user a bit. |
3009 | + Y.on('load', function (ev) { |
3010 | + that._private_banner.show(); |
3011 | + }); |
3012 | + } |
3013 | + }, |
3014 | + |
3015 | + initialize: function (cfg) {}, |
3016 | + |
3017 | + render: function () { |
3018 | + this._bind_events(); |
3019 | + this.on('destroy', this._destroy, this); |
3020 | + this._init_banners(); |
3021 | + } |
3022 | + |
3023 | + }, { |
3024 | + ATTRS: { |
3025 | + |
3026 | + } |
3027 | + }); |
3028 | + |
3029 | +}, '0.1', { |
3030 | + requires: ['base', 'view', 'lp.ui.banner', 'lp.app.information_type'] |
3031 | +}); |
3032 | |
3033 | === removed file 'lib/lp/app/javascript/views/global.js' |
3034 | --- lib/lp/app/javascript/views/global.js 2012-11-09 18:46:31 +0000 |
3035 | +++ lib/lp/app/javascript/views/global.js 1970-01-01 00:00:00 +0000 |
3036 | @@ -1,142 +0,0 @@ |
3037 | -/* |
3038 | - * Copyright 2012 Canonical Ltd. This software is licensed under the |
3039 | - * GNU Affero General Public License version 3 (see the file LICENSE). |
3040 | - * |
3041 | - * Global View handler for Launchpad |
3042 | - * |
3043 | - * @module lp.views.Global |
3044 | - * @namespace lp.views |
3045 | - * @module global |
3046 | - */ |
3047 | -YUI.add('lp.views.global', function (Y) { |
3048 | - |
3049 | - var ns = Y.namespace('lp.views'), |
3050 | - ui = Y.namespace('lp.ui'), |
3051 | - info_type = Y.namespace('lp.app.information_type'); |
3052 | - |
3053 | - /** |
3054 | - * Provides a Y.View that controls all of the things that need handling on |
3055 | - * every single request. All code currently in the base-layout-macros |
3056 | - * should eventually moved into here to be loaded via the render() method. |
3057 | - * Events bound as required, etc. |
3058 | - * |
3059 | - * @class Global |
3060 | - * @extends Y.View |
3061 | - */ |
3062 | - ns.Global = Y.Base.create('lp-views-global', Y.View, [], { |
3063 | - _events: [], |
3064 | - |
3065 | - /** |
3066 | - * Watch for page level events in all pages. |
3067 | - * |
3068 | - * @method _bind_events |
3069 | - */ |
3070 | - _bind_events: function () { |
3071 | - var that = this; |
3072 | - |
3073 | - // Watch for any changes in information type. |
3074 | - this._events.push(Y.on(info_type.EV_ISPUBLIC, function (ev) { |
3075 | - // Remove the banner if there is one. |
3076 | - if (that._private_banner) { |
3077 | - that._private_banner.hide(); |
3078 | - that._private_banner.destroy(true); |
3079 | - that._private_banner = null; |
3080 | - // XXX: Bug #1076074 |
3081 | - var body = Y.one('body'); |
3082 | - body.addClass('public'); |
3083 | - } |
3084 | - })); |
3085 | - |
3086 | - // If the information type is changed to private, and we don't |
3087 | - // currently have a privacy banner, then create a new one and set |
3088 | - // it up. |
3089 | - this._events.push(Y.on(info_type.EV_ISPRIVATE, function (ev) { |
3090 | - // Create a Private banner if there is not currently one. |
3091 | - if (!that._private_banner) { |
3092 | - that._private_banner = new ui.banner.PrivateBanner({ |
3093 | - content: ev.text |
3094 | - }); |
3095 | - |
3096 | - // There is no current container for the banner since |
3097 | - // we're creating it on the fly. |
3098 | - var container = Y.Node.create('<div>'); |
3099 | - |
3100 | - // XXX: Bug #1076074 |
3101 | - var body = Y.one('body'); |
3102 | - body.removeClass('public'); |
3103 | - that._private_banner.render(container); |
3104 | - // Only append the content to the DOM after the rest is |
3105 | - // one to avoid any repaints on the browser end. |
3106 | - body.prepend(container); |
3107 | - that._private_banner.show(); |
3108 | - } else { |
3109 | - // The banner is there but we need to update text. |
3110 | - that._private_banner.set('content', ev.text); |
3111 | - } |
3112 | - })); |
3113 | - }, |
3114 | - |
3115 | - /** |
3116 | - * Clean up the view and its event bindings when destroyed. |
3117 | - * |
3118 | - * @method _destroy |
3119 | - * @param {Event} ev |
3120 | - * @private |
3121 | - */ |
3122 | - _destroy: function (ev) { |
3123 | - var index; |
3124 | - for (index in this._events) { |
3125 | - event = this._events[index]; |
3126 | - event.detach(); |
3127 | - } |
3128 | - }, |
3129 | - |
3130 | - _init_banners: function () { |
3131 | - var that = this; |
3132 | - |
3133 | - // On page load the banner container already exists. This is so |
3134 | - // that the height of the page is already determined. |
3135 | - var is_beta = Y.one('.beta_banner_container'); |
3136 | - if (is_beta) { |
3137 | - that._beta_banner = new ui.banner.BetaBanner({ |
3138 | - features: LP.cache.related_features |
3139 | - }); |
3140 | - that._beta_banner.render(is_beta); |
3141 | - // We delay the show until the page is ready so we get our |
3142 | - // pretty css3 animation that distracts the user a bit. |
3143 | - Y.after('load', function (ev) { |
3144 | - that._beta_banner.show(); |
3145 | - }); |
3146 | - } |
3147 | - |
3148 | - // On page load the banner container already exists. This is so |
3149 | - // that the height of the page is already determined. |
3150 | - var is_private = Y.one('.private_banner_container'); |
3151 | - if (is_private) { |
3152 | - that._private_banner = new ui.banner.PrivateBanner(); |
3153 | - that._private_banner.render(is_private); |
3154 | - // We delay the show until the page is ready so we get our |
3155 | - // pretty css3 animation that distracts the user a bit. |
3156 | - Y.on('load', function (ev) { |
3157 | - that._private_banner.show(); |
3158 | - }); |
3159 | - } |
3160 | - }, |
3161 | - |
3162 | - initialize: function (cfg) {}, |
3163 | - |
3164 | - render: function () { |
3165 | - this._bind_events(); |
3166 | - this.on('destroy', this._destroy, this); |
3167 | - this._init_banners(); |
3168 | - } |
3169 | - |
3170 | - }, { |
3171 | - ATTRS: { |
3172 | - |
3173 | - } |
3174 | - }); |
3175 | - |
3176 | -}, '0.1', { |
3177 | - requires: ['base', 'view', 'lp.ui.banner', 'lp.app.information_type'] |
3178 | -}); |
3179 | |
3180 | === added directory 'lib/lp/app/javascript/views/tests' |
3181 | === removed directory 'lib/lp/app/javascript/views/tests' |
3182 | === added file 'lib/lp/app/javascript/views/tests/test_global.html' |
3183 | --- lib/lp/app/javascript/views/tests/test_global.html 1970-01-01 00:00:00 +0000 |
3184 | +++ lib/lp/app/javascript/views/tests/test_global.html 2012-11-12 13:21:28 +0000 |
3185 | @@ -0,0 +1,62 @@ |
3186 | +<!DOCTYPE html> |
3187 | + |
3188 | +<!-- |
3189 | +Copyright 2012 Canonical Ltd. This software is licensed under the |
3190 | +GNU Affero General Public License version 3 (see the file LICENSE). |
3191 | +--> |
3192 | + |
3193 | +<html> |
3194 | + <head> |
3195 | + <title>Product New Tests</title> |
3196 | + |
3197 | + <!-- YUI and test setup --> |
3198 | + <script type="text/javascript" |
3199 | + src="../../../../../../build/js/yui/yui/yui.js"> |
3200 | + </script> |
3201 | + <link rel="stylesheet" |
3202 | + href="../../../../../../build/js/yui/console/assets/console-core.css" /> |
3203 | + <link rel="stylesheet" |
3204 | + href="../../../../../../build/js/yui/test-console/assets/skins/sam/test-console.css" /> |
3205 | + <link rel="stylesheet" |
3206 | + href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" /> |
3207 | + |
3208 | + <script type="text/javascript" |
3209 | + src="../../../../../../build/js/lp/app/testing/testrunner.js"></script> |
3210 | + |
3211 | + <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" /> |
3212 | + |
3213 | + <!-- Dependencies --> |
3214 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/client.js"></script> |
3215 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/choice.js"></script> |
3216 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/ellipsis.js"></script> |
3217 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/expander.js"></script> |
3218 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/errors.js"></script> |
3219 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/information_type.js"></script> |
3220 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/lp.js"></script> |
3221 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/mustache.js"></script> |
3222 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/anim/anim.js"></script> |
3223 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/extras/extras.js"></script> |
3224 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/choiceedit/choiceedit.js"></script> |
3225 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/effects/effects.js"></script> |
3226 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/formoverlay/formoverlay.js"></script> |
3227 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/formwidgets/resizing_textarea.js"></script> |
3228 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/inlineedit/editor.js"></script> |
3229 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/testing/helpers.js"></script> |
3230 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/overlay/overlay.js"></script> |
3231 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/ui/ui.js"></script> |
3232 | + <script type="text/javascript" src="../../../../../../build/js/lp/app/ui/banner.js"></script> |
3233 | + |
3234 | + <!-- The module under test. --> |
3235 | + <script type="text/javascript" src="../global.js"></script> |
3236 | + |
3237 | + <!-- The test suite --> |
3238 | + <script type="text/javascript" src="test_global.js"></script> |
3239 | + |
3240 | + </head> |
3241 | + <body class="yui3-skin-sam"> |
3242 | + <ul id="suites"> |
3243 | + <li>lp.views.global.test</li> |
3244 | + </ul> |
3245 | + <div id="fixture"></div> |
3246 | + </body> |
3247 | +</html> |
3248 | |
3249 | === removed file 'lib/lp/app/javascript/views/tests/test_global.html' |
3250 | --- lib/lp/app/javascript/views/tests/test_global.html 2012-11-09 18:46:31 +0000 |
3251 | +++ lib/lp/app/javascript/views/tests/test_global.html 1970-01-01 00:00:00 +0000 |
3252 | @@ -1,62 +0,0 @@ |
3253 | -<!DOCTYPE html> |
3254 | - |
3255 | -<!-- |
3256 | -Copyright 2012 Canonical Ltd. This software is licensed under the |
3257 | -GNU Affero General Public License version 3 (see the file LICENSE). |
3258 | ---> |
3259 | - |
3260 | -<html> |
3261 | - <head> |
3262 | - <title>Product New Tests</title> |
3263 | - |
3264 | - <!-- YUI and test setup --> |
3265 | - <script type="text/javascript" |
3266 | - src="../../../../../../build/js/yui/yui/yui.js"> |
3267 | - </script> |
3268 | - <link rel="stylesheet" |
3269 | - href="../../../../../../build/js/yui/console/assets/console-core.css" /> |
3270 | - <link rel="stylesheet" |
3271 | - href="../../../../../../build/js/yui/test-console/assets/skins/sam/test-console.css" /> |
3272 | - <link rel="stylesheet" |
3273 | - href="../../../../../../build/js/yui/test/assets/skins/sam/test.css" /> |
3274 | - |
3275 | - <script type="text/javascript" |
3276 | - src="../../../../../../build/js/lp/app/testing/testrunner.js"></script> |
3277 | - |
3278 | - <link rel="stylesheet" href="../../../../app/javascript/testing/test.css" /> |
3279 | - |
3280 | - <!-- Dependencies --> |
3281 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/client.js"></script> |
3282 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/choice.js"></script> |
3283 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/ellipsis.js"></script> |
3284 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/expander.js"></script> |
3285 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/errors.js"></script> |
3286 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/information_type.js"></script> |
3287 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/lp.js"></script> |
3288 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/mustache.js"></script> |
3289 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/anim/anim.js"></script> |
3290 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/extras/extras.js"></script> |
3291 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/choiceedit/choiceedit.js"></script> |
3292 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/effects/effects.js"></script> |
3293 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/formoverlay/formoverlay.js"></script> |
3294 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/formwidgets/resizing_textarea.js"></script> |
3295 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/inlineedit/editor.js"></script> |
3296 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/testing/helpers.js"></script> |
3297 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/overlay/overlay.js"></script> |
3298 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/ui/ui.js"></script> |
3299 | - <script type="text/javascript" src="../../../../../../build/js/lp/app/ui/banner.js"></script> |
3300 | - |
3301 | - <!-- The module under test. --> |
3302 | - <script type="text/javascript" src="../global.js"></script> |
3303 | - |
3304 | - <!-- The test suite --> |
3305 | - <script type="text/javascript" src="test_global.js"></script> |
3306 | - |
3307 | - </head> |
3308 | - <body class="yui3-skin-sam"> |
3309 | - <ul id="suites"> |
3310 | - <li>lp.views.global.test</li> |
3311 | - </ul> |
3312 | - <div id="fixture"></div> |
3313 | - </body> |
3314 | -</html> |
3315 | |
3316 | === added file 'lib/lp/app/javascript/views/tests/test_global.js' |
3317 | --- lib/lp/app/javascript/views/tests/test_global.js 1970-01-01 00:00:00 +0000 |
3318 | +++ lib/lp/app/javascript/views/tests/test_global.js 2012-11-12 13:21:28 +0000 |
3319 | @@ -0,0 +1,164 @@ |
3320 | +/* Copyright (c) 2012 Canonical Ltd. All rights reserved. */ |
3321 | + |
3322 | +YUI.add('lp.views.global.test', function (Y) { |
3323 | + var tests = Y.namespace('lp.views.global.test'); |
3324 | + var info_type = Y.namespace('lp.app.information_type'); |
3325 | + var ns = Y.lp.views; |
3326 | + |
3327 | + tests.suite = new Y.Test.Suite('lp.views.global test'); |
3328 | + tests.suite.add(new Y.Test.Case({ |
3329 | + name: 'lp.views.global', |
3330 | + |
3331 | + setUp: function () { |
3332 | + this.container = Y.one('#fixture'); |
3333 | + window.LP = { |
3334 | + cache: { |
3335 | + related_features: { |
3336 | + private_projects: { |
3337 | + is_beta: true, |
3338 | + title: "Private Projects", |
3339 | + url: "http://blog.ld.net/private-projects-beta", |
3340 | + value: "true" |
3341 | + } |
3342 | + }, |
3343 | + information_type_data: { |
3344 | + PUBLIC: { |
3345 | + value: 'PUBLIC', name: 'Public', |
3346 | + is_private: false, order: 1, |
3347 | + description: 'Public Description' |
3348 | + }, |
3349 | + EMBARGOED: { |
3350 | + value: 'EMBARGOED', name: 'Embargoed', |
3351 | + is_private: true, order: 2, |
3352 | + description: 'Something embargoed' |
3353 | + }, |
3354 | + PROPRIETARY: { |
3355 | + value: 'PROPRIETARY', name: 'Proprietary', |
3356 | + is_private: true, order: 3, |
3357 | + description: 'Private Description' |
3358 | + } |
3359 | + } |
3360 | + } |
3361 | + }; |
3362 | + }, |
3363 | + |
3364 | + tearDown: function () { |
3365 | + this.container.empty(); |
3366 | + }, |
3367 | + |
3368 | + test_library_exists: function () { |
3369 | + Y.Assert.isObject(ns.Global, |
3370 | + "Could not locate the lp.views.global module"); |
3371 | + }, |
3372 | + |
3373 | + test_basic_render: function () { |
3374 | + // Nothing is currently rendered out by default. |
3375 | + var view = new ns.Global(); |
3376 | + view.render(); |
3377 | + |
3378 | + Y.Assert.areEqual( |
3379 | + '', |
3380 | + this.container.get('innerHTML'), |
3381 | + 'The container is still empty.'); |
3382 | + view.destroy(); |
3383 | + }, |
3384 | + |
3385 | + test_beta_banner: function () { |
3386 | + // If we've prepped on load a beta banner will auto appear. |
3387 | + var banner_container = Y.Node.create('<div/>'); |
3388 | + banner_container.addClass('beta_banner_container'); |
3389 | + this.container.append(banner_container); |
3390 | + var view = new ns.Global(); |
3391 | + view.render(); |
3392 | + |
3393 | + // We have to wait until after page load event fires to test |
3394 | + // things out. |
3395 | + var banner_node = Y.one('.banner'); |
3396 | + Y.Assert.isObject( |
3397 | + banner_node, |
3398 | + 'The container has a new banner node in there.'); |
3399 | + |
3400 | + view.destroy(); |
3401 | + }, |
3402 | + |
3403 | + test_privacy: function () { |
3404 | + var beta_container = Y.Node.create('<div/>'); |
3405 | + var private_container = Y.Node.create('<div/>'); |
3406 | + |
3407 | + beta_container.addClass('beta_banner_container'); |
3408 | + private_container.addClass('private_banner_container'); |
3409 | + |
3410 | + this.container.append(beta_container); |
3411 | + this.container.append(private_container); |
3412 | + var view = new ns.Global(); |
3413 | + view.render(); |
3414 | + |
3415 | + // We have to wait until after page load event fires to test |
3416 | + // things out. |
3417 | + var banner_nodes = Y.all('.banner'); |
3418 | + Y.Assert.areEqual( |
3419 | + 2, |
3420 | + banner_nodes._nodes.length, |
3421 | + 'We should have two banners rendered.'); |
3422 | + |
3423 | + view.destroy(); |
3424 | + }, |
3425 | + |
3426 | + test_privacy_banner_from_event: function () { |
3427 | + // We can also get a privacy banner via a fired event. |
3428 | + // This is hard coded to the <body> tag so we have to do some |
3429 | + // manual clean up here. |
3430 | + var view = new ns.Global(); |
3431 | + view.render(); |
3432 | + |
3433 | + var msg = 'Testing Global'; |
3434 | + Y.fire(info_type.EV_ISPRIVATE, { |
3435 | + text: msg |
3436 | + }); |
3437 | + |
3438 | + var banner = Y.one('.banner'); |
3439 | + var banner_text = banner.one('.banner-content').get('text'); |
3440 | + Y.Assert.areNotEqual( |
3441 | + -1, |
3442 | + banner_text.indexOf(msg), |
3443 | + 'The event text is turned into the banner content'); |
3444 | + |
3445 | + // Manually clean up. |
3446 | + Y.one('.yui3-banner').remove(true); |
3447 | + view.destroy(); |
3448 | + }, |
3449 | + |
3450 | + test_banner_updates_content: function () { |
3451 | + // If we change our privacy information type the banner needs to |
3452 | + // update the content to the new text value from the event. |
3453 | + var view = new ns.Global(); |
3454 | + view.render(); |
3455 | + |
3456 | + var msg = 'Testing Global'; |
3457 | + Y.fire(info_type.EV_ISPRIVATE, { |
3458 | + text: msg |
3459 | + }); |
3460 | + |
3461 | + var updated_msg = 'Updated content'; |
3462 | + Y.fire(info_type.EV_ISPRIVATE, { |
3463 | + text: updated_msg |
3464 | + }); |
3465 | + |
3466 | + var banner = Y.one('.banner'); |
3467 | + var banner_text = banner.one('.banner-content').get('text'); |
3468 | + Y.Assert.areNotEqual( |
3469 | + -1, |
3470 | + banner_text.indexOf(updated_msg), |
3471 | + 'The banner updated content to the second event message.'); |
3472 | + |
3473 | + // Manually clean up. |
3474 | + Y.one('.yui3-banner').remove(true); |
3475 | + view.destroy(); |
3476 | + |
3477 | + } |
3478 | + })); |
3479 | + |
3480 | +}, '0.1', { |
3481 | + requires: ['test', 'event-simulate', 'node-event-simulate', |
3482 | + 'lp.app.information_type', 'lp.views.global'] |
3483 | +}); |
3484 | |
3485 | === removed file 'lib/lp/app/javascript/views/tests/test_global.js' |
3486 | --- lib/lp/app/javascript/views/tests/test_global.js 2012-11-09 18:55:02 +0000 |
3487 | +++ lib/lp/app/javascript/views/tests/test_global.js 1970-01-01 00:00:00 +0000 |
3488 | @@ -1,164 +0,0 @@ |
3489 | -/* Copyright (c) 2012 Canonical Ltd. All rights reserved. */ |
3490 | - |
3491 | -YUI.add('lp.views.global.test', function (Y) { |
3492 | - var tests = Y.namespace('lp.views.global.test'); |
3493 | - var info_type = Y.namespace('lp.app.information_type'); |
3494 | - var ns = Y.lp.views; |
3495 | - |
3496 | - tests.suite = new Y.Test.Suite('lp.views.global test'); |
3497 | - tests.suite.add(new Y.Test.Case({ |
3498 | - name: 'lp.views.global', |
3499 | - |
3500 | - setUp: function () { |
3501 | - this.container = Y.one('#fixture'); |
3502 | - window.LP = { |
3503 | - cache: { |
3504 | - related_features: { |
3505 | - private_projects: { |
3506 | - is_beta: true, |
3507 | - title: "Private Projects", |
3508 | - url: "http://blog.ld.net/general/beta", |
3509 | - value: "true" |
3510 | - } |
3511 | - }, |
3512 | - information_type_data: { |
3513 | - PUBLIC: { |
3514 | - value: 'PUBLIC', name: 'Public', |
3515 | - is_private: false, order: 1, |
3516 | - description: 'Public Description' |
3517 | - }, |
3518 | - EMBARGOED: { |
3519 | - value: 'EMBARGOED', name: 'Embargoed', |
3520 | - is_private: true, order: 2, |
3521 | - description: 'Something embargoed' |
3522 | - }, |
3523 | - PROPRIETARY: { |
3524 | - value: 'PROPRIETARY', name: 'Proprietary', |
3525 | - is_private: true, order: 3, |
3526 | - description: 'Private Description' |
3527 | - } |
3528 | - } |
3529 | - } |
3530 | - }; |
3531 | - }, |
3532 | - |
3533 | - tearDown: function () { |
3534 | - this.container.empty(); |
3535 | - }, |
3536 | - |
3537 | - test_library_exists: function () { |
3538 | - Y.Assert.isObject(ns.Global, |
3539 | - "Could not locate the lp.views.global module"); |
3540 | - }, |
3541 | - |
3542 | - test_basic_render: function () { |
3543 | - // Nothing is currently rendered out by default. |
3544 | - var view = new ns.Global(); |
3545 | - view.render(); |
3546 | - |
3547 | - Y.Assert.areEqual( |
3548 | - '', |
3549 | - this.container.get('innerHTML'), |
3550 | - 'The container is still empty.'); |
3551 | - view.destroy(); |
3552 | - }, |
3553 | - |
3554 | - test_beta_banner: function () { |
3555 | - // If we've prepped on load a beta banner will auto appear. |
3556 | - var banner_container = Y.Node.create('<div/>'); |
3557 | - banner_container.addClass('beta_banner_container'); |
3558 | - this.container.append(banner_container); |
3559 | - var view = new ns.Global(); |
3560 | - view.render(); |
3561 | - |
3562 | - // We have to wait until after page load event fires to test |
3563 | - // things out. |
3564 | - var banner_node = Y.one('.banner'); |
3565 | - Y.Assert.isObject( |
3566 | - banner_node, |
3567 | - 'The container has a new banner node in there.'); |
3568 | - |
3569 | - view.destroy(); |
3570 | - }, |
3571 | - |
3572 | - test_privacy: function () { |
3573 | - var beta_container = Y.Node.create('<div/>'); |
3574 | - var private_container = Y.Node.create('<div/>'); |
3575 | - |
3576 | - beta_container.addClass('beta_banner_container'); |
3577 | - private_container.addClass('private_banner_container'); |
3578 | - |
3579 | - this.container.append(beta_container); |
3580 | - this.container.append(private_container); |
3581 | - var view = new ns.Global(); |
3582 | - view.render(); |
3583 | - |
3584 | - // We have to wait until after page load event fires to test |
3585 | - // things out. |
3586 | - var banner_nodes = Y.all('.banner'); |
3587 | - Y.Assert.areEqual( |
3588 | - 2, |
3589 | - banner_nodes._nodes.length, |
3590 | - 'We should have two banners rendered.'); |
3591 | - |
3592 | - view.destroy(); |
3593 | - }, |
3594 | - |
3595 | - test_privacy_banner_from_event: function () { |
3596 | - // We can also get a privacy banner via a fired event. |
3597 | - // This is hard coded to the <body> tag so we have to do some |
3598 | - // manual clean up here. |
3599 | - var view = new ns.Global(); |
3600 | - view.render(); |
3601 | - |
3602 | - var msg = 'Testing Global'; |
3603 | - Y.fire(info_type.EV_ISPRIVATE, { |
3604 | - text: msg |
3605 | - }); |
3606 | - |
3607 | - var banner = Y.one('.banner'); |
3608 | - var banner_text = banner.one('.banner-content').get('text'); |
3609 | - Y.Assert.areNotEqual( |
3610 | - -1, |
3611 | - banner_text.indexOf(msg), |
3612 | - 'The event text is turned into the banner content'); |
3613 | - |
3614 | - // Manually clean up. |
3615 | - Y.one('.yui3-banner').remove(true); |
3616 | - view.destroy(); |
3617 | - }, |
3618 | - |
3619 | - test_banner_updates_content: function () { |
3620 | - // If we change our privacy information type the banner needs to |
3621 | - // update the content to the new text value from the event. |
3622 | - var view = new ns.Global(); |
3623 | - view.render(); |
3624 | - |
3625 | - var msg = 'Testing Global'; |
3626 | - Y.fire(info_type.EV_ISPRIVATE, { |
3627 | - text: msg |
3628 | - }); |
3629 | - |
3630 | - var updated_msg = 'Updated content'; |
3631 | - Y.fire(info_type.EV_ISPRIVATE, { |
3632 | - text: updated_msg |
3633 | - }); |
3634 | - |
3635 | - var banner = Y.one('.banner'); |
3636 | - var banner_text = banner.one('.banner-content').get('text'); |
3637 | - Y.Assert.areNotEqual( |
3638 | - -1, |
3639 | - banner_text.indexOf(updated_msg), |
3640 | - 'The banner updated content to the second event message.'); |
3641 | - |
3642 | - // Manually clean up. |
3643 | - Y.one('.yui3-banner').remove(true); |
3644 | - view.destroy(); |
3645 | - |
3646 | - } |
3647 | - })); |
3648 | - |
3649 | -}, '0.1', { |
3650 | - requires: ['test', 'event-simulate', 'node-event-simulate', |
3651 | - 'lp.app.information_type', 'lp.views.global'] |
3652 | -}); |
3653 | |
3654 | === modified file 'lib/lp/app/templates/base-layout-macros.pt' |
3655 | --- lib/lp/app/templates/base-layout-macros.pt 2012-08-13 17:49:31 +0000 |
3656 | +++ lib/lp/app/templates/base-layout-macros.pt 2012-11-12 13:21:28 +0000 |
3657 | @@ -163,19 +163,17 @@ |
3658 | <script id="base-layout-load-scripts" type="text/javascript"> |
3659 | //<![CDATA[ |
3660 | LPJS.use('base', 'node', 'console', 'event', |
3661 | - 'oop', 'lp', 'lp.app.banner.privacy', |
3662 | - 'lp.app.banner.beta', 'lp.app.foldables','lp.app.sorttable', |
3663 | + 'oop', 'lp', 'lp.app.foldables','lp.app.sorttable', |
3664 | 'lp.app.inlinehelp', 'lp.app.links', 'lp.app.longpoll', |
3665 | 'lp.bugs.bugtask_index', 'lp.bugs.subscribers', |
3666 | 'lp.app.ellipsis', 'lp.code.branchmergeproposal.diff', |
3667 | + 'lp.views.global', |
3668 | function(Y) { |
3669 | |
3670 | Y.on("domready", function () { |
3671 | - if (Y.one(document.body).hasClass('private')) { |
3672 | - banner = Y.lp.app.banner.privacy.getPrivacyBanner(); |
3673 | - banner.show(); |
3674 | - } |
3675 | - Y.lp.app.banner.beta.show_beta_if_needed(); |
3676 | + var global_view = new Y.lp.views.Global(); |
3677 | + global_view.render(); |
3678 | + |
3679 | Y.lp.app.sorttable.SortTable.init(); |
3680 | Y.lp.app.inlinehelp.init_help(); |
3681 | Y.lp.activate_collapsibles(); |
3682 | |
3683 | === modified file 'lib/lp/app/templates/base-layout.pt' |
3684 | --- lib/lp/app/templates/base-layout.pt 2012-05-18 22:04:13 +0000 |
3685 | +++ lib/lp/app/templates/base-layout.pt 2012-11-12 13:21:28 +0000 |
3686 | @@ -64,6 +64,12 @@ |
3687 | ${view/macro:pagetype} |
3688 | ${view/fmt:global-css} |
3689 | yui3-skin-sam"> |
3690 | + <tal:beta-banner condition="view/beta_features"> |
3691 | + <div class="beta_banner_container"></div> |
3692 | + </tal:beta-banner> |
3693 | + <tal:private-banner condition="view/private"> |
3694 | + <div class="private_banner_container"></div> |
3695 | + </tal:private-banner> |
3696 | <script type="text/javascript" |
3697 | tal:condition="python: is_lpnet"> |
3698 | var _gaq = _gaq || []; |
3699 | @@ -97,10 +103,8 @@ |
3700 | <div class="yui-t4" |
3701 | tal:omit-tag="not: view/macro:pagehas/portlets"> |
3702 | <div id="maincontent" class="yui-main"> |
3703 | - <metal:privacy-banner |
3704 | - use-macro="view/@@+banner-macros/beta-banner"/> |
3705 | - <metal:privacy-banner |
3706 | - use-macro="view/@@+banner-macros/privacy-banner"/> |
3707 | + <!-- <metal:privacy-banner --> |
3708 | + <!-- use-macro="view/@@+banner-macros/privacy-banner"/> --> |
3709 | <div class="yui-b" |
3710 | tal:attributes=" |
3711 | lang view/lang|default_language|default; |
3712 | |
3713 | === modified file 'lib/lp/archivepublisher/scripts/generate_contents_files.py' |
3714 | --- lib/lp/archivepublisher/scripts/generate_contents_files.py 2012-11-10 02:25:07 +0000 |
3715 | +++ lib/lp/archivepublisher/scripts/generate_contents_files.py 2012-11-12 13:21:28 +0000 |
3716 | @@ -94,6 +94,16 @@ |
3717 | "Failure while running command: %s" % description) |
3718 | |
3719 | |
3720 | +def move_file(old_path, new_path): |
3721 | + """Rename file `old_path` to `new_path`. |
3722 | + |
3723 | + Mercilessly delete any file that may already exist at `new_path`. |
3724 | + """ |
3725 | + if file_exists(new_path): |
3726 | + os.remove(new_path) |
3727 | + os.rename(old_path, new_path) |
3728 | + |
3729 | + |
3730 | class GenerateContentsFiles(LaunchpadCronScript): |
3731 | |
3732 | distribution = None |
3733 | @@ -154,7 +164,7 @@ |
3734 | def getArchs(self, suite): |
3735 | """Query architectures supported by the suite.""" |
3736 | series, _ = self.distribution.getDistroSeriesAndPocket(suite) |
3737 | - return [arch.architecturetag for arch in series.enabled_architectures] |
3738 | + return [arch.architecturetag for arch in series.architectures] |
3739 | |
3740 | def getDirs(self, archs): |
3741 | """Subdirectories needed for each component.""" |
3742 | @@ -276,8 +286,8 @@ |
3743 | contents_dest = os.path.join( |
3744 | self.config.distsroot, suite, "%s.gz" % contents_filename) |
3745 | |
3746 | - os.rename(current_contents, last_contents) |
3747 | - os.rename(new_contents, contents_dest) |
3748 | + move_file(current_contents, last_contents) |
3749 | + move_file(new_contents, contents_dest) |
3750 | os.chmod(contents_dest, 0664) |
3751 | else: |
3752 | self.logger.debug( |
3753 | |
3754 | === modified file 'lib/lp/archivepublisher/scripts/generate_extra_overrides.py' |
3755 | --- lib/lp/archivepublisher/scripts/generate_extra_overrides.py 2012-11-10 02:21:31 +0000 |
3756 | +++ lib/lp/archivepublisher/scripts/generate_extra_overrides.py 2012-11-12 13:21:28 +0000 |
3757 | @@ -367,7 +367,7 @@ |
3758 | series_name = series.name |
3759 | components = self.getComponents(series) |
3760 | architectures = sorted( |
3761 | - arch.architecturetag for arch in series.enabled_architectures) |
3762 | + [arch.architecturetag for arch in series.architectures]) |
3763 | |
3764 | # This takes a while. Ensure that we do it without keeping a |
3765 | # database transaction open. |
3766 | |
3767 | === modified file 'lib/lp/archivepublisher/tests/test_generate_contents_files.py' |
3768 | --- lib/lp/archivepublisher/tests/test_generate_contents_files.py 2012-11-10 02:25:07 +0000 |
3769 | +++ lib/lp/archivepublisher/tests/test_generate_contents_files.py 2012-11-12 13:21:28 +0000 |
3770 | @@ -14,10 +14,10 @@ |
3771 | differ_in_content, |
3772 | execute, |
3773 | GenerateContentsFiles, |
3774 | + move_file, |
3775 | ) |
3776 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
3777 | from lp.services.log.logger import DevNullLogger |
3778 | -from lp.services.osutils import write_file |
3779 | from lp.services.scripts.base import LaunchpadScriptFailure |
3780 | from lp.services.scripts.tests import run_script |
3781 | from lp.services.utils import file_exists |
3782 | @@ -29,24 +29,33 @@ |
3783 | ) |
3784 | |
3785 | |
3786 | +def write_file(filename, content=""): |
3787 | + """Write `content` to `filename`, and flush.""" |
3788 | + output_file = file(filename, 'w') |
3789 | + output_file.write(content) |
3790 | + output_file.close() |
3791 | + |
3792 | + |
3793 | def fake_overrides(script, distroseries): |
3794 | """Fake overrides files so `script` can run `apt-ftparchive`.""" |
3795 | + os.makedirs(script.config.overrideroot) |
3796 | + |
3797 | components = ['main', 'restricted', 'universe', 'multiverse'] |
3798 | architectures = script.getArchs(distroseries.name) |
3799 | suffixes = components + ['extra.' + component for component in components] |
3800 | for suffix in suffixes: |
3801 | write_file(os.path.join( |
3802 | script.config.overrideroot, |
3803 | - "override.%s.%s" % (distroseries.name, suffix)), "") |
3804 | + "override.%s.%s" % (distroseries.name, suffix))) |
3805 | |
3806 | for component in components: |
3807 | write_file(os.path.join( |
3808 | script.config.overrideroot, |
3809 | - "%s_%s_source" % (distroseries.name, component)), "") |
3810 | + "%s_%s_source" % (distroseries.name, component))) |
3811 | for arch in architectures: |
3812 | write_file(os.path.join( |
3813 | script.config.overrideroot, |
3814 | - "%s_%s_binary-%s" % (distroseries.name, component, arch)), "") |
3815 | + "%s_%s_binary-%s" % (distroseries.name, component, arch))) |
3816 | |
3817 | |
3818 | class TestHelpers(TestCaseWithFactory): |
3819 | @@ -96,6 +105,24 @@ |
3820 | execute(logger, "touch", [filename]) |
3821 | self.assertTrue(file_exists(filename)) |
3822 | |
3823 | + def test_move_file_renames_file(self): |
3824 | + # move_file renames a file from its old name to its new name. |
3825 | + self.useTempDir() |
3826 | + text = self.factory.getUniqueString() |
3827 | + write_file("old_name", text) |
3828 | + move_file("old_name", "new_name") |
3829 | + self.assertEqual(text, file("new_name").read()) |
3830 | + |
3831 | + def test_move_file_overwrites_old_file(self): |
3832 | + # If move_file finds another file in the way, that file gets |
3833 | + # deleted. |
3834 | + self.useTempDir() |
3835 | + write_file("new_name", self.factory.getUniqueString()) |
3836 | + new_text = self.factory.getUniqueString() |
3837 | + write_file("old_name", new_text) |
3838 | + move_file("old_name", "new_name") |
3839 | + self.assertEqual(new_text, file("new_name").read()) |
3840 | + |
3841 | |
3842 | class TestGenerateContentsFiles(TestCaseWithFactory): |
3843 | """Tests for the actual `GenerateContentsFiles` script.""" |
3844 | @@ -135,6 +162,9 @@ |
3845 | :return: The arbitrary string that is also in the file. |
3846 | """ |
3847 | marker_contents = self.factory.getUniqueString() |
3848 | + dir_name = os.path.dirname(file_path) |
3849 | + if not file_exists(dir_name): |
3850 | + os.makedirs(dir_name) |
3851 | write_file(file_path, marker_contents) |
3852 | return marker_contents |
3853 | |
3854 | @@ -173,12 +203,10 @@ |
3855 | self.assertEqual(distro, script.distribution) |
3856 | |
3857 | def test_getArchs(self): |
3858 | - # getArchs returns a list of enabled architectures in the distroseries. |
3859 | + # getArchs returns a list of architectures in the distroseries. |
3860 | distro = self.makeDistro() |
3861 | distroseries = self.factory.makeDistroSeries(distro) |
3862 | das = self.factory.makeDistroArchSeries(distroseries=distroseries) |
3863 | - self.factory.makeDistroArchSeries( |
3864 | - distroseries=distroseries, enabled=False) |
3865 | script = self.makeScript(das.distroseries.distribution) |
3866 | self.assertEqual( |
3867 | [das.architecturetag], script.getArchs(distroseries.name)) |
3868 | |
3869 | === modified file 'lib/lp/archivepublisher/tests/test_generate_extra_overrides.py' |
3870 | --- lib/lp/archivepublisher/tests/test_generate_extra_overrides.py 2012-11-10 02:21:31 +0000 |
3871 | +++ lib/lp/archivepublisher/tests/test_generate_extra_overrides.py 2012-11-12 13:21:28 +0000 |
3872 | @@ -36,7 +36,6 @@ |
3873 | from lp.services.utils import file_exists |
3874 | from lp.soyuz.enums import PackagePublishingStatus |
3875 | from lp.testing import TestCaseWithFactory |
3876 | -from lp.testing.fakemethod import FakeMethod |
3877 | from lp.testing.faketransaction import FakeTransaction |
3878 | from lp.testing.layers import ( |
3879 | LaunchpadZopelessLayer, |
3880 | @@ -614,21 +613,6 @@ |
3881 | self.assertTrue(os.path.exists(output(seed_new))) |
3882 | self.assertFalse(os.path.exists(output(seed_old))) |
3883 | |
3884 | - def test_process_skips_disabled_distroarchseries(self): |
3885 | - # The script does not generate overrides for disabled DistroArchSeries. |
3886 | - flavour = self.factory.getUniqueString() |
3887 | - self.setUpDistroAndScript(extra_args=[flavour]) |
3888 | - das = self.factory.makeDistroArchSeries( |
3889 | - distroseries=self.distroseries[0]) |
3890 | - self.factory.makeDistroArchSeries( |
3891 | - distroseries=self.distroseries[0], enabled=False) |
3892 | - self.script.generateExtraOverrides = FakeMethod() |
3893 | - self.script.process() |
3894 | - self.assertEqual(1, self.script.generateExtraOverrides.call_count) |
3895 | - self.assertEqual( |
3896 | - [das.architecturetag], |
3897 | - self.script.generateExtraOverrides.calls[0][0][2]) |
3898 | - |
3899 | def test_main(self): |
3900 | # If run end-to-end, the script generates override files containing |
3901 | # output for all architectures, and sends germinate's log output to |
3902 | |
3903 | === modified file 'lib/lp/blueprints/javascript/addspec.js' |
3904 | --- lib/lp/blueprints/javascript/addspec.js 2012-10-15 16:01:38 +0000 |
3905 | +++ lib/lp/blueprints/javascript/addspec.js 2012-11-12 13:21:28 +0000 |
3906 | @@ -10,11 +10,24 @@ |
3907 | |
3908 | var namespace = Y.namespace('lp.blueprints.addspec'); |
3909 | var to_choice = Y.lp.app.information_type.cache_to_choicesource; |
3910 | +var info_type = Y.lp.app.information_type; |
3911 | |
3912 | namespace.set_up = function () { |
3913 | var choice_data = to_choice(LP.cache.information_type_data); |
3914 | - Y.lp.app.choice.addPopupChoiceForRadioButtons('information_type', |
3915 | - choice_data); |
3916 | + var widget = Y.lp.app.choice.addPopupChoiceForRadioButtons( |
3917 | + 'information_type', |
3918 | + choice_data); |
3919 | + |
3920 | + // We are not doing ajax saves of the information type so we need to |
3921 | + // disable the flash on save for the widget. |
3922 | + widget.set('flashEnabled', false); |
3923 | + |
3924 | + // Make sure we catch changes to the information type. |
3925 | + widget.on('save', function (ev) { |
3926 | + Y.fire(info_type.EV_CHANGE, { |
3927 | + value: ev.target.get('value') |
3928 | + }); |
3929 | + }); |
3930 | }; |
3931 | |
3932 | }, "0.1", {"requires": ['lp.app.information_type', 'lp.app.choice']}); |
3933 | |
3934 | === modified file 'lib/lp/bugs/browser/tests/test_bug_views.py' |
3935 | --- lib/lp/bugs/browser/tests/test_bug_views.py 2012-11-11 23:39:34 +0000 |
3936 | +++ lib/lp/bugs/browser/tests/test_bug_views.py 2012-11-12 13:21:28 +0000 |
3937 | @@ -28,6 +28,7 @@ |
3938 | from zope.security.proxy import removeSecurityProxy |
3939 | |
3940 | from lp.app.enums import InformationType |
3941 | +from lp.app.interfaces.services import IService |
3942 | from lp.bugs.adapters.bugchange import BugAttachmentChange |
3943 | from lp.registry.enums import BugSharingPolicy |
3944 | from lp.registry.interfaces.accesspolicy import ( |
3945 | @@ -499,6 +500,28 @@ |
3946 | self.assertEqual( |
3947 | u'Private', soup.find('label', text="Private")) |
3948 | |
3949 | + def test_bugtask_view_user_with_grant_on_bug_for_private_product(self): |
3950 | + # The regular bug view is properly rendered even if the user |
3951 | + # does not have permissions to view every detail of a product. |
3952 | + owner = self.factory.makePerson() |
3953 | + product = self.factory.makeProduct( |
3954 | + owner=owner, |
3955 | + information_type=InformationType.PROPRIETARY) |
3956 | + user = self.factory.makePerson() |
3957 | + with person_logged_in(owner): |
3958 | + bug = self.factory.makeBug( |
3959 | + target=product, information_type=InformationType.PROPRIETARY) |
3960 | + getUtility(IService, 'sharing').ensureAccessGrants( |
3961 | + [user], owner, bugs=[bug]) |
3962 | + launchbag = getUtility(IOpenLaunchBag) |
3963 | + launchbag.add(bug) |
3964 | + launchbag.add(bug.default_bugtask) |
3965 | + with person_logged_in(user): |
3966 | + view = create_initialized_view( |
3967 | + bug.default_bugtask, name=u'+index', principal=user) |
3968 | + contents = view.render() |
3969 | + self.assertTrue(bug.title in contents) |
3970 | + |
3971 | |
3972 | class TestBugTextViewPrivateTeams(TestCaseWithFactory): |
3973 | """ Test for rendering BugTextView with private team artifacts. |
3974 | |
3975 | === modified file 'lib/lp/bugs/javascript/bugtask_index.js' |
3976 | --- lib/lp/bugs/javascript/bugtask_index.js 2012-10-11 04:57:59 +0000 |
3977 | +++ lib/lp/bugs/javascript/bugtask_index.js 2012-11-12 13:21:28 +0000 |
3978 | @@ -1131,6 +1131,5 @@ |
3979 | "lp.app.information_type", |
3980 | "lp.app.widgets.expander", "lp.client", "escape", |
3981 | "lp.client.plugins", "lp.app.errors", |
3982 | - "lp.app.banner.privacy", |
3983 | "lp.app.confirmationoverlay", |
3984 | "lp.bugs.duplicates"]}); |
3985 | |
3986 | === modified file 'lib/lp/bugs/javascript/filebug.js' |
3987 | --- lib/lp/bugs/javascript/filebug.js 2012-09-25 19:15:04 +0000 |
3988 | +++ lib/lp/bugs/javascript/filebug.js 2012-11-12 13:21:28 +0000 |
3989 | @@ -9,6 +9,7 @@ |
3990 | YUI.add('lp.bugs.filebug', function(Y) { |
3991 | |
3992 | var namespace = Y.namespace('lp.bugs.filebug'); |
3993 | +var info_type = Y.lp.app.information_type; |
3994 | |
3995 | // For tests. |
3996 | var skip_animation; |
3997 | @@ -28,13 +29,40 @@ |
3998 | if (Y.Lang.isValue(search_button )) { |
3999 | search_button.set('value', 'Check again'); |
4000 | } |
4001 | + setup_plain_inputs(); |
4002 | set_default_privacy_banner(); |
4003 | - setup_information_type(); |
4004 | setup_security_related(); |
4005 | setupChoiceWidgets(); |
4006 | } |
4007 | }; |
4008 | |
4009 | + |
4010 | +/** |
4011 | + * If there are not choice widgets, but radio buttons, then we should watch |
4012 | + * those radio buttons for change to make sure we fire the information type |
4013 | + * change events. |
4014 | + */ |
4015 | +var setup_plain_inputs = function () { |
4016 | + var itypes_table = Y.one('.radio-button-widget'); |
4017 | + |
4018 | + if (itypes_table) { |
4019 | + itypes_table.delegate('change', function(ev) { |
4020 | + Y.fire(info_type.EV_CHANGE, { |
4021 | + value: this.get('value') |
4022 | + }); |
4023 | + }, "input[name='field.information_type']"); |
4024 | + } |
4025 | +}; |
4026 | + |
4027 | +/** |
4028 | + * Due to the privacy setting of the project/bugs we might only allow a |
4029 | + * non-public information type. In this case we need to go ahead and let the |
4030 | + * user know it's going to be private. |
4031 | + * |
4032 | + * This is used by the security checks. If the issue is unmade/not security |
4033 | + * related then we need to check the normal default behavior to make sure we |
4034 | + * show the correct banner. |
4035 | + */ |
4036 | var set_default_privacy_banner = function() { |
4037 | var itypes_table = Y.one('.radio-button-widget'); |
4038 | var val = null; |
4039 | @@ -48,47 +76,12 @@ |
4040 | if (LP.cache.bug_private_by_default) { |
4041 | var filebug_privacy_text = "This report will be private. " + |
4042 | "You can disclose it later."; |
4043 | - update_privacy_banner(true, filebug_privacy_text); |
4044 | - } else { |
4045 | - update_banner_from_information_type(val); |
4046 | - } |
4047 | -}; |
4048 | - |
4049 | -var update_privacy_banner = function(show, banner_text) { |
4050 | - var banner = Y.lp.app.banner.privacy.getPrivacyBanner( |
4051 | - banner_text, skip_animation); |
4052 | - if (show) { |
4053 | - banner.show(); |
4054 | - } else { |
4055 | - banner.hide(); |
4056 | - } |
4057 | -}; |
4058 | - |
4059 | -var get_new_banner_text = function(value) { |
4060 | - var cache = LP.cache.information_type_data; |
4061 | - var text_template = "This report contains {info_type} information." + |
4062 | - " You can change the information type later."; |
4063 | - return Y.Lang.substitute(text_template, { |
4064 | - 'info_type': cache[value].name |
4065 | - }); |
4066 | -}; |
4067 | - |
4068 | -var update_banner_from_information_type = function(value) { |
4069 | - var banner_text = get_new_banner_text(value); |
4070 | - var is_private = LP.cache.information_type_data[value].is_private; |
4071 | - update_privacy_banner(is_private, banner_text); |
4072 | -}; |
4073 | - |
4074 | -var setup_information_type = function() { |
4075 | - var itypes_table = Y.one('.radio-button-widget'); |
4076 | - if (!Y.Lang.isValue(itypes_table)) { |
4077 | - return; |
4078 | - } |
4079 | - |
4080 | - |
4081 | - itypes_table.delegate('change', function() { |
4082 | - update_banner_from_information_type(this.get('value')); |
4083 | - }, "input[name='field.information_type']"); |
4084 | + |
4085 | + Y.fire(info_type.EV_ISPRIVATE, { |
4086 | + text: filebug_privacy_text, |
4087 | + value: val |
4088 | + }); |
4089 | + } |
4090 | }; |
4091 | |
4092 | |
4093 | @@ -100,8 +93,25 @@ |
4094 | var information_helpers = Y.lp.app.information_type; |
4095 | var choices = information_helpers.cache_to_choicesource(cache); |
4096 | |
4097 | - Y.lp.app.choice.addPopupChoiceForRadioButtons( |
4098 | + var information_type = Y.lp.app.choice.addPopupChoiceForRadioButtons( |
4099 | 'information_type', choices, true); |
4100 | + |
4101 | + // When dealing with legacy inputs the information type could have not |
4102 | + // been created and we get back a null value. |
4103 | + if (information_type) { |
4104 | + // We are not doing ajax saves of the information type so we need to |
4105 | + // disable the flash on save for the widget. |
4106 | + information_type.set('flashEnabled', false); |
4107 | + |
4108 | + // When the information type widget changes we need to let the |
4109 | + // information type module know so it can process the change and |
4110 | + // update things like banners displayed. |
4111 | + information_type.on('save', function (ev) { |
4112 | + Y.fire(info_type.EV_CHANGE, { |
4113 | + value: ev.target.get('value') |
4114 | + }); |
4115 | + }); |
4116 | + } |
4117 | }; |
4118 | |
4119 | var setup_security_related = function() { |
4120 | @@ -116,8 +126,19 @@ |
4121 | security_related.on('change', function() { |
4122 | var checked = security_related.get('checked'); |
4123 | if (checked) { |
4124 | - update_privacy_banner(true, notification_text); |
4125 | + // XXX: This should use the correct information type based on the |
4126 | + // project default. We use PRIVATESECURITY because it'll get the |
4127 | + // right banner shown. |
4128 | + Y.fire(info_type.EV_ISPRIVATE, { |
4129 | + text: notification_text, |
4130 | + value: 'PRIVATESECURITY' |
4131 | + }); |
4132 | } else { |
4133 | + Y.fire(info_type.EV_ISPUBLIC, { |
4134 | + value: 'PUBLIC' |
4135 | + }); |
4136 | + // Check with the default settings if we should add the privacy |
4137 | + // banner back because it's the default of the current project. |
4138 | set_default_privacy_banner(); |
4139 | } |
4140 | }); |
4141 | @@ -127,5 +148,5 @@ |
4142 | |
4143 | }, "0.1", {"requires": [ |
4144 | "base", "node", "event", "node-event-delegate", "lp.ui.choiceedit", |
4145 | - "lp.app.banner.privacy", "lp.app.choice", "lp.app.information_type", |
4146 | + "lp.ui.banner", "lp.app.choice", "lp.app.information_type", |
4147 | "lp.bugs.filebug_dupefinder"]}); |
4148 | |
4149 | === modified file 'lib/lp/bugs/javascript/tests/test_filebug.js' |
4150 | --- lib/lp/bugs/javascript/tests/test_filebug.js 2012-10-26 10:00:20 +0000 |
4151 | +++ lib/lp/bugs/javascript/tests/test_filebug.js 2012-11-12 13:21:28 +0000 |
4152 | @@ -3,6 +3,8 @@ |
4153 | YUI.add('lp.bugs.filebug.test', function (Y) { |
4154 | |
4155 | var tests = Y.namespace('lp.bugs.filebug.test'); |
4156 | + var info_type = Y.lp.app.information_type; |
4157 | + |
4158 | tests.suite = new Y.Test.Suite( |
4159 | 'lp.bugs.filebug Tests'); |
4160 | |
4161 | @@ -73,96 +75,136 @@ |
4162 | |
4163 | // Filing a public bug does not show the privacy banner. |
4164 | test_setup_filebug_public: function () { |
4165 | + // Watch out for the event that showing a privacy banner would |
4166 | + // fire. |
4167 | + var fired = false; |
4168 | + var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) { |
4169 | + fired = true; |
4170 | + }); |
4171 | this.setupForm(true); |
4172 | - var banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4173 | - Y.Assert.isNotNull(banner_hidden); |
4174 | + Y.Assert.isFalse(fired); |
4175 | + ev.detach(); |
4176 | }, |
4177 | |
4178 | // Filing a bug for a project with private bugs shows the privacy |
4179 | // banner. |
4180 | test_setup_filebug_private: function () { |
4181 | + var fired = false; |
4182 | + var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) { |
4183 | + fired = true; |
4184 | + Y.Assert.areEqual( |
4185 | + 'This report will be private. ' + |
4186 | + 'You can disclose it later.', ev.text); |
4187 | + }); |
4188 | + |
4189 | window.LP.cache.bug_private_by_default = true; |
4190 | this.setupForm(true); |
4191 | - var banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4192 | - Y.Assert.isNull(banner_hidden); |
4193 | - var banner_text = Y.one('.banner-text').get('text'); |
4194 | - Y.Assert.areEqual( |
4195 | - 'This report will be private. ' + |
4196 | - 'You can disclose it later.', banner_text); |
4197 | + Y.Assert.isTrue(fired); |
4198 | + ev.detach(); |
4199 | }, |
4200 | |
4201 | // Selecting a private info type using the legacy radio buttons |
4202 | // turns on the privacy banner. |
4203 | test_legacy_select_private_info_type: function () { |
4204 | + var fired = false; |
4205 | + var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) { |
4206 | + fired = true; |
4207 | + Y.Assert.areEqual( |
4208 | + 'This report will be private because it is a security ' + |
4209 | + 'vulnerability. You can disclose it later.', ev.text); |
4210 | + }); |
4211 | + |
4212 | this.setupForm(true); |
4213 | - var banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4214 | - Y.Assert.isNotNull(banner_hidden); |
4215 | + Y.Assert.isFalse(fired); |
4216 | + |
4217 | Y.one('[id="field.information_type.2"]').simulate('click'); |
4218 | - banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4219 | - Y.Assert.isNull(banner_hidden); |
4220 | - var banner_text = Y.one('.banner-text').get('text'); |
4221 | - Y.Assert.areEqual( |
4222 | - 'This report contains Private Security information. ' + |
4223 | - 'You can change the information type later.', banner_text); |
4224 | + // And the event should be fired and caught. |
4225 | + Y.Assert.isTrue(fired); |
4226 | + ev.detach(); |
4227 | }, |
4228 | |
4229 | // Selecting a public info type using the legacy radio buttons |
4230 | // turns off the privacy banner. |
4231 | test_legacy_select_public_info_type: function () { |
4232 | + var fired = false; |
4233 | + var ev = Y.on(info_type.EV_ISPUBLIC, function (ev) { |
4234 | + fired = true; |
4235 | + }); |
4236 | + |
4237 | window.LP.cache.bug_private_by_default = true; |
4238 | this.setupForm(true); |
4239 | + |
4240 | + // This will fire ISPRIVATE and a banner shows. |
4241 | Y.one('[id="field.information_type.2"]').simulate('click'); |
4242 | - var banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4243 | - Y.Assert.isNull(banner_hidden); |
4244 | + |
4245 | + // The second one will fire ISPUBLIC and the banner disappears. |
4246 | Y.one('[id="field.information_type.0"]').simulate('click'); |
4247 | - banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4248 | - Y.Assert.isNotNull(banner_hidden); |
4249 | + Y.Assert.isTrue(fired); |
4250 | }, |
4251 | |
4252 | // When non bug supervisors select a security related bug the privacy |
4253 | // banner is turned on. |
4254 | test_select_security_related: function () { |
4255 | + var fired = false; |
4256 | + var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) { |
4257 | + fired = true; |
4258 | + Y.Assert.areEqual( |
4259 | + 'This report will be private because it is a security ' + |
4260 | + 'vulnerability. You can disclose it later.', ev.text); |
4261 | + }); |
4262 | + |
4263 | this.setupForm(false); |
4264 | - var banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4265 | - Y.Assert.isNotNull(banner_hidden); |
4266 | + Y.Assert.isFalse(fired); |
4267 | + |
4268 | Y.one('[id="field.security_related"]').simulate('click'); |
4269 | - banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4270 | - Y.Assert.isNull(banner_hidden); |
4271 | - var banner_text = Y.one('.banner-text').get('text'); |
4272 | - Y.Assert.areEqual( |
4273 | - 'This report will be private because it is a ' + |
4274 | - 'security vulnerability. You can disclose it later.', |
4275 | - banner_text); |
4276 | + // And the event should be fired and caught. |
4277 | + Y.Assert.isTrue(fired); |
4278 | + ev.detach(); |
4279 | }, |
4280 | |
4281 | // When non bug supervisors unselect a security related bug the privacy |
4282 | // banner is turned off. |
4283 | test_unselect_security_related: function () { |
4284 | + var fired = false; |
4285 | + var ev = Y.on(info_type.EV_ISPUBLIC, function (ev) { |
4286 | + fired = true; |
4287 | + }); |
4288 | + |
4289 | this.setupForm(false); |
4290 | - Y.one('[id="field.security_related"]').simulate('click'); |
4291 | - var banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4292 | - Y.Assert.isNull(banner_hidden); |
4293 | - Y.one('[id="field.security_related"]').simulate('click'); |
4294 | - banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4295 | - Y.Assert.isNotNull(banner_hidden); |
4296 | + |
4297 | + Y.one('[id="field.security_related"]').simulate('click'); |
4298 | + Y.Assert.isFalse(fired); |
4299 | + |
4300 | + Y.one('[id="field.security_related"]').simulate('click'); |
4301 | + Y.Assert.isTrue(fired); |
4302 | }, |
4303 | |
4304 | // When non bug supervisors unselect a security related bug the privacy |
4305 | // banner remains on for private_by_default bugs. |
4306 | test_unselect_security_related_default_private: function () { |
4307 | window.LP.cache.bug_private_by_default = true; |
4308 | + var public = 0; |
4309 | + var private = 0; |
4310 | + var ev = Y.on(info_type.EV_ISPUBLIC, function (ev) { |
4311 | + public = public + 1; |
4312 | + }); |
4313 | + |
4314 | + var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) { |
4315 | + private = private + 1; |
4316 | + }); |
4317 | + |
4318 | + |
4319 | this.setupForm(false); |
4320 | - Y.one('[id="field.security_related"]').simulate('click'); |
4321 | - var banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4322 | - Y.Assert.isNull(banner_hidden); |
4323 | - Y.one('[id="field.security_related"]').simulate('click'); |
4324 | - banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4325 | - Y.Assert.isNull(banner_hidden); |
4326 | - var banner_text = Y.one('.banner-text').get('text'); |
4327 | + Y.Assert.areEqual(1, private, 'Private is the default state.'); |
4328 | + |
4329 | + Y.one('[id="field.security_related"]').simulate('click'); |
4330 | + Y.Assert.areEqual(2, private, 'The first click fires ISPRIVATE'); |
4331 | + |
4332 | + Y.one('[id="field.security_related"]').simulate('click'); |
4333 | + Y.Assert.areEqual(1, public, 'The second click fires ISPUBLIC'); |
4334 | Y.Assert.areEqual( |
4335 | - 'This report will be private. ' + |
4336 | - 'You can disclose it later.', |
4337 | - banner_text); |
4338 | + 3, private, |
4339 | + "It also fires an ISPRIVATE since that's the default state."); |
4340 | }, |
4341 | |
4342 | // The dupe finder functionality is setup. |
4343 | @@ -280,44 +322,59 @@ |
4344 | // Selecting a private info type using the popup choice widget |
4345 | // turns on the privacy banner. |
4346 | test_select_private_info_type: function () { |
4347 | + var fired = false; |
4348 | + var ev = Y.on(info_type.EV_ISPRIVATE, function (ev) { |
4349 | + fired = true; |
4350 | + Y.Assert.areEqual( |
4351 | + 'This report contains Private information. ' + |
4352 | + 'You can change the information type later.', ev.text); |
4353 | + }); |
4354 | + |
4355 | this.setupForm(true); |
4356 | - var banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4357 | - Y.Assert.isNotNull(banner_hidden); |
4358 | + Y.Assert.isFalse(fired); |
4359 | + |
4360 | var information_type_popup = Y.one('.information_type-content a'); |
4361 | information_type_popup.simulate('click'); |
4362 | var information_type_choice = Y.one( |
4363 | '.yui3-ichoicelist-content a[href="#USERDATA"]'); |
4364 | information_type_choice.simulate('click'); |
4365 | - banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4366 | - Y.Assert.isNull(banner_hidden); |
4367 | - var banner_text = Y.one('.banner-text').get('text'); |
4368 | - Y.Assert.areEqual( |
4369 | - 'This report contains Private information. ' + |
4370 | - 'You can change the information type later.', banner_text); |
4371 | + |
4372 | + // And the event should be fired and caught. |
4373 | + Y.Assert.isTrue(fired); |
4374 | + ev.detach(); |
4375 | }, |
4376 | |
4377 | // Selecting a public info type using the popup choice widget |
4378 | // turns off the privacy banner. |
4379 | test_select_public_info_type: function () { |
4380 | + var fired = false; |
4381 | + var ev = Y.on(info_type.EV_ISPUBLIC, function (ev) { |
4382 | + fired = true; |
4383 | + }); |
4384 | + |
4385 | window.LP.cache.bug_private_by_default = true; |
4386 | this.setupForm(true); |
4387 | + |
4388 | + // This will fire ISPRIVATE and a banner shows. |
4389 | var information_type_popup = Y.one('.information_type-content a'); |
4390 | information_type_popup.simulate('click'); |
4391 | var information_type_choice = Y.one( |
4392 | '.yui3-ichoicelist-content a[href="#USERDATA"]'); |
4393 | information_type_choice.simulate('click'); |
4394 | - var banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4395 | - Y.Assert.isNull(banner_hidden); |
4396 | + |
4397 | + // The second one will fire ISPUBLIC and the banner disappears. |
4398 | information_type_popup.simulate('click'); |
4399 | information_type_choice = Y.one( |
4400 | '.yui3-ichoicelist-content a[href="#PUBLIC"]'); |
4401 | information_type_choice.simulate('click'); |
4402 | - banner_hidden = Y.one('.yui3-privacybanner-hidden'); |
4403 | - Y.Assert.isNotNull(banner_hidden); |
4404 | + |
4405 | + Y.Assert.isTrue(fired); |
4406 | } |
4407 | })); |
4408 | |
4409 | -}, '0.1', {'requires': ['test', 'test-console', 'event', 'node-event-simulate', |
4410 | - 'lp.app.banner.privacy', 'lp.app.choice', |
4411 | - 'lp.bugs.filebug_dupefinder', 'lp.bugs.filebug' |
4412 | - ]}); |
4413 | +}, '0.1', { |
4414 | + requires: [ |
4415 | + 'test', 'test-console', 'event', 'node-event-simulate', |
4416 | + 'lp.app.banner.privacy', 'lp.app.choice', 'lp.app.information_type', |
4417 | + 'lp.bugs.filebug_dupefinder', 'lp.bugs.filebug' ] |
4418 | +}); |
4419 | |
4420 | === modified file 'lib/lp/code/javascript/branch.information_type_choice.js' |
4421 | --- lib/lp/code/javascript/branch.information_type_choice.js 2012-09-21 15:39:22 +0000 |
4422 | +++ lib/lp/code/javascript/branch.information_type_choice.js 2012-11-12 13:21:28 +0000 |
4423 | @@ -105,7 +105,9 @@ |
4424 | LP.cache.context.information_type = |
4425 | information_type.get_cache_data_from_key( |
4426 | value, 'value', 'name'); |
4427 | - information_type.update_privacy_banner(value); |
4428 | + Y.fire(information_type.EV_CHANGE, { |
4429 | + value: value |
4430 | + }); |
4431 | if (this.get('use_animation')) { |
4432 | this.information_type_edit._showSucceeded(); |
4433 | } |
4434 | @@ -119,7 +121,8 @@ |
4435 | } |
4436 | }); |
4437 | |
4438 | -}, "0.1", {"requires": ["base", "oop", "node", "event", "io-base", |
4439 | - "lp.ui.choiceedit", "lp.app.banner.privacy", |
4440 | - "lp.app.errors", "lp.app.choice", |
4441 | - "lp.app.information_type"]}); |
4442 | +}, "0.1", { |
4443 | + requires: [ |
4444 | + "base", "oop", "node", "event", "io-base", "lp.ui.choiceedit", |
4445 | + "lp.app.errors", "lp.app.choice", "lp.app.information_type"] |
4446 | +}); |
4447 | |
4448 | === modified file 'lib/lp/code/javascript/tests/test_information_type_choice.js' |
4449 | --- lib/lp/code/javascript/tests/test_information_type_choice.js 2012-10-26 10:00:20 +0000 |
4450 | +++ lib/lp/code/javascript/tests/test_information_type_choice.js 2012-11-12 13:21:28 +0000 |
4451 | @@ -4,6 +4,8 @@ |
4452 | |
4453 | var tests = Y.namespace('lp.code.branch.information_type_choice.test'); |
4454 | var ns = Y.lp.code.branch.information_type_choice; |
4455 | + var info_type = Y.lp.app.information_type; |
4456 | + |
4457 | tests.suite = new Y.Test.Suite( |
4458 | 'lp.code.branch.information_type_choice Tests'); |
4459 | |
4460 | @@ -62,22 +64,6 @@ |
4461 | this.widget.render(); |
4462 | }, |
4463 | |
4464 | - _shim_privacy_banner: function () { |
4465 | - var old_func = Y.lp.app.banner.privacy.getPrivacyBanner; |
4466 | - Y.lp.app.banner.privacy.getPrivacyBanner = function () { |
4467 | - return { |
4468 | - show: function () { Y.fire('test:banner:show'); }, |
4469 | - hide: function () { Y.fire('test:banner:hide'); }, |
4470 | - updateText: function () { Y.fire('test:banner:update'); } |
4471 | - }; |
4472 | - }; |
4473 | - return old_func; |
4474 | - }, |
4475 | - |
4476 | - _unshim_privacy_banner: function (old_func) { |
4477 | - Y.lp.app.banner.privacy.getPrivacyBanner = old_func; |
4478 | - }, |
4479 | - |
4480 | test_library_exists: function () { |
4481 | Y.Assert.isObject(Y.lp.code.branch.information_type_choice, |
4482 | "Cannot locate the " + |
4483 | @@ -118,44 +104,31 @@ |
4484 | |
4485 | // Setting a private type shows the privacy banner. |
4486 | test_information_type_save_success_private: function() { |
4487 | + var fired = false; |
4488 | + Y.on(info_type.EV_ISPRIVATE, function (ev) { |
4489 | + fired = true; |
4490 | + }); |
4491 | + |
4492 | this.makeWidget(); |
4493 | - var old_func = this._shim_privacy_banner(); |
4494 | - var hide_flag = false; |
4495 | - var update_flag = false; |
4496 | - Y.on('test:banner:show', function() { |
4497 | - hide_flag = true; |
4498 | - }); |
4499 | - Y.on('test:banner:update', function() { |
4500 | - update_flag = true; |
4501 | - }); |
4502 | |
4503 | this.widget._information_type_save_success('PROPRIETARY'); |
4504 | - var body = Y.one('body'); |
4505 | - Y.Assert.isTrue(body.hasClass('private')); |
4506 | - Y.Assert.isTrue(hide_flag); |
4507 | - Y.Assert.isTrue(update_flag); |
4508 | + Y.Assert.isTrue(fired); |
4509 | Y.Assert.areEqual( |
4510 | 'Proprietary', LP.cache.context.information_type); |
4511 | - this._unshim_privacy_banner(old_func); |
4512 | }, |
4513 | |
4514 | // Setting a private type hides the privacy banner. |
4515 | test_information_type_save_success_public: function() { |
4516 | + var fired = false; |
4517 | + Y.on(info_type.EV_ISPUBLIC, function (ev) { |
4518 | + fired = true; |
4519 | + }); |
4520 | + |
4521 | this.makeWidget(); |
4522 | - var old_func = this._shim_privacy_banner(); |
4523 | - var flag = false; |
4524 | - Y.on('test:banner:hide', function() { |
4525 | - flag = true; |
4526 | - }); |
4527 | - var summary = Y.one('#information-type-summary'); |
4528 | - summary.replaceClass('public', 'private'); |
4529 | |
4530 | this.widget._information_type_save_success('PUBLIC'); |
4531 | - var body = Y.one('body'); |
4532 | - Y.Assert.isTrue(body.hasClass('public')); |
4533 | - Y.Assert.isTrue(flag); |
4534 | + Y.Assert.isTrue(fired); |
4535 | Y.Assert.areEqual('Public', LP.cache.context.information_type); |
4536 | - this._unshim_privacy_banner(old_func); |
4537 | }, |
4538 | |
4539 | // Test error handling when a save fails. |
4540 | |
4541 | === modified file 'lib/lp/registry/browser/product.py' |
4542 | --- lib/lp/registry/browser/product.py 2012-10-26 15:11:20 +0000 |
4543 | +++ lib/lp/registry/browser/product.py 2012-11-12 13:21:28 +0000 |
4544 | @@ -1905,6 +1905,7 @@ |
4545 | |
4546 | class ProjectAddStepTwo(StepView, ProductLicenseMixin, ReturnToReferrerMixin): |
4547 | """Step 2 (of 2) in the +new project add wizard.""" |
4548 | + related_features = [PRIVATE_PROJECTS_FLAG] |
4549 | |
4550 | _field_names = ['displayname', 'name', 'title', 'summary', 'description', |
4551 | 'homepageurl', 'information_type', 'licenses', |
4552 | |
4553 | === modified file 'lib/lp/registry/configure.zcml' |
4554 | --- lib/lp/registry/configure.zcml 2012-11-11 23:39:34 +0000 |
4555 | +++ lib/lp/registry/configure.zcml 2012-11-12 13:21:28 +0000 |
4556 | @@ -1356,6 +1356,25 @@ |
4557 | set_schema="lp.registry.interfaces.product.IProductModerateRestricted" |
4558 | set_attributes="active"/> |
4559 | |
4560 | + <!-- IBugTarget --> |
4561 | + |
4562 | + <require |
4563 | + permission="launchpad.LimitedView" |
4564 | + attributes=" |
4565 | + bugtargetdisplayname"/> |
4566 | + |
4567 | + <require |
4568 | + permission="launchpad.View" |
4569 | + attributes=" |
4570 | + bug_reported_acknowledgement |
4571 | + bug_reporting_guidelines |
4572 | + bugtargetname |
4573 | + createBug |
4574 | + enable_bugfiling_duplicate_search |
4575 | + getBugTaskWeightFunction |
4576 | + pillar |
4577 | + searchTasks"/> |
4578 | + |
4579 | <!-- IHasAliases --> |
4580 | |
4581 | <require |
4582 | @@ -1391,8 +1410,19 @@ |
4583 | <!-- IStructuralSubscriptionTarget --> |
4584 | |
4585 | <require |
4586 | + permission="launchpad.LimitedView" |
4587 | + attributes=" |
4588 | + parent_subscription_target" /> |
4589 | + <require |
4590 | permission="launchpad.View" |
4591 | - interface="lp.bugs.interfaces.structuralsubscription.IStructuralSubscriptionTargetRead" /> |
4592 | + attributes=" |
4593 | + bug_subscriptions |
4594 | + getSubscription |
4595 | + getSubscriptions |
4596 | + target_type_display |
4597 | + userCanAlterBugSubscription |
4598 | + userCanAlterSubscription |
4599 | + userHasBugSubscriptions" /> |
4600 | <require |
4601 | permission="launchpad.AnyAllowedPerson" |
4602 | interface="lp.bugs.interfaces.structuralsubscription.IStructuralSubscriptionTargetWrite" /> |
4603 | |
4604 | === modified file 'lib/lp/registry/interfaces/product.py' |
4605 | --- lib/lp/registry/interfaces/product.py 2012-11-11 23:39:34 +0000 |
4606 | +++ lib/lp/registry/interfaces/product.py 2012-11-12 13:21:28 +0000 |
4607 | @@ -89,7 +89,6 @@ |
4608 | from lp.blueprints.interfaces.sprint import IHasSprints |
4609 | from lp.bugs.interfaces.bugsupervisor import IHasBugSupervisor |
4610 | from lp.bugs.interfaces.bugtarget import ( |
4611 | - IBugTarget, |
4612 | IHasExpirableBugs, |
4613 | IOfficialBugTagTargetPublic, |
4614 | IOfficialBugTagTargetRestricted, |
4615 | @@ -428,11 +427,27 @@ |
4616 | """True if the given user has access to this product.""" |
4617 | |
4618 | |
4619 | -class IProductLimitedView(Interface): |
4620 | +class IProductLimitedView(IHasLogo, IHasOwner, ILaunchpadUsage): |
4621 | """Attributes that must be visible for person with artifact grants |
4622 | on bugs, branches or specifications for the product. |
4623 | """ |
4624 | |
4625 | + displayname = exported( |
4626 | + TextLine( |
4627 | + title=_('Display Name'), |
4628 | + description=_("""The name of the project as it would appear in a |
4629 | + paragraph.""")), |
4630 | + exported_as='display_name') |
4631 | + |
4632 | + logo = exported( |
4633 | + LogoImageUpload( |
4634 | + title=_("Logo"), required=False, |
4635 | + default_image_resource='/@@/product-logo', |
4636 | + description=_( |
4637 | + "An image of exactly 64x64 pixels that will be displayed in " |
4638 | + "the heading of all pages related to this project. It should " |
4639 | + "be no bigger than 50kb in size."))) |
4640 | + |
4641 | name = exported( |
4642 | ProductNameField( |
4643 | title=_('Name'), |
4644 | @@ -442,16 +457,14 @@ |
4645 | "letters, numbers, dots, hyphens or pluses. " |
4646 | "Keep this name short; it is used in URLs as shown above."))) |
4647 | |
4648 | - |
4649 | -class IProductView( |
4650 | - IBugTarget, ICanGetMilestonesDirectly, IHasAppointedDriver, IHasBranches, |
4651 | - IHasDrivers, IHasExternalBugTracker, IHasIcon, |
4652 | - IHasLogo, IHasMergeProposals, IHasMilestones, IHasExpirableBugs, |
4653 | - IHasMugshot, IHasOwner, IHasSprints, IHasTranslationImports, |
4654 | - ITranslationPolicy, IKarmaContext, ILaunchpadUsage, IMakesAnnouncements, |
4655 | - IOfficialBugTagTargetPublic, IHasOOPSReferences, |
4656 | - ISpecificationTarget, IHasRecipes, IHasCodeImports, IServiceUsage): |
4657 | - """Public IProduct properties.""" |
4658 | + owner = exported( |
4659 | + PersonChoice( |
4660 | + title=_('Maintainer'), |
4661 | + required=True, |
4662 | + vocabulary='ValidPillarOwner', |
4663 | + description=_("The restricted team, moderated team, or person " |
4664 | + "who maintains the project information in " |
4665 | + "Launchpad."))) |
4666 | |
4667 | project = exported( |
4668 | ReferenceChoice( |
4669 | @@ -469,14 +482,21 @@ |
4670 | 'and security policy will apply to this project.')), |
4671 | exported_as='project_group') |
4672 | |
4673 | - owner = exported( |
4674 | - PersonChoice( |
4675 | - title=_('Maintainer'), |
4676 | - required=True, |
4677 | - vocabulary='ValidPillarOwner', |
4678 | - description=_("The restricted team, moderated team, or person " |
4679 | - "who maintains the project information in " |
4680 | - "Launchpad."))) |
4681 | + title = exported( |
4682 | + Title( |
4683 | + title=_('Title'), |
4684 | + description=_("The project title. Should be just a few words."))) |
4685 | + |
4686 | + |
4687 | +class IProductView( |
4688 | + ICanGetMilestonesDirectly, IHasAppointedDriver, IHasBranches, |
4689 | + IHasDrivers, IHasExternalBugTracker, IHasIcon, |
4690 | + IHasMergeProposals, IHasMilestones, IHasExpirableBugs, |
4691 | + IHasMugshot, IHasSprints, IHasTranslationImports, |
4692 | + ITranslationPolicy, IKarmaContext, IMakesAnnouncements, |
4693 | + IOfficialBugTagTargetPublic, IHasOOPSReferences, |
4694 | + ISpecificationTarget, IHasRecipes, IHasCodeImports, IServiceUsage): |
4695 | + """Public IProduct properties.""" |
4696 | |
4697 | registrant = exported( |
4698 | PublicPersonChoice( |
4699 | @@ -503,18 +523,6 @@ |
4700 | "required because there might be a project driver and also a " |
4701 | "driver appointed in the overarching project group.") |
4702 | |
4703 | - displayname = exported( |
4704 | - TextLine( |
4705 | - title=_('Display Name'), |
4706 | - description=_("""The name of the project as it would appear in a |
4707 | - paragraph.""")), |
4708 | - exported_as='display_name') |
4709 | - |
4710 | - title = exported( |
4711 | - Title( |
4712 | - title=_('Title'), |
4713 | - description=_("The project title. Should be just a few words."))) |
4714 | - |
4715 | summary = exported( |
4716 | Summary( |
4717 | title=_('Summary'), |
4718 | @@ -614,15 +622,6 @@ |
4719 | "will be displayed next to the project name everywhere in " |
4720 | "Launchpad that we refer to the project and link to it."))) |
4721 | |
4722 | - logo = exported( |
4723 | - LogoImageUpload( |
4724 | - title=_("Logo"), required=False, |
4725 | - default_image_resource='/@@/product-logo', |
4726 | - description=_( |
4727 | - "An image of exactly 64x64 pixels that will be displayed in " |
4728 | - "the heading of all pages related to this project. It should " |
4729 | - "be no bigger than 50kb in size."))) |
4730 | - |
4731 | mugshot = exported( |
4732 | MugshotImageUpload( |
4733 | title=_("Brand"), required=False, |
4734 | |
4735 | === modified file 'lib/lp/registry/javascript/product_views.js' |
4736 | --- lib/lp/registry/javascript/product_views.js 2012-10-26 06:59:14 +0000 |
4737 | +++ lib/lp/registry/javascript/product_views.js 2012-11-12 13:21:28 +0000 |
4738 | @@ -95,6 +95,9 @@ |
4739 | */ |
4740 | information_type_change: function (value) { |
4741 | toggle_license_field(value); |
4742 | + Y.fire(info_type.EV_CHANGE, { |
4743 | + value: value |
4744 | + }); |
4745 | }, |
4746 | |
4747 | /** |
4748 | @@ -349,6 +352,9 @@ |
4749 | */ |
4750 | information_type_change: function (value) { |
4751 | toggle_license_field(value); |
4752 | + Y.fire(info_type.EV_CHANGE, { |
4753 | + value: value |
4754 | + }); |
4755 | var driver_cont = |
4756 | Y.one('input[name="field.driver"]').ancestor('td'); |
4757 | var bug_super_cont = |
4758 | |
4759 | === modified file 'lib/lp/registry/model/product.py' |
4760 | --- lib/lp/registry/model/product.py 2012-11-11 23:39:34 +0000 |
4761 | +++ lib/lp/registry/model/product.py 2012-11-12 13:21:28 +0000 |
4762 | @@ -109,6 +109,7 @@ |
4763 | from lp.bugs.interfaces.bugtarget import ( |
4764 | BUG_POLICY_ALLOWED_TYPES, |
4765 | BUG_POLICY_DEFAULT_TYPES, |
4766 | + IBugTarget, |
4767 | ) |
4768 | from lp.bugs.interfaces.bugtaskfilter import OrderedBugTask |
4769 | from lp.bugs.model.bugtarget import ( |
4770 | @@ -345,7 +346,7 @@ |
4771 | """A Product.""" |
4772 | |
4773 | implements( |
4774 | - IBugSummaryDimension, IFAQTarget, IHasBugSupervisor, |
4775 | + IBugSummaryDimension, IBugTarget, IFAQTarget, IHasBugSupervisor, |
4776 | IHasCustomLanguageCodes, IHasIcon, IHasLogo, IHasMugshot, |
4777 | IHasOOPSReferences, ILaunchpadUsage, IProduct, IServiceUsage) |
4778 | |
4779 | |
4780 | === modified file 'lib/lp/registry/tests/test_product.py' |
4781 | --- lib/lp/registry/tests/test_product.py 2012-11-11 23:39:34 +0000 |
4782 | +++ lib/lp/registry/tests/test_product.py 2012-11-12 13:21:28 +0000 |
4783 | @@ -551,7 +551,11 @@ |
4784 | CheckerPublic: set(( |
4785 | 'active', 'id', 'information_type', 'pillar_category', 'private', |
4786 | 'userCanView',)), |
4787 | - 'launchpad.LimitedView': set(('name', )), |
4788 | + 'launchpad.LimitedView': set(( |
4789 | + 'bugtargetdisplayname', 'displayname', 'enable_bug_expiration', |
4790 | + 'logo', 'name', 'official_answers', 'official_anything', |
4791 | + 'official_blueprints', 'official_codehosting', 'official_malone', |
4792 | + 'owner', 'parent_subscription_target', 'project', 'title', )), |
4793 | 'launchpad.View': set(( |
4794 | '_getOfficialTagClause', '_all_specifications', |
4795 | '_valid_specifications', 'active_or_packaged_series', |
4796 | @@ -561,16 +565,15 @@ |
4797 | 'blueprints_usage', 'branch_sharing_policy', |
4798 | 'bug_reported_acknowledgement', 'bug_reporting_guidelines', |
4799 | 'bug_sharing_policy', 'bug_subscriptions', 'bug_supervisor', |
4800 | - 'bug_tracking_usage', 'bugtargetdisplayname', 'bugtargetname', |
4801 | - 'bugtracker', 'canUserAlterAnswerContact', |
4802 | - 'codehosting_usage', |
4803 | + 'bug_tracking_usage', 'bugtargetname', |
4804 | + 'bugtracker', 'canUserAlterAnswerContact', 'codehosting_usage', |
4805 | 'coming_sprints', 'commercial_subscription', |
4806 | 'commercial_subscription_is_due', 'createBug', |
4807 | 'createCustomLanguageCode', 'custom_language_codes', |
4808 | 'date_next_suggest_packaging', 'datecreated', 'description', |
4809 | 'development_focus', 'development_focusID', |
4810 | - 'direct_answer_contacts', 'displayname', 'distrosourcepackages', |
4811 | - 'downloadurl', 'driver', 'drivers', 'enable_bug_expiration', |
4812 | + 'direct_answer_contacts', 'distrosourcepackages', |
4813 | + 'downloadurl', 'driver', 'drivers', |
4814 | 'enable_bugfiling_duplicate_search', 'findReferencedOOPS', |
4815 | 'findSimilarFAQs', 'findSimilarQuestions', 'freshmeatproject', |
4816 | 'getAllowedBugInformationTypes', |
4817 | @@ -594,15 +597,13 @@ |
4818 | 'has_custom_language_codes', 'has_milestones', 'homepage_content', |
4819 | 'homepageurl', 'icon', 'invitesTranslationEdits', |
4820 | 'invitesTranslationSuggestions', |
4821 | - 'license_info', 'license_status', 'licenses', 'logo', 'milestones', |
4822 | + 'license_info', 'license_status', 'licenses', 'milestones', |
4823 | 'mugshot', 'name_with_project', 'newCodeImport', |
4824 | - 'obsolete_translatable_series', 'official_answers', |
4825 | - 'official_anything', 'official_blueprints', 'official_bug_tags', |
4826 | - 'official_codehosting', 'official_malone', 'owner', |
4827 | - 'parent_subscription_target', 'packagedInDistros', 'packagings', |
4828 | + 'obsolete_translatable_series', 'official_bug_tags', |
4829 | + 'packagedInDistros', 'packagings', |
4830 | 'past_sprints', 'personHasDriverRights', 'pillar', |
4831 | 'primary_translatable', 'private_bugs', |
4832 | - 'programminglang', 'project', 'qualifies_for_free_hosting', |
4833 | + 'programminglang', 'qualifies_for_free_hosting', |
4834 | 'recipes', 'redeemSubscriptionVoucher', 'registrant', 'releases', |
4835 | 'remote_product', 'removeCustomLanguageCode', |
4836 | 'screenshotsurl', |
4837 | @@ -610,7 +611,7 @@ |
4838 | 'series', |
4839 | 'sharesTranslationsWithOtherSide', 'sourceforgeproject', |
4840 | 'sourcepackages', 'specification_sharing_policy', 'specifications', |
4841 | - 'sprints', 'summary', 'target_type_display', 'title', |
4842 | + 'sprints', 'summary', 'target_type_display', |
4843 | 'translatable_packages', 'translatable_series', |
4844 | 'translation_focus', 'translationgroup', 'translationgroups', |
4845 | 'translationpermission', 'translations_usage', 'ubuntu_packages', |
4846 | |
4847 | === modified file 'lib/lp/services/features/flags.py' |
4848 | --- lib/lp/services/features/flags.py 2012-11-08 06:06:22 +0000 |
4849 | +++ lib/lp/services/features/flags.py 2012-11-12 13:21:28 +0000 |
4850 | @@ -236,7 +236,7 @@ |
4851 | 'boolean', |
4852 | 'If true, enabled access to private project registration features.', |
4853 | 'disabled', |
4854 | - '', |
4855 | + 'Allow registering a non-public project.', |
4856 | 'http://blog.launchpad.net/general/private-projects-beta'), |
4857 | ('disclosure.private_project.traversal_override', |
4858 | 'boolean', |