Merge lp:~makyo/juju-gui/ambiguous-relations into lp:juju-gui/experimental

Proposed by Madison Scott-Clary
Status: Merged
Approved by: Kapil Thangavelu
Approved revision: 200
Merged at revision: 199
Proposed branch: lp:~makyo/juju-gui/ambiguous-relations
Merge into: lp:juju-gui/experimental
Diff against target: 346 lines (+153/-34)
8 files modified
app/templates/ambiguousRelationList.handlebars (+12/-0)
app/templates/overview.handlebars (+6/-2)
app/views/environment.js (+84/-15)
app/views/utils.js (+11/-0)
lib/views/stylesheet.less (+2/-2)
test/test_application_notifications.js (+5/-1)
test/test_charm_configuration.js (+2/-1)
test/test_environment_view.js (+31/-13)
To merge this branch: bzr merge lp:~makyo/juju-gui/ambiguous-relations
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+130616@code.launchpad.net

Description of the change

Implement ambiguous relation menu for adding rels

Displays a menu of choices when adding a relation between two services would result in ambiguity, otherwise simply adds a relation. Also, a bit of minor test clean-up in charm config, due to floating point inequality.

https://codereview.appspot.com/6736051/

To post a comment you must log in.
Revision history for this message
Madison Scott-Clary (makyo) wrote :

Reviewers: mp+130616_code.launchpad.net,

Message:
Please take a look.

Description:
Implement ambiguous relation menu for adding rels

Displays a menu of choices when adding a relation between two services
would result in ambiguity, otherwise simply adds a relation. Also, a
bit of minor test clean-up in charm config, due to floating point
inequality.

https://code.launchpad.net/~makyo/juju-gui/ambiguous-relations/+merge/130616

(do not edit description out of merge proposal)

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

Affected files:
   A [revision details]
   M app/templates/overview.handlebars
   M app/views/environment.js
   M lib/views/stylesheet.less
   M test/test_application_notifications.js
   M test/test_charm_configuration.js
   M test/test_environment_view.js

Revision history for this message
Thiago Veronezi (tveronezi) wrote :

https://codereview.appspot.com/6736051/diff/1/app/views/environment.js
File app/views/environment.js (right):

https://codereview.appspot.com/6736051/diff/1/app/views/environment.js#newcode1449
app/views/environment.js:1449: var menu =
container.one('#ambiguous-relation-menu'),
If you are using ids you could simply use Y.one, right? Or you could use
a class instead.

https://codereview.appspot.com/6736051/diff/1/app/views/environment.js#newcode1463
app/views/environment.js:1463:
endpoints[m.id].forEach(function(endpoint) {
You could use handlebars to build the list for you. For example:

//remove old list, if any
menu.all('ul').remove();
.
.
.
//create new <ul><li></li>...<ul> list
var list = Templates.overviewRelationMenuList({
   endPoints: endpoints
});

list.all('li').on('click', ...

menu.append(list);
.
.
.

This way you remove some html elements from this js file. wdyt?

https://codereview.appspot.com/6736051/diff/1/lib/views/stylesheet.less
File lib/views/stylesheet.less (right):

https://codereview.appspot.com/6736051/diff/1/lib/views/stylesheet.less#newcode145
lib/views/stylesheet.less:145: #service-menu, #ambiguous-relation-menu {
You could remove the id and use both classes in your menu. Like...

<div class="service-menu ambiguous-relation-menu">
   <div class="triangle">&nbsp;</div>
     <ul/>
   </div>
</div>

So you can remove this new css declaration and do something like...

var menu = container.one('.ambiguous-relation-menu')

...in environment.js

https://codereview.appspot.com/6736051/

Revision history for this message
Madison Scott-Clary (makyo) wrote :

Thanks for the review, Thiago. See below for notes.

https://codereview.appspot.com/6736051/diff/1/app/views/environment.js
File app/views/environment.js (right):

https://codereview.appspot.com/6736051/diff/1/app/views/environment.js#newcode1449
app/views/environment.js:1449: var menu =
container.one('#ambiguous-relation-menu'),
On 2012/10/19 18:09:29, thiago wrote:
> If you are using ids you could simply use Y.one, right? Or you could
use a class
> instead.

I don't think that using a class would buy me anything here. The
ambiguous relation menu is unique, and referred to by a unique id.
Convention in the past has been to access nodes through container.

https://codereview.appspot.com/6736051/diff/1/app/views/environment.js#newcode1463
app/views/environment.js:1463:
endpoints[m.id].forEach(function(endpoint) {
On 2012/10/19 18:09:29, thiago wrote:
> You could use handlebars to build the list for you. For example:

> //remove old list, if any
> menu.all('ul').remove();
> .
> .
> .
> //create new <ul><li></li>...<ul> list
> var list = Templates.overviewRelationMenuList({
> endPoints: endpoints
> });

> list.all('li').on('click', ...

> menu.append(list);
> .
> .
> .

> This way you remove some html elements from this js file. wdyt?

Done. I initially couldn't figure out how I'd do it with Handlebars
given that the click action references each individual endpoint set, but
I did it with node data.

https://codereview.appspot.com/6736051/diff/1/lib/views/stylesheet.less
File lib/views/stylesheet.less (right):

https://codereview.appspot.com/6736051/diff/1/lib/views/stylesheet.less#newcode145
lib/views/stylesheet.less:145: #service-menu, #ambiguous-relation-menu {
On 2012/10/19 18:09:29, thiago wrote:
> You could remove the id and use both classes in your menu. Like...

> <div class="service-menu ambiguous-relation-menu">
> <div class="triangle">&nbsp;</div>
> <ul/>
> </div>
> </div>

> So you can remove this new css declaration and do something like...

> var menu = container.one('.ambiguous-relation-menu')

> ...in environment.js

Done. Both #service-menu and #ambiguous-relation-menu are unique and
must be referred to that way because of the way they're controlled in
the view. However, I have added a 'environment-menu' class to each, and
then used that as the selector here.

https://codereview.appspot.com/6736051/

198. By Madison Scott-Clary

Implement ambiguous relation menu for adding relations

199. By Madison Scott-Clary

Implement ambiguous relation menu for adding relations

200. By Madison Scott-Clary

Implement ambiguous relation menu for adding relations

Revision history for this message
Madison Scott-Clary (makyo) wrote :
Revision history for this message
Benjamin Saller (bcsaller) wrote :
Download full text (3.3 KiB)

Thanks for this. A number of things, some of which will be good talks
for next week. For now I think updating the HTML generation is a good
start and cards for the ux cases mentioned below.

One, we've chosen different paths for self.state and self.set('state',
...). We
should agree to a pattern and stick with it. My feeling is that instance
vars
were fine as we didn't depend on change events from Attribute
manipulation. We
now have enough state on the env graph that I'd like to create
ViewModels
around various operations and bind them to a Scene object. We're
scribbling
scale/zoom/transform, click actions, current actions etc. If we don't
contain
this better its only going to keep getting harder to develop.

UX:

I'd title the menu, it may not be clear to users what is happening w/o
some
'Add Relation...' menu entry as they may not be familiar with ambiguous
relations and their drag action just turned into something else.

Its now possible to have two relation between the same services. These
will
draw in the same visual space and remove relation will need a way to
control
the selection of which relation is being addressed. It would be a very
special
case to detect if there is more than one relation sharing the same
visual
space, I think a better solution is to develop a way that we can show
both
relations exist which is not possible now. We need a card around
addressing
this. The layout changes we plan to make must take this into account.
Additionally w/o the label disambiguation this case still won't be clear
in
many cases.

https://codereview.appspot.com/6736051/diff/1/app/views/environment.js
File app/views/environment.js (right):

https://codereview.appspot.com/6736051/diff/1/app/views/environment.js#newcode1463
app/views/environment.js:1463:
endpoints[m.id].forEach(function(endpoint) {
On 2012/10/19 18:09:29, thiago wrote:
> You could use handlebars to build the list for you. For example:

> //remove old list, if any
> menu.all('ul').remove();
> .
> .
> .
> //create new <ul><li></li>...<ul> list
> var list = Templates.overviewRelationMenuList({
> endPoints: endpoints
> });

> list.all('li').on('click', ...

> menu.append(list);
> .
> .
> .

> This way you remove some html elements from this js file. wdyt?

Feeding the data to a template is the correct thing to do here. Single
element DOM node creation is ok, but we avoid generating structures
like this.

https://codereview.appspot.com/6736051/diff/1/app/views/environment.js#newcode1488
app/views/environment.js:1488: menu.addClass('active');
setStyles can do these in one call. It does seem like we should be
adding support for scale/translate to Box and be using that for
calculations like this. Even though this is an HTML element we should
still be able to wrap it in a box

box.scaledPosition(scale, translate) -> {x, y, w, h} as with .pos today

https://codereview.appspot.com/6736051/diff/1/app/views/environment.js#newcode1495
app/views/environment.js:1495: role: 'server' }],
I think you're right and we sort the endpoints, but we need to document
were taking advantage of this here, we shouldn't get client/server
wrong.

https://codereview.appspot.com/6736051/diff/1/app/views/envi...

Read more...

Revision history for this message
Kapil Thangavelu (hazmat) wrote :

Looks pretty good. some minors below. could you a new card for the menu
scroll and positioning (ie. if too close to an edge, display on opposite
side).

https://codereview.appspot.com/6736051/diff/3002/app/views/environment.js
File app/views/environment.js (right):

https://codereview.appspot.com/6736051/diff/3002/app/views/environment.js#newcode1076
app/views/environment.js:1076: .ambiguousAddRelationTest(endpoint, self,
rect);
i'd suggest renaming this method, just to avoid the test parlance
outside of unit testing. maybe... addRelationEndpointCheck

https://codereview.appspot.com/6736051/diff/3002/app/views/environment.js#newcode1476
app/views/environment.js:1476: // Add a cancel item.
The cancel item is better at the end, preferably styled as a dialog
cancel button or with red/differentiating text.

https://codereview.appspot.com/6736051/diff/3002/app/views/environment.js#newcode1477
app/views/environment.js:1477: menu.one('.cancel').on('click',
function(evt) {
The menu should also cancel on click outside, the same way the invalid
target fadeout works.

https://codereview.appspot.com/6736051/diff/3002/app/views/environment.js#newcode1483
app/views/environment.js:1483: var tr = view.zoom.translate(),
like the service menu this should also track roughly with the service
container on zoom/pan (the menu shouldn't resize though on zoom).

https://codereview.appspot.com/6736051/diff/3002/app/views/environment.js#newcode1489
app/views/environment.js:1489: // Create a relation with the only
available endpoint.
i think this is better structured with the second clause upfront with a
return at the end of the block, and then the first block can become
dedented.

https://codereview.appspot.com/6736051/diff/3002/test/test_environment_view.js
File test/test_environment_view.js (right):

https://codereview.appspot.com/6736051/diff/3002/test/test_environment_view.js#newcode309
test/test_environment_view.js:309: add_rel =
container.one('#service-menu .add-relation'),
indent looks a little off here.

https://codereview.appspot.com/6736051/

Revision history for this message
Madison Scott-Clary (makyo) wrote :

Cards created in FrontPage.

https://codereview.appspot.com/6736051/diff/3002/app/views/environment.js
File app/views/environment.js (right):

https://codereview.appspot.com/6736051/diff/3002/app/views/environment.js#newcode1076
app/views/environment.js:1076: .ambiguousAddRelationTest(endpoint, self,
rect);
On 2012/10/19 21:48:58, hazmat wrote:
> i'd suggest renaming this method, just to avoid the test parlance
outside of
> unit testing. maybe... addRelationEndpointCheck

Done.

https://codereview.appspot.com/6736051/diff/3002/app/views/environment.js#newcode1476
app/views/environment.js:1476: // Add a cancel item.
On 2012/10/19 21:48:58, hazmat wrote:
> The cancel item is better at the end, preferably styled as a dialog
cancel
> button or with red/differentiating text.

Done.

https://codereview.appspot.com/6736051/diff/3002/app/views/environment.js#newcode1477
app/views/environment.js:1477: menu.one('.cancel').on('click',
function(evt) {
On 2012/10/19 21:48:58, hazmat wrote:
> The menu should also cancel on click outside, the same way the invalid
target
> fadeout works.

Done.

https://codereview.appspot.com/6736051/diff/3002/app/views/environment.js#newcode1483
app/views/environment.js:1483: var tr = view.zoom.translate(),
On 2012/10/19 21:48:58, hazmat wrote:
> like the service menu this should also track roughly with the service
container
> on zoom/pan (the menu shouldn't resize though on zoom).

Done.

https://codereview.appspot.com/6736051/diff/3002/app/views/environment.js#newcode1489
app/views/environment.js:1489: // Create a relation with the only
available endpoint.
On 2012/10/19 21:48:58, hazmat wrote:
> i think this is better structured with the second clause upfront with
a return
> at the end of the block, and then the first block can become dedented.

Done.

https://codereview.appspot.com/6736051/

Revision history for this message
Madison Scott-Clary (makyo) wrote :

*** Submitted:

Implement ambiguous relation menu for adding rels

Displays a menu of choices when adding a relation between two services
would result in ambiguity, otherwise simply adds a relation. Also, a
bit of minor test clean-up in charm config, due to floating point
inequality.

R=thiago, benjamin.saller, hazmat
CC=
https://codereview.appspot.com/6736051

https://codereview.appspot.com/6736051/

Revision history for this message
Kapil Thangavelu (hazmat) wrote :

There's still some minors in the this branch fwiw.. Relation cancel text
should read 'Cancel' not 'None'. The pending relation line should continue
to be displayed while the pending display menu is active. The relation
pairs shoulds shown should be sorted (deterministic order), and there's no
need to indent the pairs.

-k

On Sat, Oct 20, 2012 at 8:21 PM, Matthew Scott
<email address hidden>wrote:

> *** Submitted:
>
> Implement ambiguous relation menu for adding rels
>
> Displays a menu of choices when adding a relation between two services
> would result in ambiguity, otherwise simply adds a relation. Also, a
> bit of minor test clean-up in charm config, due to floating point
> inequality.
>
> R=thiago, benjamin.saller, hazmat
> CC=
> https://codereview.appspot.com/6736051
>
>
> https://codereview.appspot.com/6736051/
>
> --
>
> https://code.launchpad.net/~makyo/juju-gui/ambiguous-relations/+merge/130616
> Your team Juju GUI Hackers is requested to review the proposed merge of
> lp:~makyo/juju-gui/ambiguous-relations into lp:juju-gui.
>

Revision history for this message
Madison Scott-Clary (makyo) wrote :

These should be separate cards if they did not make it into the review. I'm shut down for the night, I'll see about making them tomorrow prior to travel.

~Matthew Scott

PGP key: http://drab-makyo.com/pgp/

(Sent from my phone, responses may be delayed; forgive any typing errors)

On Oct 21, 2012, at 6:13 PM, Kapil Thangavelu <email address hidden> wrote:

> There's still some minors in the this branch fwiw.. Relation cancel text
> should read 'Cancel' not 'None'. The pending relation line should continue
> to be displayed while the pending display menu is active. The relation
> pairs shoulds shown should be sorted (deterministic order), and there's no
> need to indent the pairs.
>
> -k
>
>
> On Sat, Oct 20, 2012 at 8:21 PM, Matthew Scott
> <email address hidden>wrote:
>
>> *** Submitted:
>>
>> Implement ambiguous relation menu for adding rels
>>
>> Displays a menu of choices when adding a relation between two services
>> would result in ambiguity, otherwise simply adds a relation. Also, a
>> bit of minor test clean-up in charm config, due to floating point
>> inequality.
>>
>> R=thiago, benjamin.saller, hazmat
>> CC=
>> https://codereview.appspot.com/6736051
>>
>>
>> https://codereview.appspot.com/6736051/
>>
>> --
>>
>> https://code.launchpad.net/~makyo/juju-gui/ambiguous-relations/+merge/130616
>> Your team Juju GUI Hackers is requested to review the proposed merge of
>> lp:~makyo/juju-gui/ambiguous-relations into lp:juju-gui.
>
> --
> https://code.launchpad.net/~makyo/juju-gui/ambiguous-relations/+merge/130616
> You are the owner of lp:~makyo/juju-gui/ambiguous-relations.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'app/templates/ambiguousRelationList.handlebars'
--- app/templates/ambiguousRelationList.handlebars 1970-01-01 00:00:00 +0000
+++ app/templates/ambiguousRelationList.handlebars 2012-10-19 19:19:23 +0000
@@ -0,0 +1,12 @@
1<ul>
2 <li class="cancel">None</li>
3 {{#relationslist endpoints}}
4 <li
5 data-startservice="{{start.service}}"
6 data-startname="{{start.name}}"
7 data-endservice="{{end.service}}"
8 data-endname="{{end.name}}">
9 {{start.service}}:{{start.name}} &rarr; {{end.service}}:{{end.name}}
10 </li>
11 {{/relationslist}}
12</ul>
013
=== modified file 'app/templates/overview.handlebars'
--- app/templates/overview.handlebars 2012-10-11 10:49:21 +0000
+++ app/templates/overview.handlebars 2012-10-19 19:19:23 +0000
@@ -1,7 +1,7 @@
1<div id="overview">1<div id="overview">
2 <div id="canvas" class="crosshatch-background">2 <div id="canvas" class="crosshatch-background">
3 <div id="service-menu">3 <div class="environment-menu" id="service-menu">
4 <div id="service-menu-triangle">&nbsp;</div>4 <div class="triangle">&nbsp;</div>
5 <ul>5 <ul>
6 <li class="view-service">View</li>6 <li class="view-service">View</li>
7 <li class="add-relation">Build Relation</li>7 <li class="add-relation">Build Relation</li>
@@ -9,6 +9,10 @@
9 <li class="destroy-service">Destroy</li>9 <li class="destroy-service">Destroy</li>
10 </ul>10 </ul>
11 </div>11 </div>
12 <div class="environment-menu" id="ambiguous-relation-menu">
13 <div class="triangle">&nbsp;</div>
14 <ul/>
15 </div>
12 </div>16 </div>
13 <div id="overview-tasks">17 <div id="overview-tasks">
14 <div class="controls yui3-skin-sam">18 <div class="controls yui3-skin-sam">
1519
=== modified file 'app/views/environment.js'
--- app/views/environment.js 2012-10-18 17:52:44 +0000
+++ app/views/environment.js 2012-10-19 19:19:23 +0000
@@ -1016,7 +1016,7 @@
1016 if (curr_action === 'show_service') {1016 if (curr_action === 'show_service') {
1017 this.set('currentServiceClickAction', 'addRelationStart');1017 this.set('currentServiceClickAction', 'addRelationStart');
1018 } else if (curr_action === 'addRelationStart' ||1018 } else if (curr_action === 'addRelationStart' ||
1019 curr_action === 'addRelationEnd') {1019 curr_action === 'ambiguousAddRelationTest') {
1020 this.set('currentServiceClickAction', 'toggleControlPanel');1020 this.set('currentServiceClickAction', 'toggleControlPanel');
1021 } // Otherwise do nothing.1021 } // Otherwise do nothing.
1022 },1022 },
@@ -1073,7 +1073,7 @@
1073 // If we landed on a rect, add relation, otherwise, cancel.1073 // If we landed on a rect, add relation, otherwise, cancel.
1074 if (rect) {1074 if (rect) {
1075 self.service_click_actions1075 self.service_click_actions
1076 .addRelationEnd(endpoint, self, rect);1076 .ambiguousAddRelationTest(endpoint, self, rect);
1077 } else {1077 } else {
1078 // TODO clean up, abstract1078 // TODO clean up, abstract
1079 self.cancelRelationBuild();1079 self.cancelRelationBuild();
@@ -1395,15 +1395,16 @@
1395 var db = view.get('db'),1395 var db = view.get('db'),
1396 app = view.get('app'),1396 app = view.get('app'),
1397 service = view.serviceForBox(m),1397 service = view.serviceForBox(m),
1398 endpoints = models.getEndpoints(
1399 service, app.serviceEndpoints, db),
13981400
1399 /* Transform endpoints into a list of1401 /* Transform endpoints into a list of
1400 * relatable services (to the service in m)1402 * relatable services (to the service in m)
1401 */1403 */
1402 possible_relations = Y.Array.map(1404 possible_relations = Y.Array.map(
1403 Y.Array.flatten(Y.Object.values(1405 Y.Array.flatten(Y.Object.values(
1404 models.getEndpoints(1406 endpoints)),
1405 service, app.serviceEndpoints, db))),1407 function(ep) {return ep.service;}),
1406 function(ep) {return ep.service;}),
1407 invalidRelationTargets = {};1408 invalidRelationTargets = {};
14081409
1409 // Iterate services and invert the possibles list.1410 // Iterate services and invert the possibles list.
@@ -1430,15 +1431,86 @@
14301431
1431 // Store start service in attrs.1432 // Store start service in attrs.
1432 view.set('addRelationStart_service', m);1433 view.set('addRelationStart_service', m);
1434 // Store possible endpoints.
1435 view.set('addRelationStart_possibleEndpoints', endpoints);
1433 // Set click action.1436 // Set click action.
1434 view.set('currentServiceClickAction', 'addRelationEnd');1437 view.set('currentServiceClickAction', 'ambiguousAddRelationTest');
1438 },
1439
1440 /*
1441 * Test if the pending relation is ambiguous. Display a menu if so,
1442 * create the relation if not.
1443 */
1444 ambiguousAddRelationTest: function(m, view, context) {
1445 var endpoints = view.get('addRelationStart_possibleEndpoints'),
1446 container = view.get('container');
1447 if (endpoints[m.id].length > 1) {
1448 // Display menu with available endpoints.
1449 var menu = container.one('#ambiguous-relation-menu'),
1450 list = menu.one('ul');
1451 list.empty();
1452 menu.one('ul').remove(true);
1453
1454 menu.append(Templates
1455 .ambiguousRelationList({endpoints: endpoints[m.id]}));
1456
1457 // For each endpoint choice, bind an an event to 'click' to
1458 // add the specified relation.
1459 menu.all('li').on('click', function(evt) {
1460 if (evt.currentTarget.hasClass('cancel')) {
1461 return;
1462 }
1463 var el = evt.currentTarget,
1464 endpoints_item = [
1465 [el.getData('startservice'), {
1466 name: el.getData('startname'),
1467 role: 'server' }],
1468 [el.getData('endservice'), {
1469 name: el.getData('endname'),
1470 role: 'client' }]];
1471 menu.removeClass('active');
1472 view.service_click_actions
1473 .addRelationEnd(endpoints_item, view, context);
1474 });
1475
1476 // Add a cancel item.
1477 menu.one('.cancel').on('click', function(evt) {
1478 menu.removeClass('active');
1479 view.cancelRelationBuild();
1480 });
1481
1482 // Display the menu at the service endpoint.
1483 var tr = view.zoom.translate(),
1484 z = view.zoom.scale();
1485 menu.setStyle('top', m.y * z + tr[1]);
1486 menu.setStyle('left', m.x * z + m.w * z + tr[0]);
1487 menu.addClass('active');
1488 } else {
1489 // Create a relation with the only available endpoint.
1490 var ep = endpoints[m.id][0],
1491 endpoints_item = [
1492 [ep[0].service, {
1493 name: ep[0].name,
1494 role: 'server' }],
1495 [ep[1].service, {
1496 name: ep[1].name,
1497 role: 'client' }]];
1498 view.service_click_actions
1499 .addRelationEnd(endpoints_item, view, context);
1500 }
1435 },1501 },
14361502
1437 /*1503 /*
1438 * Fired when clicking the second service is clicked in the1504 * Fired when clicking the second service is clicked in the
1439 * add relation flow.1505 * add relation flow.
1506 *
1507 * :param endpoints: array of two endpoints, each in the form
1508 * ['service name', {
1509 * name: 'endpoint type',
1510 * role: 'client or server'
1511 * }]
1440 */1512 */
1441 addRelationEnd: function(m, view, context) {1513 addRelationEnd: function(endpoints, view, context) {
1442 // Redisplay all services1514 // Redisplay all services
1443 view.cancelRelationBuild();1515 view.cancelRelationBuild();
14441516
@@ -1447,9 +1519,9 @@
1447 env = view.get('env'),1519 env = view.get('env'),
1448 db = view.get('db'),1520 db = view.get('db'),
1449 source = view.get('addRelationStart_service'),1521 source = view.get('addRelationStart_service'),
1450 relation_id = 'pending:' + source.id + m.id;1522 relation_id = 'pending:' + endpoints[0][0] + endpoints[1][0];
14511523
1452 if (m.id === source.id) {1524 if (endpoints[0][0] === endpoints[1][0]) {
1453 view.set('currentServiceClickAction', 'toggleControlPanel');1525 view.set('currentServiceClickAction', 'toggleControlPanel');
1454 return;1526 return;
1455 }1527 }
@@ -1459,10 +1531,7 @@
1459 db.relations.create({1531 db.relations.create({
1460 relation_id: relation_id,1532 relation_id: relation_id,
1461 display_name: 'pending',1533 display_name: 'pending',
1462 endpoints: [1534 endpoints: endpoints,
1463 [source.id, {name: 'pending', role: 'server'}],
1464 [m.id, {name: 'pending', role: 'client'}]
1465 ],
1466 pending: true1535 pending: true
1467 });1536 });
14681537
@@ -1473,8 +1542,8 @@
1473 // Fire event to add relation in juju.1542 // Fire event to add relation in juju.
1474 // This needs to specify interface in the future.1543 // This needs to specify interface in the future.
1475 env.add_relation(1544 env.add_relation(
1476 source.id,1545 endpoints[0][0] + ':' + endpoints[0][1].name,
1477 m.id,1546 endpoints[1][0] + ':' + endpoints[1][1].name,
1478 Y.bind(this._addRelationCallback, this, view, relation_id)1547 Y.bind(this._addRelationCallback, this, view, relation_id)
1479 );1548 );
1480 view.set('currentServiceClickAction', 'toggleControlPanel');1549 view.set('currentServiceClickAction', 'toggleControlPanel');
14811550
=== modified file 'app/views/utils.js'
--- app/views/utils.js 2012-10-18 20:19:26 +0000
+++ app/views/utils.js 2012-10-19 19:19:23 +0000
@@ -852,6 +852,17 @@
852 Y.Markdown.toHTML(text));852 Y.Markdown.toHTML(text));
853 });853 });
854854
855 /*
856 * Build a list of relation types given a list of endpoints.
857 */
858 Y.Handlebars.registerHelper('relationslist', function(endpoints, options) {
859 var out = '';
860 endpoints.forEach(function(ep) {
861 out += options.fn({start: ep[0], end: ep[1]});
862 });
863 return out;
864 });
865
855}, '0.1.0', {866}, '0.1.0', {
856 requires: ['base-build',867 requires: ['base-build',
857 'handlebars',868 'handlebars',
858869
=== modified file 'lib/views/stylesheet.less'
--- lib/views/stylesheet.less 2012-10-18 17:50:22 +0000
+++ lib/views/stylesheet.less 2012-10-19 19:19:23 +0000
@@ -142,7 +142,7 @@
142}142}
143143
144144
145#service-menu {145.environment-menu {
146 @border_radius: 20px;146 @border_radius: 20px;
147 @background_color: #282421;147 @background_color: #282421;
148148
@@ -166,7 +166,7 @@
166 display: block;166 display: block;
167 }167 }
168168
169 #service-menu-triangle {169 .triangle {
170 position: absolute;170 position: absolute;
171 top: 62px;171 top: 62px;
172 left: -12px;172 left: -12px;
173173
=== modified file 'test/test_application_notifications.js'
--- test/test_application_notifications.js 2012-10-15 18:18:52 +0000
+++ test/test_application_notifications.js 2012-10-19 19:19:23 +0000
@@ -310,7 +310,11 @@
310 };310 };
311311
312 views.environment.prototype.service_click_actions.addRelationEnd312 views.environment.prototype.service_click_actions.addRelationEnd
313 .apply(view, [{id: 1}, view]);313 .apply(view, [
314 [
315 ['s1', {name: 'n', role: 'client'}],
316 ['s2', {name: 'n', role: 'server'}]],
317 view]);
314318
315 assertNotificationNumber('1');319 assertNotificationNumber('1');
316320
317321
=== modified file 'test/test_charm_configuration.js'
--- test/test_charm_configuration.js 2012-10-18 00:27:33 +0000
+++ test/test_charm_configuration.js 2012-10-19 19:19:23 +0000
@@ -232,7 +232,8 @@
232 // The simulate module does not support firing scroll events so we call232 // The simulate module does not support firing scroll events so we call
233 // the associated method directly.233 // the associated method directly.
234 view._moveTooltip();234 view._moveTooltip();
235 tooltip.get('boundingBox').getY().should.equal(originalY - 10);235 Math.floor(tooltip.get('boundingBox').getY())
236 .should.equal(Math.floor(originalY - 10));
236 });237 });
237238
238 it('must hide the tooltip when its field scrolls away', function() {239 it('must hide the tooltip when its field scrolls away', function() {
239240
=== modified file 'test/test_environment_view.js'
--- test/test_environment_view.js 2012-10-15 10:07:49 +0000
+++ test/test_environment_view.js 2012-10-19 19:19:23 +0000
@@ -299,28 +299,46 @@
299299
300 it('must be able to add a relation from the control panel',300 it('must be able to add a relation from the control panel',
301 function() {301 function() {
302 var view = new views.environment({
303 container: container,
304 app: {serviceEndpoints: {}},
305 db: db,
306 env: env
307 }).render();
308 var service = container.one('.service'),
309 add_rel = container.one('#service-menu .add-relation'),
310 after_evt;
311
302 // Mock endpoints312 // Mock endpoints
303 var existing = models.getEndpoints;313 var existing = models.getEndpoints;
304 models.getEndpoints = function() {314 models.getEndpoints = function() {
305 return {requires: [],315 var endpoints = {},
306 provides: []};316 serviceName = service.one('.name')
317 .getDOMNode().firstChild.nodeValue,
318 nextServiceName = service.next().one('.name')
319 .getDOMNode().firstChild.nodeValue;
320 endpoints[nextServiceName] = [
321 [
322 {
323 service: serviceName,
324 name: 'relName',
325 type: 'relType'
326 },
327 {
328 service: nextServiceName,
329 name: 'relName',
330 type: 'relType'
331 }
332 ]
333 ];
334 return endpoints;
307 };335 };
308336
309 var view = new views.environment({
310 container: container,
311 app: {serviceEndpoints: {}},
312 db: db,
313 env: env
314 }).render();
315 var service = container.one('.service'),
316 add_rel = container.one('#service-menu .add-relation'),
317 after_evt;
318
319 service.simulate('click');337 service.simulate('click');
320 add_rel.simulate('click');338 add_rel.simulate('click');
321 container.all('.selectable-service')339 container.all('.selectable-service')
322 .size()340 .size()
323 .should.equal(1);341 .should.equal(2);
324 service.next().simulate('click');342 service.next().simulate('click');
325 container.all('.selectable-service').size()343 container.all('.selectable-service').size()
326 .should.equal(0);344 .should.equal(0);

Subscribers

People subscribed via source and target branches