Merge lp:~bcsaller/juju-gui/hotkey-ext into lp:juju-gui/experimental

Proposed by Benjamin Saller
Status: Merged
Merged at revision: 688
Proposed branch: lp:~bcsaller/juju-gui/hotkey-ext
Merge into: lp:juju-gui/experimental
Diff against target: 260 lines (+94/-21)
5 files modified
app/app.js (+61/-15)
app/config-debug.js (+2/-1)
app/store/env/simulator.js (+17/-0)
app/views/topology/panzoom.js (+7/-5)
lib/views/stylesheet.less (+7/-0)
To merge this branch: bzr merge lp:~bcsaller/juju-gui/hotkey-ext
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+165428@code.launchpad.net

Description of the change

Hotkey extensions

Keybindings can declare more behavior
Toggle simulator

https://codereview.appspot.com/9694043/

To post a comment you must log in.
Revision history for this message
Benjamin Saller (bcsaller) wrote :

Reviewers: mp+165428_code.launchpad.net,

Message:
Please take a look.

Description:
Hotkey extensions

Keybindings can declare more behavior
Toggle simulator

https://code.launchpad.net/~bcsaller/juju-gui/hotkey-ext/+merge/165428

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/9694043/

Affected files:
   A [revision details]
   M app/app.js
   M app/config-debug.js
   M app/store/env/simulator.js
   M app/views/topology/panzoom.js
   M lib/views/stylesheet.less

Revision history for this message
Jeff Pihach (hatch) wrote :

LGTM - This hotkey stuff is getting to be a considerable number of lines
and looks pretty easy to be able to break out into an app extension to
clean up app.js. Possibly a follow-up?

https://codereview.appspot.com/9694043/

Revision history for this message
Gary Poster (gary) wrote :

LGTM. Maybe we should remove the feature flag simulator support? Oh,
and I think we should always instantiate the simulator in sandbox mode,
but only start it if simulateEvents is true in the config?

Thanks!

https://codereview.appspot.com/9694043/diff/1/app/app.js
File app/app.js (right):

https://codereview.appspot.com/9694043/diff/1/app/app.js#newcode173
app/app.js:173: '/': {
+1
...though on reflection it reminds me that we will need to change this
to work with the charm browser when it lands. Can cross the bridge when
we come to it.

https://codereview.appspot.com/9694043/diff/1/app/app.js#newcode207
app/app.js:207: '+': {
cool :-)

https://codereview.appspot.com/9694043/

Revision history for this message
Benjamin Saller (bcsaller) wrote :

*** Submitted:

Hotkey extensions

Keybindings can declare more behavior
Toggle simulator

R=jeff.pihach, gary.poster
CC=
https://codereview.appspot.com/9694043

https://codereview.appspot.com/9694043/

Revision history for this message
Benjamin Saller (bcsaller) wrote :

Thanks for the reviews, changed it to always create the simulator, to
start on config or hotkey and to clean up in the destructor.

https://codereview.appspot.com/9694043/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'app/app.js'
2--- app/app.js 2013-05-22 22:30:29 +0000
3+++ app/app.js 2013-05-23 16:07:28 +0000
4@@ -154,6 +154,9 @@
5 * target: {String} CSS selector of one element
6 * focus: {Boolean} Focus the element.
7 * toggle: {Boolean} Toggle element visibility.
8+ * fire: {String} Event to fire when triggered. (XXX: Target is topology)
9+ * condition: {Function} returns Boolean, should method be added to
10+ * keybindings.
11 * callback: {Function} Taking (event, target).
12 * help: {String} Help text to display in popup.
13 *
14@@ -167,17 +170,10 @@
15 focus: true,
16 help: 'Select the charm Search'
17 },
18- 'S-d': {
19- callback: function(evt) {
20- /* global saveAs: false */
21- this.env.exportEnvironment(function(r) {
22- var exportData = JSON.stringify(r.result, undefined, 2);
23- var exportBlob = new Blob([exportData],
24- {type: 'application/json;charset=utf-8'});
25- saveAs(exportBlob, 'export.json');
26- });
27- },
28- help: 'Export the environment'
29+ '/': {
30+ target: '#charm-search-field',
31+ focus: true,
32+ help: 'Select the charm Search'
33 },
34 'S-/': {
35 target: '#shortcut-help',
36@@ -187,10 +183,15 @@
37 if (target && !target.getHTML().length) {
38 var bindings = [];
39 Y.each(this.keybindings, function(v, k) {
40- if (v.help) {
41+ if (v.help && (v.condition === undefined ||
42+ v.condition.call(this) === true)) {
43+ // TODO: translate keybindings to
44+ // human <Alt> m
45+ // <Control> <Shift> N (note caps)
46+ // also 'g then i' style
47 bindings.push({key: k, help: v.help});
48 }
49- });
50+ }, this);
51 target.setHTML(
52 views.Templates.shortcuts({bindings: bindings}));
53 }
54@@ -203,13 +204,46 @@
55 },
56 help: 'Navigate to the Environment overview.'
57 },
58+ '+': {
59+ fire: 'zoom_in',
60+ help: 'Zoom In'
61+ },
62+ '-': {
63+ fire: 'zoom_out',
64+ help: 'Zoom Out'
65+ },
66 'esc': {
67+ fire: 'clearState',
68 callback: function() {
69 // Explicitly hide anything we might care about.
70 Y.one('#shortcut-help').hide();
71 },
72 help: 'Cancel current action'
73+ },
74+
75+ 'C-s': {
76+ 'condition': function() {
77+ return this._simulator !== undefined;
78+ },
79+ callback: function() {
80+ this._simulator.toggle();
81+ },
82+ help: 'Toggle the simulator'
83+ },
84+
85+ 'S-d': {
86+ callback: function(evt) {
87+ /* global saveAs: false */
88+ this.env.exportEnvironment(function(r) {
89+ var exportData = JSON.stringify(r.result, undefined, 2);
90+ var exportBlob = new Blob([exportData],
91+ {type: 'application/json;charset=utf-8'});
92+ saveAs(exportBlob, 'export.json');
93+ });
94+ },
95+ help: 'Export the environment'
96 }
97+
98 },
99
100 /**
101@@ -248,14 +282,14 @@
102 */
103 activateHotkeys: function() {
104 var key_map = {
105- '/': 191, '?': 63,
106+ '/': 191, '?': 63, '+': 187, '-': 189,
107 enter: 13, esc: 27, backspace: 8,
108 tab: 9, pageup: 33, pagedown: 34};
109 var code_map = {};
110 Y.each(key_map, function(v, k) {
111 code_map[v] = k;
112 });
113- Y.one(window).on('keydown', function(evt) {
114+ this._keybindings = Y.one(window).on('keydown', function(evt) {
115 //Normalize key-code
116 var symbolic = [];
117 if (evt.ctrlKey) { symbolic.push('C');}
118@@ -266,12 +300,21 @@
119 var trigger = symbolic.join('-');
120 var spec = this.keybindings[trigger];
121 if (spec) {
122+ if (spec.condition && !spec.condition.call(this)) {
123+ // Note that when a condition check fails
124+ // the event still propagates.
125+ return;
126+ }
127 var target = Y.one(spec.target);
128 if (target) {
129 if (spec.toggle) { target.toggleView(); }
130 if (spec.focus) { target.focus(); }
131 }
132 if (spec.callback) { spec.callback.call(this, evt, target); }
133+ // HACK w/o context/view restriction but right direction
134+ if (spec.fire) {
135+ this.views.environment.instance.topo.fire(spec.fire);
136+ }
137 // If we handled the event nothing else has to.
138 evt.stopPropagation();
139 evt.preventDefault();
140@@ -521,6 +564,9 @@
141 @method destructor
142 */
143 destructor: function() {
144+ if (this._keybindings) {
145+ this._keybindings.detach();
146+ }
147 Y.each(
148 [this.env, this.db, this.charm_store, this.notifications,
149 this.landscape, this.endpointsController],
150
151=== modified file 'app/config-debug.js'
152--- app/config-debug.js 2013-05-21 01:16:15 +0000
153+++ app/config-debug.js 2013-05-23 16:07:28 +0000
154@@ -45,7 +45,8 @@
155 sandbox: true,
156 // When in sandbox mode should we create events to simulate a live env.
157 // You can also use the :flags:/simulateEvents feature flag.
158- simulateEvents: false,
159+ // There is also a hotkey to toggle the simulator.
160+ simulateEvents: true,
161 readOnly: false,
162 login_help: 'For this demonstration, use the password "admin" to connect.'
163 };
164
165=== modified file 'app/store/env/simulator.js'
166--- app/store/env/simulator.js 2013-05-21 12:52:33 +0000
167+++ app/store/env/simulator.js 2013-05-23 16:07:28 +0000
168@@ -484,6 +484,7 @@
169
170 // Invoke on start as well.
171 tick();
172+ console.log('Simulator started');
173 return this;
174
175 },
176@@ -497,6 +498,22 @@
177 if (this._scheduler) {
178 this._scheduler.cancel();
179 this._scheduler = null;
180+ console.log('Simulator stopped');
181+ }
182+ return this;
183+ },
184+
185+ /**
186+ Toggle the running state of the simulator.
187+
188+ @method toggle
189+ @chainable
190+ */
191+ toggle: function() {
192+ if (this._scheduler) {
193+ this.stop();
194+ } else {
195+ this.start();
196 }
197 return this;
198 }
199
200=== modified file 'app/views/topology/panzoom.js'
201--- app/views/topology/panzoom.js 2013-05-17 14:51:05 +0000
202+++ app/views/topology/panzoom.js 2013-05-23 16:07:28 +0000
203@@ -59,7 +59,9 @@
204
205 @event rendered
206 */
207- rendered: 'renderedHandler'
208+ rendered: 'renderedHandler',
209+ zoom_in: 'zoom_in',
210+ zoom_out: 'zoom_out'
211 }
212 },
213
214@@ -130,8 +132,8 @@
215 *
216 * @method zoom_out
217 */
218- zoom_out: function(data, context) {
219- var slider = context.slider,
220+ zoom_out: function(data, self) {
221+ var slider = this.slider || self.slider,
222 val = slider.get('value');
223 slider.set('value', val - 25);
224 },
225@@ -141,8 +143,8 @@
226 *
227 * @method zoom_in
228 */
229- zoom_in: function(data, context) {
230- var slider = context.slider,
231+ zoom_in: function(data, self) {
232+ var slider = this.slider || self.slider,
233 val = slider.get('value');
234 slider.set('value', val + 25);
235 },
236
237=== modified file 'lib/views/stylesheet.less'
238--- lib/views/stylesheet.less 2013-05-22 22:30:29 +0000
239+++ lib/views/stylesheet.less 2013-05-23 16:07:28 +0000
240@@ -117,6 +117,7 @@
241 background: url(/juju-ui/assets/images/top_bar.png) repeat-x;
242 padding: 0;
243 position: relative;
244+ overflow: hidden;
245 color: @navbar-color;
246 .brand {
247 margin: 12px 26px 6px 10px;
248@@ -1725,6 +1726,12 @@
249 letter-spacing: normal;
250 }
251
252+.yui3-slider-thumb {
253+ &:focus {
254+ outline: none;
255+ }
256+}
257+
258 /** Browser Setup **/
259 @import "browser/reset.less";
260 @import "browser/vars.less";

Subscribers

People subscribed via source and target branches