Merge lp:~gary/juju-gui/env-help-text into lp:juju-gui/experimental

Proposed by Gary Poster
Status: Merged
Merged at revision: 621
Proposed branch: lp:~gary/juju-gui/env-help-text
Merge into: lp:juju-gui/experimental
Diff against target: 350 lines (+136/-19)
10 files modified
app/assets/javascripts/d3-components.js (+3/-0)
app/store/endpoints.js (+6/-2)
app/templates/overview.handlebars (+11/-0)
app/views/environment.js (+29/-1)
app/widgets/overlay-indicator.js (+2/-3)
lib/views/stylesheet.less (+35/-0)
test/test_environment_view.js (+30/-2)
test/test_panzoom.js (+3/-4)
test/test_service_module.js (+8/-7)
test/utils.js (+9/-0)
To merge this branch: bzr merge lp:~gary/juju-gui/env-help-text
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+161418@code.launchpad.net

Description of the change

Help on empty canvas

The env view should show some help text when the canvas is empty.

Landing work from bcsaller that I modified.

https://codereview.appspot.com/8961049/

To post a comment you must log in.
Revision history for this message
Gary Poster (gary) wrote :

Reviewers: mp+161418_code.launchpad.net,

Message:
Please take a look.

Description:
Help on empty canvas

The env view should show some help text when the canvas is empty.

Landing work from bcsaller that I modified.

https://code.launchpad.net/~gary/juju-gui/env-help-text/+merge/161418

(do not edit description out of merge proposal)

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

Affected files:
   A [revision details]
   A app/assets/images/empty_canvas.png
   M app/assets/javascripts/d3-components.js
   M app/store/endpoints.js
   M app/templates/overview.handlebars
   M app/views/environment.js
   M app/widgets/overlay-indicator.js
   M lib/views/stylesheet.less
   M test/test_environment_view.js
   M test/test_panzoom.js
   M test/test_service_module.js
   M test/utils.js

Revision history for this message
Richard Harding (rharding) wrote :

LGTM Thanks for updating.

https://codereview.appspot.com/8961049/

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

*** Submitted:

Help on empty canvas

The env view should show some help text when the canvas is empty.

Landing work from bcsaller that I modified.

R=rharding
CC=
https://codereview.appspot.com/8961049

https://codereview.appspot.com/8961049/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'app/assets/images/empty_canvas.png'
2Binary files app/assets/images/empty_canvas.png 1970-01-01 00:00:00 +0000 and app/assets/images/empty_canvas.png 2013-04-29 12:42:28 +0000 differ
3=== modified file 'app/assets/javascripts/d3-components.js'
4--- app/assets/javascripts/d3-components.js 2013-03-25 15:39:48 +0000
5+++ app/assets/javascripts/d3-components.js 2013-04-29 12:42:28 +0000
6@@ -346,6 +346,9 @@
7 * @chainable
8 **/
9 recordSubscription: function(module, subscription) {
10+ if (typeof module === 'string') {
11+ module = this.modules[module];
12+ }
13 if (!(module.name in this.events)) {
14 throw 'Unable able to recordSubscription, module not added.';
15 }
16
17=== modified file 'app/store/endpoints.js'
18--- app/store/endpoints.js 2013-04-24 14:39:32 +0000
19+++ app/store/endpoints.js 2013-04-29 12:42:28 +0000
20@@ -143,8 +143,12 @@
21 }
22
23 if (!charm) {
24- charm = db.charms.add({id: charm_id})
25- .load(env,
26+ // XXX: temp hack to work around failures here;
27+ charm = db.charms.add({id: charm_id});
28+ if (!charm) {
29+ charm = db.charms.getById(charm_id);
30+ }
31+ charm.load(env,
32 // If views are bound to the charm model, firing "update" is
33 // unnecessary, and potentially even mildly harmful.
34 function(err, result) { db.fire('update'); });
35
36=== modified file 'app/templates/overview.handlebars'
37--- app/templates/overview.handlebars 2013-02-26 21:34:28 +0000
38+++ app/templates/overview.handlebars 2013-04-29 12:42:28 +0000
39@@ -1,5 +1,16 @@
40 <div class="topology">
41 <div class="crosshatch-background topology-canvas">
42+ <div id="environment-help" style="display: none;">
43+ <div class="vertical-center-floater"></div>
44+ <div class="content">
45+ <h1>Add your first charm here!</h1>
46+ <i class="sprite empty_canvas"></i>
47+ <p>
48+ Click on a charm on the left to view its details. Select the
49+ Add button to add it to this canvas.
50+ </p>
51+ </div>
52+ </div>
53 <div class="environment-menu" id="service-menu">
54 <div class="triangle">&nbsp;</div>
55 <ul>
56
57=== modified file 'app/views/environment.js'
58--- app/views/environment.js 2013-04-09 20:22:01 +0000
59+++ app/views/environment.js 2013-04-29 12:42:28 +0000
60@@ -52,7 +52,9 @@
61 */
62 render: function() {
63 var container = this.get('container'),
64- topo = this.topo;
65+ topo = this.topo,
66+ db = this.get('db'),
67+ self = this;
68
69 // If we need the initial HTML template, take care of that.
70 if (!this._rendered) {
71@@ -83,11 +85,37 @@
72 this.topo = topo;
73 }
74
75+ topo.recordSubscription(
76+ 'ServiceModule',
77+ db.services.after('remove', Y.bind(this.updateIndicator, this)));
78+
79+ topo.recordSubscription(
80+ 'ServiceModule',
81+ db.services.after('add', Y.bind(this.updateIndicator, this)));
82+
83 topo.render();
84+ topo.once('rendered', Y.bind(this.updateIndicator, this));
85 return this;
86 },
87
88 /**
89+ * Support for canvas help function (when canvas is empty).
90+ *
91+ * @method updateIndicator
92+ */
93+ updateIndicator: function(evt) {
94+ var helpText = this.get('container').one('#environment-help'),
95+ db = this.get('db'),
96+ services = db.services;
97+ if (helpText) {
98+ if (services.size() === 0) {
99+ helpText.show(true);
100+ } else {
101+ helpText.hide(true);
102+ }
103+ }
104+ },
105+ /**
106 * Render callback handler, triggered from app when the view renders.
107 *
108 * @method render.rendered
109
110=== modified file 'app/widgets/overlay-indicator.js'
111--- app/widgets/overlay-indicator.js 2013-04-08 18:30:20 +0000
112+++ app/widgets/overlay-indicator.js 2013-04-29 12:42:28 +0000
113@@ -52,10 +52,9 @@
114 * @method renderUI
115 */
116 renderUI: function() {
117- var node_html = '<img src={src}>';
118+ var node_html = '<img src="{src}">';
119 var img = Y.Node.create(
120 sub(node_html, {src: this.get('loading_image')}));
121- img.set('src', '/juju-ui/assets/images/non-sprites/loading-spinner.gif');
122 this.get('contentBox').append(img);
123 },
124
125@@ -155,7 +154,7 @@
126 * @type {string}
127 */
128 loading_image: {
129- value: '/juju-ui/assets/images/loading-spinner.gif'
130+ value: '/juju-ui/assets/images/non-sprites/loading-spinner.gif'
131 }
132 }
133 });
134
135=== modified file 'lib/views/stylesheet.less'
136--- lib/views/stylesheet.less 2013-04-25 17:03:09 +0000
137+++ lib/views/stylesheet.less 2013-04-29 12:42:28 +0000
138@@ -278,6 +278,41 @@
139 cursor: move;
140 }
141
142+#environment-help {
143+ color: #757575;
144+ text-align: center;
145+ position: absolute;
146+ overflow: hidden;
147+ padding: 0;
148+ width: 100%;
149+ height: 100%;
150+ /* pointer-events does not work in IE 10 except in SVG, so this is just a
151+ way to slightly improve the experience during transitions. */
152+ pointer-events: none;
153+ div.vertical-center-floater {
154+ height: 50%;
155+ margin-bottom: -225px;
156+ margin-top: 0;
157+ min-height: 225px;
158+ }
159+ div.content {
160+ height: 450px;
161+ }
162+ h1 {
163+ line-height: normal;
164+ margin-bottom: 1ex;
165+ font-weight: normal;
166+ font-size: 26px;
167+ }
168+ p {
169+ line-height: normal;
170+ font-size: 18px;
171+ width: 301px;
172+ margin-left: auto;
173+ margin-right: auto;
174+ margin-top: 2ex;
175+ }
176+}
177
178 .environment-menu {
179 @border_radius: 20px;
180
181=== modified file 'test/test_environment_view.js'
182--- test/test_environment_view.js 2013-04-19 18:28:51 +0000
183+++ test/test_environment_view.js 2013-04-29 12:42:28 +0000
184@@ -104,8 +104,7 @@
185 });
186
187 beforeEach(function() {
188- container = Y.Node.create('<div />').setStyle('visibility', 'hidden');
189- Y.one('body').prepend(container);
190+ container = testUtils.makeContainer();
191 db = new models.Database();
192 // Use a clone to avoid any mutation
193 // to the input set (as happens with processed
194@@ -121,6 +120,35 @@
195 done();
196 });
197
198+
199+ it('should display help text when canvas is empty', function() {
200+ // Use a db w/o the delta loaded
201+ db = new models.Database();
202+ var view = new views.environment({container: container, db: db}),
203+ topo,
204+ beforeResizeEventFired = false;
205+ view.render().rendered();
206+ topo = view.topo;
207+
208+ // Verify we have help text.
209+ var help = Y.one('#environment-help');
210+ assert.strictEqual(help.getStyle('display'), 'block');
211+ });
212+
213+
214+ it('should not display help text when canvas is populated', function() {
215+ var view = new views.environment({container: container, db: db}),
216+ topo,
217+ beforeResizeEventFired = false;
218+ view.render().rendered();
219+ topo = view.topo;
220+
221+ // Verify we do not have help text.
222+ var help = Y.one('#environment-help');
223+ assert.strictEqual(help.getStyle('display'), 'none');
224+ });
225+
226+
227 it('must handle the window resize event', function(done) {
228 var view = new views.environment({container: container, db: db}),
229 topo,
230
231=== modified file 'test/test_panzoom.js'
232--- test/test_panzoom.js 2013-03-07 22:22:10 +0000
233+++ test/test_panzoom.js 2013-04-29 12:42:28 +0000
234@@ -1,7 +1,7 @@
235 'use strict';
236
237 describe('pan zoom module', function() {
238- var db, juju, models, viewContainer, views, Y, pz, topo, vis;
239+ var db, juju, models, utils, viewContainer, views, Y, pz, topo, vis;
240
241 before(function(done) {
242 Y = YUI(GlobalConfig).use(['node',
243@@ -15,14 +15,13 @@
244 juju = Y.namespace('juju');
245 models = Y.namespace('juju.models');
246 views = Y.namespace('juju.views');
247+ utils = Y.namespace('juju-tests.utils');
248 done();
249 });
250 });
251
252 beforeEach(function() {
253- viewContainer = Y.Node.create('<div />');
254- viewContainer.appendTo(Y.one('body'));
255- viewContainer.hide();
256+ viewContainer = utils.makeContainer();
257 db = new models.Database();
258 var view = new views.environment({container: viewContainer, db: db});
259 view.render();
260
261=== modified file 'test/test_service_module.js'
262--- test/test_service_module.js 2013-04-17 15:45:59 +0000
263+++ test/test_service_module.js 2013-04-29 12:42:28 +0000
264@@ -1,10 +1,11 @@
265 'use strict';
266
267 describe('service module annotations', function() {
268- var db, juju, models, viewContainer, views, Y, serviceModule;
269+ var db, juju, models, utils, viewContainer, views, Y, serviceModule;
270 var called, location;
271 before(function(done) {
272 Y = YUI(GlobalConfig).use(['node',
273+ 'juju-tests-utils',
274 'juju-models',
275 'juju-views',
276 'juju-gui',
277@@ -12,15 +13,14 @@
278 function(Y) {
279 juju = Y.namespace('juju');
280 models = Y.namespace('juju.models');
281+ utils = Y.namespace('juju-tests.utils');
282 views = Y.namespace('juju.views');
283 done();
284 });
285 });
286
287 beforeEach(function() {
288- viewContainer = Y.Node.create('<div />');
289- viewContainer.appendTo(Y.one('body'));
290- viewContainer.hide();
291+ viewContainer = utils.makeContainer(),
292 db = new models.Database();
293 called = false;
294 location =
295@@ -77,10 +77,11 @@
296 });
297
298 describe('service module events', function() {
299- var db, juju, models, serviceModule, topo,
300+ var db, juju, models, serviceModule, topo, utils,
301 view, viewContainer, views, Y;
302 before(function(done) {
303 Y = YUI(GlobalConfig).use(['node',
304+ 'juju-tests-utils',
305 'juju-landscape',
306 'juju-models',
307 'juju-views',
308@@ -91,13 +92,13 @@
309 juju = Y.namespace('juju');
310 models = Y.namespace('juju.models');
311 views = Y.namespace('juju.views');
312+ utils = Y.namespace('juju-tests.utils');
313 done();
314 });
315 });
316
317 beforeEach(function() {
318- viewContainer = Y.Node.create('<div />');
319- viewContainer.appendTo(Y.one('body'));
320+ viewContainer = utils.makeContainer();
321 db = new models.Database();
322 db.services.add({id: 'haproxy'});
323 view = new views.environment({
324
325=== modified file 'test/utils.js'
326--- test/utils.js 2013-04-17 01:08:13 +0000
327+++ test/utils.js 2013-04-29 12:42:28 +0000
328@@ -5,6 +5,14 @@
329 var jujuTests = Y.namespace('juju-tests');
330
331 jujuTests.utils = {
332+ makeContainer: function() {
333+ var container = Y.Node.create('<div>');
334+ container.appendTo(document.body);
335+ container.setStyle('position', 'absolute');
336+ container.setStyle('top', '-10000px');
337+ container.setStyle('left', '-10000px');
338+ return container;
339+ },
340
341 SocketStub: function() {
342 this.messages = [];
343@@ -102,6 +110,7 @@
344 }, '0.1.0', {
345 requires: [
346 'io',
347+ 'node',
348 'datasource-local',
349 'juju-charm-store',
350 'juju-env-fakebackend'

Subscribers

People subscribed via source and target branches