Merge lp:~jcsackett/juju-gui/search-fixes into lp:juju-gui/experimental
- search-fixes
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 607 |
Proposed branch: | lp:~jcsackett/juju-gui/search-fixes |
Merge into: | lp:juju-gui/experimental |
Diff against target: |
739 lines (+271/-131) 6 files modified
app/subapps/browser/browser.js (+135/-122) app/subapps/browser/views/editorial.js (+4/-7) app/subapps/browser/views/search.js (+48/-0) test/test_browser_app.js (+60/-0) test/test_browser_editorial.js (+0/-2) test/test_browser_search_view.js (+24/-0) |
To merge this branch: | bzr merge lp:~jcsackett/juju-gui/search-fixes |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju GUI Hackers | Pending | ||
Review via email: mp+160706@code.launchpad.net |
Commit message
Description of the change
Fixes several problems with search
-Querystring was eaten on viewmode changes or when a search url was pasted
into browser.
-Editorial and Search could have collisions in fullscreen.
-Charm add button didn't work on search results charm tokens.
Note: this reproduced (and now has merged) work in https:/
j.c.sackett (jcsackett) wrote : | # |
j.c.sackett (jcsackett) wrote : | # |
Please take a look.
Jeff Pihach (hatch) wrote : | # |
LGTM thanks, with trivial
https:/
File app/subapps/
https:/
app/subapps/
We decided against the *'s in a Friday call.
https:/
File test/test_
https:/
test/test_
function() {
non descriptive test name.
Madison Scott-Clary (makyo) wrote : | # |
LGTM with little comment change. Thanks for the branch.
https:/
File app/subapps/
https:/
app/subapps/
hide the div for
Minor:
// If there are no details in the route, then hide the div for
- 591. By j.c.sackett
-
Comments conform.
- 592. By j.c.sackett
-
Comment typo fixed.
- 593. By j.c.sackett
-
More descriptive test name.
j.c.sackett (jcsackett) wrote : | # |
*** Submitted:
Fixes several problems with search
-Querystring was eaten on viewmode changes or when a search url was
pasted
into browser.
-Editorial and Search could have collisions in fullscreen.
-Charm add button didn't work on search results charm tokens.
Note: this reproduced (and now has merged) work in
https:/
R=jeff.pihach, matthew.scott
CC=
https:/
Preview Diff
1 | === modified file 'app/subapps/browser/browser.js' |
2 | --- app/subapps/browser/browser.js 2013-04-23 16:20:42 +0000 |
3 | +++ app/subapps/browser/browser.js 2013-04-24 18:15:32 +0000 |
4 | @@ -2,22 +2,20 @@ |
5 | |
6 | |
7 | /** |
8 | - * SubApp for the Browser |
9 | - * |
10 | - * @module juju |
11 | - * @submodule subapps |
12 | - * |
13 | + SubApp for the Browser |
14 | + |
15 | + @module juju |
16 | + @submodule subapps |
17 | */ |
18 | YUI.add('subapp-browser', function(Y) { |
19 | var ns = Y.namespace('juju.subapps'), |
20 | models = Y.namespace('juju.models'); |
21 | |
22 | /** |
23 | - * Browser Sub App for the Juju Gui. |
24 | - * |
25 | - * @class Browser |
26 | - * @extends {juju.SubApp} |
27 | - * |
28 | + Browser Sub App for the Juju Gui. |
29 | + |
30 | + @class Browser |
31 | + @extends {juju.SubApp} |
32 | */ |
33 | ns.Browser = Y.Base.create('subapp-browser', Y.juju.SubApp, [], { |
34 | /** |
35 | @@ -25,7 +23,6 @@ |
36 | |
37 | @method _detailsVisible |
38 | @param {Boolean} visible set the panel to hide or show. |
39 | - |
40 | */ |
41 | _detailsVisible: function(visible) { |
42 | var detailsNode = Y.one('.bws-view-data'); |
43 | @@ -45,7 +42,6 @@ |
44 | |
45 | @method _getStateUrl |
46 | @param {Object} change the values to change in the current state. |
47 | - |
48 | */ |
49 | _getStateUrl: function(change) { |
50 | var urlParts = ['/bws']; |
51 | @@ -70,12 +66,11 @@ |
52 | }, |
53 | |
54 | /** |
55 | - * Generate a standard shared set of cfg all Views can expect to see. |
56 | - * |
57 | - * @method _getViewCfg |
58 | - * @param {Object} cfg additional config to merge into the default view |
59 | - * config. |
60 | - * |
61 | + Generate a standard shared set of cfg all Views can expect to see. |
62 | + |
63 | + @method _getViewCfg |
64 | + @param {Object} cfg additional config to merge into the default view |
65 | + config. |
66 | */ |
67 | _getViewCfg: function(cfg) { |
68 | return Y.merge(cfg, { |
69 | @@ -88,24 +83,23 @@ |
70 | Create an initial subapp state for later url generation. |
71 | |
72 | @method _initState |
73 | - |
74 | */ |
75 | _initState: function() { |
76 | this._oldState = { |
77 | - viewmode: null, |
78 | + charmID: null, |
79 | + querystring: null, |
80 | search: null, |
81 | - charmID: null |
82 | + viewmode: null |
83 | }; |
84 | this._viewState = Y.merge(this._oldState, {}); |
85 | }, |
86 | |
87 | /** |
88 | - Determine if we should render the charm details based on the current |
89 | - state. |
90 | - |
91 | - @return {Boolean} true if should show. |
92 | - |
93 | - */ |
94 | + Determine if we should render the charm details based on the current |
95 | + state. |
96 | + |
97 | + @return {Boolean} true if should show. |
98 | + */ |
99 | _shouldShowCharm: function() { |
100 | if ( |
101 | this._viewState.charmID && |
102 | @@ -121,12 +115,11 @@ |
103 | }, |
104 | |
105 | /** |
106 | - Determine if we should render the editorial content based on the current |
107 | - state. |
108 | - |
109 | - @return {Boolean} true if should show. |
110 | - |
111 | - */ |
112 | + Determine if we should render the editorial content based on the current |
113 | + state. |
114 | + |
115 | + @return {Boolean} true if should show. |
116 | + */ |
117 | _shouldShowEditorial: function() { |
118 | if ( |
119 | !this._viewState.search && |
120 | @@ -139,19 +132,19 @@ |
121 | }, |
122 | |
123 | /** |
124 | - Determine if we should render the search results based on the current |
125 | - state. |
126 | - |
127 | - @return {Boolean} true if should show. |
128 | - |
129 | - */ |
130 | + Determine if we should render the search results based on the current |
131 | + state. |
132 | + |
133 | + @return {Boolean} true if should show. |
134 | + */ |
135 | _shouldShowSearch: function() { |
136 | if ( |
137 | this._viewState.search && |
138 | ( |
139 | this._hasStateChanged('search') || |
140 | this._hasStateChanged('viewmode') || |
141 | - this._hasStateChanged('querystring') |
142 | + this._hasStateChanged('querystring') || |
143 | + (this._hasStateChanged('charmID') && !this._viewState.charmID) |
144 | ) |
145 | ) { |
146 | return true; |
147 | @@ -161,11 +154,10 @@ |
148 | }, |
149 | |
150 | /** |
151 | - Verify that a particular part of the state has changed. |
152 | - |
153 | - @method _hasStateChanged |
154 | - @param {String} field the part of the state to check. |
155 | - |
156 | + Verify that a particular part of the state has changed. |
157 | + |
158 | + @method _hasStateChanged |
159 | + @param {String} field the part of the state to check. |
160 | */ |
161 | _hasStateChanged: function(field) { |
162 | if (this._oldState[field] === this._viewState[field]) { |
163 | @@ -176,11 +168,10 @@ |
164 | }, |
165 | |
166 | /** |
167 | - Update the oldState with the viewState now that we're done processing |
168 | - the request. |
169 | - |
170 | - @method _saveState |
171 | - |
172 | + Update the oldState with the viewState now that we're done processing |
173 | + the request. |
174 | + |
175 | + @method _saveState |
176 | */ |
177 | _saveState: function() { |
178 | this._oldState = Y.merge( |
179 | @@ -193,17 +184,21 @@ |
180 | be. |
181 | |
182 | @method _updateState |
183 | - @param {String} path the requested path. |
184 | - @param {Object} params the params from the request payload. |
185 | - |
186 | + @param {Object} req the request payload. |
187 | */ |
188 | - _updateState: function(path, params) { |
189 | + _updateState: function(req) { |
190 | // Update the viewmode. Every request has a viewmode. |
191 | + var path = req.path, |
192 | + params = req.params, |
193 | + query = req.query; |
194 | + |
195 | this._viewState.viewmode = params.viewmode; |
196 | |
197 | // Check for a charm id in the request. |
198 | if (params.id && params.id !== 'search') { |
199 | - this._viewState.charmID = params.id; |
200 | + // Make sure we clear out any accidental matching of search/ in the |
201 | + // url. |
202 | + this._viewState.charmID = params.id.replace(/^search\//, ''); |
203 | } else { |
204 | this._viewState.charmID = null; |
205 | } |
206 | @@ -214,12 +209,19 @@ |
207 | } else { |
208 | this._viewState.search = false; |
209 | } |
210 | + |
211 | + // Check if there's a query string to set. |
212 | + if (query) { |
213 | + // Store it as a straight string. |
214 | + this._viewState.querystring = Y.QueryString.stringify(query); |
215 | + } else { |
216 | + this._viewState.querystring = null; |
217 | + } |
218 | }, |
219 | |
220 | /** |
221 | - * The available Views run from this sub app. |
222 | - * @attribute views |
223 | - * |
224 | + The available Views run from this sub app. |
225 | + @attribute views |
226 | */ |
227 | views: { |
228 | fullscreen: { |
229 | @@ -236,7 +238,6 @@ |
230 | Cleanup after ourselves on destroy. |
231 | |
232 | @method destructor |
233 | - |
234 | */ |
235 | destructor: function() { |
236 | this._cacheCharms.destroy(); |
237 | @@ -244,11 +245,10 @@ |
238 | }, |
239 | |
240 | /** |
241 | - * General app initializer |
242 | - * |
243 | - * @method initializer |
244 | - * @param {Object} cfg general init config object. |
245 | - * |
246 | + General app initializer |
247 | + |
248 | + @method initializer |
249 | + @param {Object} cfg general init config object. |
250 | */ |
251 | initializer: function(cfg) { |
252 | // Hold onto charm data so we can pass model instances to other views when |
253 | @@ -269,16 +269,15 @@ |
254 | }, |
255 | |
256 | /** |
257 | - * Render the charm details view |
258 | - * |
259 | - * @method renderCharmDetails |
260 | - * @param {Request} req current request object. |
261 | - * @param {Response} res current response object. |
262 | - * @param {function} next callable for the next route in the chain. |
263 | - * |
264 | + Render the charm details view |
265 | + |
266 | + @method renderCharmDetails |
267 | + @param {Request} req current request object. |
268 | + @param {Response} res current response object. |
269 | + @param {function} next callable for the next route in the chain. |
270 | */ |
271 | renderCharmDetails: function(req, res, next) { |
272 | - var charmID = req.params.id; |
273 | + var charmID = this._viewState.charmID; |
274 | var extraCfg = { |
275 | charmID: charmID, |
276 | container: Y.Node.create('<div class="charmview"/>'), |
277 | @@ -305,16 +304,15 @@ |
278 | }, |
279 | |
280 | /** |
281 | - Render editorial content into the parent view when required. |
282 | - |
283 | - The parent view is either fullscreen/sidebar which determines how the |
284 | - editorial content is to be rendered. |
285 | - |
286 | - @method renderEditorial |
287 | - @param {Request} req current request object. |
288 | - @param {Response} res current response object. |
289 | - @param {function} next callable for the next route in the chain. |
290 | - |
291 | + Render editorial content into the parent view when required. |
292 | + |
293 | + The parent view is either fullscreen/sidebar which determines how the |
294 | + editorial content is to be rendered. |
295 | + |
296 | + @method renderEditorial |
297 | + @param {Request} req current request object. |
298 | + @param {Response} res current response object. |
299 | + @param {function} next callable for the next route in the chain. |
300 | */ |
301 | renderEditorial: function(req, res, next) { |
302 | // If loading the interesting content then it's not a search going on. |
303 | @@ -353,19 +351,19 @@ |
304 | }, |
305 | |
306 | /** |
307 | - * Render search results |
308 | - * |
309 | - * @method renderSearchResults |
310 | - * @param {Request} req current request object. |
311 | - * @param {Response} res current response object. |
312 | - * @param {function} next callable for the next route in the chain. |
313 | + Render search results |
314 | + |
315 | + @method renderSearchResults |
316 | + @param {Request} req current request object. |
317 | + @param {Response} res current response object. |
318 | + @param {function} next callable for the next route in the chain. |
319 | */ |
320 | renderSearchResults: function(req, res, next) { |
321 | var container = this.get('container'), |
322 | extraCfg = {}, |
323 | query; |
324 | - if (this._viewState.querystring) { |
325 | - query = Y.QueryString.parse(this._viewState.querystring); |
326 | + if (req.query) { |
327 | + query = req.query; |
328 | } else { |
329 | // If there's no querystring, we need a default "empty" search. |
330 | query = {text: ''}; |
331 | @@ -385,13 +383,12 @@ |
332 | }, |
333 | |
334 | /** |
335 | - * Render the fullscreen view to the client. |
336 | - * |
337 | - * @method fullscreen |
338 | - * @param {Request} req current request object. |
339 | - * @param {Response} res current response object. |
340 | - * @param {function} next callable for the next route in the chain. |
341 | - * |
342 | + Render the fullscreen view to the client. |
343 | + |
344 | + @method fullscreen |
345 | + @param {Request} req current request object. |
346 | + @param {Response} res current response object. |
347 | + @param {function} next callable for the next route in the chain. |
348 | */ |
349 | fullscreen: function(req, res, next) { |
350 | // If we've switched to viewmode fullscreen, we need to render it. |
351 | @@ -402,6 +399,20 @@ |
352 | this._fullscreen = this.showView('fullscreen', this._getViewCfg()); |
353 | } |
354 | |
355 | + // Regardless of the results below we need to clear out the old |
356 | + // subviews. |
357 | + if (this._editorial) { |
358 | + this._editorial.destroy(); |
359 | + } |
360 | + |
361 | + if (this._details) { |
362 | + this._details.destroy(); |
363 | + } |
364 | + |
365 | + if (this._search) { |
366 | + this._search.destroy(); |
367 | + } |
368 | + |
369 | // If we've changed the charmID or the viewmode has changed and we have |
370 | // a charmID, render charmDetails. |
371 | if (this._shouldShowCharm()) { |
372 | @@ -411,7 +422,7 @@ |
373 | // Render search results if search is in the url and the viewmode or |
374 | // the search has been changed in the state. |
375 | this.renderSearchResults(req, res, next); |
376 | - } else if (!this._viewState.charmID) { |
377 | + } else if (!this._viewState.search && !this._viewState.charmID) { |
378 | // Render the editorial in fullscreen only if we don't have a charmid |
379 | this.renderEditorial(req, res, next); |
380 | } |
381 | @@ -422,13 +433,12 @@ |
382 | }, |
383 | |
384 | /** |
385 | - * Handle the route for the sidebar view. |
386 | - * |
387 | - * @method sidebar |
388 | - * @param {Request} req current request object. |
389 | - * @param {Response} res current response object. |
390 | - * @param {function} next callable for the next route in the chain. |
391 | - * |
392 | + Handle the route for the sidebar view. |
393 | + |
394 | + @method sidebar |
395 | + @param {Request} req current request object. |
396 | + @param {Response} res current response object. |
397 | + @param {function} next callable for the next route in the chain. |
398 | */ |
399 | sidebar: function(req, res, next) { |
400 | // If we've switched to viewmode sidebar, we need to render it. |
401 | @@ -440,10 +450,20 @@ |
402 | // Render search results if search is in the url and the viewmode or the |
403 | // search has been changed in the state. |
404 | if (this._shouldShowSearch()) { |
405 | + // Showing search implies that other sidebar content is destroyed. |
406 | + if (this._editorial) { |
407 | + this._editorial.destroy(); |
408 | + } |
409 | + |
410 | this.renderSearchResults(req, res, next); |
411 | } |
412 | |
413 | if (this._shouldShowEditorial()) { |
414 | + // Showing editorial implies that other sidebar content is destroyed. |
415 | + if (this._search) { |
416 | + this._search.destroy(); |
417 | + } |
418 | + |
419 | this.renderEditorial(req, res, next); |
420 | } |
421 | |
422 | @@ -454,7 +474,7 @@ |
423 | this.renderCharmDetails(req, res, next); |
424 | } |
425 | |
426 | - // If the sidebar is the final part of the route, then hide the div for |
427 | + // If there are no details in the route then hide the div for |
428 | // viewing the charm details. |
429 | if (!this._viewState.charmID) { |
430 | this._detailsVisible(false); |
431 | @@ -474,17 +494,16 @@ |
432 | }, |
433 | |
434 | /** |
435 | - Dispatch to the correct viewmode based on the route that was hit. |
436 | + Dispatch to the correct viewmode based on the route that was hit. |
437 | |
438 | @method routeView |
439 | @param {Request} req current request object. |
440 | @param {Response} res current response object. |
441 | @param {function} next callable for the next route in the chain. |
442 | - |
443 | */ |
444 | routeView: function(req, res, next) { |
445 | // Update the state for the rest of things to figure out what to do. |
446 | - this._updateState(req.path, req.params); |
447 | + this._updateState(req); |
448 | this[req.params.viewmode](req, res, next); |
449 | } |
450 | |
451 | @@ -494,7 +513,6 @@ |
452 | @attribute container |
453 | @default '#subapp-browser' |
454 | @type {String} |
455 | - |
456 | */ |
457 | container: { |
458 | value: '#subapp-browser' |
459 | @@ -504,17 +522,15 @@ |
460 | @attribute store |
461 | @default Charmworld0 |
462 | @type {Charmworld0} |
463 | - |
464 | */ |
465 | store: { |
466 | /** |
467 | - We keep one instance of the store and will work on caching results |
468 | - at the app level so that routes can share api calls. However, in |
469 | - tests there's no config for talking to the api so we have to watch |
470 | - out in test runs and allow the store to be broken. |
471 | - |
472 | - method store.valueFn |
473 | - |
474 | + We keep one instance of the store and will work on caching results |
475 | + at the app level so that routes can share api calls. However, in |
476 | + tests there's no config for talking to the api so we have to watch |
477 | + out in test runs and allow the store to be broken. |
478 | + |
479 | + method store.valueFn |
480 | */ |
481 | valueFn: function() { |
482 | var url = ''; |
483 | @@ -533,7 +549,6 @@ |
484 | @attribute routes |
485 | @default Array of subapp routes. |
486 | @type {Array} |
487 | - |
488 | */ |
489 | routes: { |
490 | value: [ |
491 | @@ -549,7 +564,6 @@ |
492 | @attribute urlNamespace |
493 | @default 'charmstore' |
494 | @type {String} |
495 | - |
496 | */ |
497 | urlNamespace: { |
498 | value: 'charmstore' |
499 | @@ -562,7 +576,6 @@ |
500 | @attribute deploy |
501 | @default undefined |
502 | @type {Function} |
503 | - |
504 | */ |
505 | deploy: {} |
506 | |
507 | @@ -573,7 +586,7 @@ |
508 | requires: [ |
509 | 'juju-charm-store', |
510 | 'juju-models', |
511 | - 'querystring-parse', |
512 | + 'querystring', |
513 | 'sub-app', |
514 | 'subapp-browser-charmview', |
515 | 'subapp-browser-editorial', |
516 | |
517 | === modified file 'app/subapps/browser/views/editorial.js' |
518 | --- app/subapps/browser/views/editorial.js 2013-04-24 06:18:42 +0000 |
519 | +++ app/subapps/browser/views/editorial.js 2013-04-24 18:15:32 +0000 |
520 | @@ -60,17 +60,14 @@ |
521 | var charmID = charm.getData('charmid'); |
522 | |
523 | // Update the UI for the active one. |
524 | - this._updateActive(ev.currentTarget); |
525 | + if (!this.get('isFullscreen')) { |
526 | + this._updateActive(ev.currentTarget); |
527 | + } |
528 | + |
529 | var change = { |
530 | charmID: charmID |
531 | }; |
532 | |
533 | - if (this.get('isFullscreen')) { |
534 | - change.viewmode = 'fullscreen'; |
535 | - } else { |
536 | - change.viewmode = 'sidebar'; |
537 | - } |
538 | - |
539 | this.fire('viewNavigate', {change: change}); |
540 | }, |
541 | |
542 | |
543 | === modified file 'app/subapps/browser/views/search.js' |
544 | --- app/subapps/browser/views/search.js 2013-04-23 13:31:29 +0000 |
545 | +++ app/subapps/browser/views/search.js 2013-04-24 18:15:32 +0000 |
546 | @@ -17,7 +17,52 @@ |
547 | ns.BrowserSearchView = Y.Base.create('browser-view-searchview', Y.View, [ |
548 | views.utils.apiFailingView |
549 | ], { |
550 | + events: { |
551 | + '.charm-token': { |
552 | + click: '_handleCharmSelection' |
553 | + } |
554 | + }, |
555 | + |
556 | template: views.Templates.search, |
557 | + |
558 | + /** |
559 | + When selecting a charm from the list make sure we re-route the app to |
560 | + the details view with that charm selected. |
561 | + |
562 | + @method _handleCharmSelection |
563 | + @param {Event} ev the click event handler for the charm selected. |
564 | + |
565 | + */ |
566 | + _handleCharmSelection: function(ev) { |
567 | + ev.halt(); |
568 | + var charm = ev.currentTarget; |
569 | + var charmID = charm.getData('charmid'); |
570 | + |
571 | + // Update the UI for the active one. |
572 | + if (!this.get('isFullscreen')) { |
573 | + this._updateActive(ev.currentTarget); |
574 | + } |
575 | + var change = { |
576 | + charmID: charmID |
577 | + }; |
578 | + this.fire('viewNavigate', {change: change}); |
579 | + }, |
580 | + |
581 | + /** |
582 | + Update the node in the editorial list marked as 'active'. |
583 | + |
584 | + @method _updateActive |
585 | + @param {Node} clickTarget the charm-token clicked on to activate. |
586 | + |
587 | + */ |
588 | + _updateActive: function(clickTarget) { |
589 | + // Remove the active class from any nodes that have it. |
590 | + Y.all('.yui3-charmtoken.active').removeClass('active'); |
591 | + |
592 | + // Add it to the current node. |
593 | + clickTarget.ancestor('.yui3-charmtoken').addClass('active'); |
594 | + }, |
595 | + |
596 | /** |
597 | * Renders the search results from the the store query. |
598 | * |
599 | @@ -30,6 +75,9 @@ |
600 | tplNode = Y.Node.create(tpl), |
601 | container = tplNode.one('.search-results'); |
602 | |
603 | + // Set the container so that our events will delegate based off of it. |
604 | + this.set('container', container); |
605 | + |
606 | results.map(function(charm) { |
607 | var ct = new widgets.browser.CharmToken(charm.getAttrs()); |
608 | ct.render(container); |
609 | |
610 | === modified file 'test/test_browser_app.js' |
611 | --- test/test_browser_app.js 2013-04-23 19:36:04 +0000 |
612 | +++ test/test_browser_app.js 2013-04-24 18:15:32 +0000 |
613 | @@ -468,6 +468,66 @@ |
614 | assert.deepEqual(hits, expected); |
615 | }); |
616 | |
617 | + it('changing the query string dispatches correctly', function() { |
618 | + var req = { |
619 | + path: '/bws/fullscreen/search/', |
620 | + params: { |
621 | + viewmode: 'fullscreen' |
622 | + }, |
623 | + query: { |
624 | + text: 'test' |
625 | + } |
626 | + }; |
627 | + browser.routeView(req, undefined, function() {}); |
628 | + |
629 | + // Reset the hits and we should not redraw anything to update the view. |
630 | + resetHits(); |
631 | + req.query.text = 'test2'; |
632 | + |
633 | + var expected = Y.merge(hits, { |
634 | + renderSearchResults: true |
635 | + }); |
636 | + browser.routeView(req, undefined, function() {}); |
637 | + assert.deepEqual(hits, expected); |
638 | + }); |
639 | + |
640 | + it('no change to query string does not redraw', function() { |
641 | + var req = { |
642 | + path: '/bws/fullscreen/search/', |
643 | + params: { |
644 | + viewmode: 'fullscreen' |
645 | + }, |
646 | + query: { |
647 | + text: 'test' |
648 | + } |
649 | + }; |
650 | + browser.routeView(req, undefined, function() {}); |
651 | + |
652 | + // Reset the hits and we should not redraw anything to update the view. |
653 | + resetHits(); |
654 | + |
655 | + var expected = Y.merge(hits); |
656 | + browser.routeView(req, undefined, function() {}); |
657 | + assert.deepEqual(hits, expected); |
658 | + }); |
659 | + |
660 | + it('handles searches with no querystring', function() { |
661 | + var req = { |
662 | + path: '/bws/fullscreen/search/', |
663 | + params: { |
664 | + viewmode: 'fullscreen' |
665 | + } |
666 | + }; |
667 | + |
668 | + var expected = Y.merge(hits, { |
669 | + fullscreen: true, |
670 | + renderSearchResults: true |
671 | + }); |
672 | + |
673 | + browser.routeView(req, undefined, function() {}); |
674 | + assert.deepEqual(hits, expected); |
675 | + }); |
676 | + |
677 | }); |
678 | })(); |
679 | |
680 | |
681 | === modified file 'test/test_browser_editorial.js' |
682 | --- test/test_browser_editorial.js 2013-04-24 16:42:05 +0000 |
683 | +++ test/test_browser_editorial.js 2013-04-24 18:15:32 +0000 |
684 | @@ -106,7 +106,6 @@ |
685 | |
686 | view.on('viewNavigate', function(ev) { |
687 | ev.halt(); |
688 | - assert(ev.change.viewmode === 'fullscreen'); |
689 | assert(ev.change.charmID === 'precise/ceph-7'); |
690 | done(); |
691 | }); |
692 | @@ -134,7 +133,6 @@ |
693 | |
694 | view.on('viewNavigate', function(ev) { |
695 | ev.halt(); |
696 | - assert(ev.change.viewmode === 'sidebar'); |
697 | assert(ev.change.charmID === 'precise/ceph-7'); |
698 | done(); |
699 | }); |
700 | |
701 | === modified file 'test/test_browser_search_view.js' |
702 | --- test/test_browser_search_view.js 2013-04-22 21:04:27 +0000 |
703 | +++ test/test_browser_search_view.js 2013-04-24 18:15:32 +0000 |
704 | @@ -12,6 +12,7 @@ |
705 | 'json', |
706 | 'juju-charm-store', |
707 | 'node', |
708 | + 'node-event-simulate', |
709 | 'subapp-browser-searchview', |
710 | function(Y) { |
711 | done(); |
712 | @@ -75,4 +76,27 @@ |
713 | view.render(); |
714 | assert.equal('charms?text=', apiURL); |
715 | }); |
716 | + |
717 | + it('clicking a charm navigates for fullscreen', function(done) { |
718 | + view.render(); |
719 | + view.on('viewNavigate', function(ev) { |
720 | + ev.halt(); |
721 | + assert(ev.change.charmID === 'foo/bar-2'); |
722 | + done(); |
723 | + }); |
724 | + |
725 | + container.one('.charm-token').simulate('click'); |
726 | + }); |
727 | + |
728 | + it('clicking a charm navigates for sidebar', function(done) { |
729 | + view.render(); |
730 | + view.on('viewNavigate', function(ev) { |
731 | + ev.halt(); |
732 | + assert(ev.change.charmID === 'foo/bar-2'); |
733 | + done(); |
734 | + }); |
735 | + |
736 | + container.one('.charm-token').simulate('click'); |
737 | + }); |
738 | + |
739 | }); |
Reviewers: mp+160706_ code.launchpad. net,
Message:
Please take a look.
Description:
Fixes several problems with search
-Querystring was eaten on viewmode changes or when a search url was
pasted
into browser.
-Editorial and Search could have collisions in fullscreen.
-Charm add button didn't work on search results charm tokens.
https:/ /code.launchpad .net/~jcsackett /juju-gui/ search- fixes/+ merge/160706
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/8940043/
Affected files: browser/ browser. js browser/ views/editorial .js browser/ views/search. js browser_ app.js browser_ editorial. js browser_ search_ view.js
A [revision details]
M app/subapps/
M app/subapps/
M app/subapps/
M test/test_
M test/test_
M test/test_