brooklyn-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From henev...@apache.org
Subject [27/50] [abbrv] brooklyn-ui git commit: REST api supports batch-style fetch, and app tree is lazily (efficiently) loaded -- so much better for big trees -- and updates dynamically, including status icon
Date Mon, 01 Feb 2016 17:52:11 GMT
REST api supports batch-style fetch, and app tree is lazily (efficiently) loaded -- so much
better for big trees -- and updates dynamically, including status icon


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/869239d1
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/869239d1
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/869239d1

Branch: refs/heads/0.6.0
Commit: 869239d175619aa7a4152405be5dc31f13911187
Parents: e03bb7b
Author: Alex Heneveld <alex.heneveld@cloudsoftcorp.com>
Authored: Tue Sep 17 12:22:08 2013 +0100
Committer: Alex Heneveld <alex.heneveld@cloudsoftcorp.com>
Committed: Wed Sep 18 09:30:06 2013 +0100

----------------------------------------------------------------------
 usage/jsgui/src/main/webapp/assets/css/base.css |   6 +-
 .../src/main/webapp/assets/js/model/app-tree.js |  38 ++-
 .../webapp/assets/js/view/activity-details.js   |   6 +-
 .../assets/js/view/application-explorer.js      |  15 +-
 .../webapp/assets/js/view/application-tree.js   | 282 +++++++++++++------
 .../webapp/assets/js/view/entity-details.js     |   4 +-
 .../src/main/webapp/assets/js/view/viewutils.js |   8 +-
 .../main/webapp/assets/tpl/apps/tree-item.html  |  52 ++--
 8 files changed, 278 insertions(+), 133 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/869239d1/usage/jsgui/src/main/webapp/assets/css/base.css
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/css/base.css b/usage/jsgui/src/main/webapp/assets/css/base.css
index bd69c3e..5904082 100644
--- a/usage/jsgui/src/main/webapp/assets/css/base.css
+++ b/usage/jsgui/src/main/webapp/assets/css/base.css
@@ -539,7 +539,7 @@ ol.tree {
 	color: #54932b !important;
 	text-decoration: none;
 }
-.entity_tree_node.active {
+.entity_tree_node_wrapper.active .entity_tree_node {
     font-weight: bold;
 }
 #tree label {
@@ -568,7 +568,9 @@ line-height: 18px;
     position: relative; 
     float: left;
 }
-
+.entity_tree_node_wrapper {
+	position: relative;
+}
 .tree-box {
     border: 1px solid #AAA;
     border-right: 0px;

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/869239d1/usage/jsgui/src/main/webapp/assets/js/model/app-tree.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/model/app-tree.js b/usage/jsgui/src/main/webapp/assets/js/model/app-tree.js
index 91bc63d..0b2dbde 100644
--- a/usage/jsgui/src/main/webapp/assets/js/model/app-tree.js
+++ b/usage/jsgui/src/main/webapp/assets/js/model/app-tree.js
@@ -1,6 +1,6 @@
 define([
-    "backbone"
-], function (Backbone) {
+    "underscore", "backbone"
+], function (_, Backbone) {
 
     var AppTree = {}
 
@@ -9,21 +9,47 @@ define([
             return {
                 id:"",
                 name:"",
+                type:"",
                 iconUrl:"",
-                children:[]
+                serviceUp:"",
+                serviceState:"",
+                applicationId:"",
+                parentId:"",
+                childrenIds:[]
             }
         },
         getDisplayName:function () {
-            return this.get("name") //+ ":" + this.get("id")
+            return this.get("name")
         },
         hasChildren:function () {
-            return this.get("children").length > 0
+            return this.get("childrenIds").length > 0
         }
     })
 
     AppTree.Collection = Backbone.Collection.extend({
         model:AppTree.Model,
-        url:"/v1/applications/tree"
+        includedEntities: [],
+        getApplications: function () {
+            var entities = [];
+            _.each(this.models, function(it) { if (it.get('id')==it.get('applicationId'))
entities.push(it.get('id')) });
+            return entities;
+        },
+        getNonApplications: function () {
+            var entities = [];
+            _.each(this.models, function(it) { if (it.get('id')!=it.get('applicationId'))
entities.push(it.get('id')) });
+            return entities;
+        },
+        includeEntities: function (entities) {
+            var oldLength = this.includedEntities.length;
+            this.includedEntities = _.uniq(this.includedEntities.concat(entities))
+            return (this.includedEntities.length > oldLength);
+        },
+        url: function() {
+            if (this.includedEntities.length)
+                return "/v1/applications/fetch?items="+this.includedEntities.join(",");
+            else
+                return "/v1/applications/fetch";
+        }
     })
 
     return AppTree

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/869239d1/usage/jsgui/src/main/webapp/assets/js/view/activity-details.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/view/activity-details.js b/usage/jsgui/src/main/webapp/assets/js/view/activity-details.js
index c8079fd..1466bca 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/activity-details.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/activity-details.js
@@ -80,7 +80,7 @@ define([
             }
             this.renderSubtasks()
         
-            this.callPeriodically("refreshNow", function () {
+            this.callPeriodically("refresh-activities-now", function () {
                 this.refreshNow()
             }, 1000);
 
@@ -158,7 +158,7 @@ define([
                 this.children = new TaskSummary.Collection()
                 this.children.url = this.task.get("links").children
                 this.children.on("reset", this.renderChildren, this)
-                this.callPeriodically("refreshChildren", function () {
+                this.callPeriodically("refresh-activity-children", function () {
                     that.children.fetch({reset: true});
                 }, 3000);
                 that.children.fetch({reset: true});
@@ -169,7 +169,7 @@ define([
                         that.collection = new TaskSummary.Collection()
                         that.collection.url = entity.links.activities
                         that.collection.on("reset", this.renderSubtasks, this)
-                        that.callPeriodically("refreshSubmittedTasks", function () {
+                        that.callPeriodically("refresh-activity-bgtasks", function () {
                             that.collection.fetch({reset: true});
                         }, 3000);
                         that.collection.fetch({reset: true});

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/869239d1/usage/jsgui/src/main/webapp/assets/js/view/application-explorer.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/view/application-explorer.js b/usage/jsgui/src/main/webapp/assets/js/view/application-explorer.js
index d6837e7..4cd2008 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/application-explorer.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/application-explorer.js
@@ -15,11 +15,12 @@ define([
         id:'application-explorer',
         template:_.template(PageHtml),
         events:{
-            'click .application-tree-refresh': 'refreshApplications',
+            'click .application-tree-refresh': 'refreshApplicationsInPlace',
             'click #add-new-application':'createApplication',
             'click .delete':'deleteApplication'
         },
         initialize:function () {
+            var that = this;
             this.$el.html(this.template({}))
             $(".nav1").removeClass("active");
             $(".nav1_apps").addClass("active");
@@ -28,8 +29,10 @@ define([
             this.treeView = new ApplicationTreeView({
                 collection:this.collection
             })
-            this.$('div#app-tree').html(this.treeView.render().el)
-            this.treeView.render()
+            this.$('div#app-tree').html(this.treeView.renderFull().el)
+            this.refreshApplications();
+            that.callPeriodically("entity-tree-apps", 
+                    function() { that.refreshApplicationsInPlace() }, 3000)
         },
         beforeClose:function () {
             this.collection.off("reset", this.render)
@@ -43,6 +46,10 @@ define([
             this.collection.fetch({reset: true})
             return false
         },
+        refreshApplicationsInPlace:function () {
+            this.collection.fetch()
+            return false
+        },
         show: function(entityId) {
             this.treeView.displayEntityId(entityId)
         },
@@ -57,7 +64,7 @@ define([
             }
             var wizard = new AppAddWizard({
             	appRouter:that.options.appRouter,
-            	callback:function() { that.refreshApplications() }
+            	callback:function() { that.refreshApplicationsInPlace() }
         	})
             this._modal = wizard
             this.$(".add-app #modal-container").html(wizard.render().el)

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/869239d1/usage/jsgui/src/main/webapp/assets/js/view/application-tree.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/view/application-tree.js b/usage/jsgui/src/main/webapp/assets/js/view/application-tree.js
index 9e1cc73..db1c679 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/application-tree.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/application-tree.js
@@ -24,16 +24,130 @@ define([
         },
 
         initialize:function () {
-            this.collection.on('reset', this.render, this)
+            this.collection.on('all', this.modelEvent, this)
+            this.collection.on('change', this.modelChange, this)
+            this.collection.on('remove', this.modelRemove, this)
+            this.collection.on('add', this.modelAdd, this)
+            this.collection.on('reset', this.renderFull, this)
             _.bindAll(this);
         },
 
         beforeClose:function () {
-            this.collection.off("reset", this.render)
+            this.collection.off("reset", this.renderFull)
             if (this.detailsView) this.detailsView.close()
         },
+        
+        modelChange: function (child) {
+            this.updateNode(child.id)
+        },
+        modelAdd: function (child) {
+            this.updateNode(child.id)
+        },
+        modelRemove: function (child) {
+            this.removeNode(child.id)
+        },
+        modelEvent: function (eventName, event, x) {
+            if (eventName == "change" || eventName == "remove" || eventName == "add" ||
+                    eventName == "reset" ||
+                    // above are handled; below is no-op
+                    eventName == "sync" || eventName == "request")
+                return;
+
+            // don't think we get other events, but just in case:
+            log("unhandled model event")
+            log(eventName)
+            log(event)
+            log(x)
+        },
+
+        removeNode: function(id) {
+            $('#'+id, this.$el).parent().remove()
+        },
+        
+        updateNode: function(id, parentId, isApp) {
+            var that = this;
+            var nModel = that.collection.get(id);
+            var nEl = $('#'+id, that.$el)
+            
+            if (!isApp) {
+                // autodiscover whether this is an app, looking at the model and the tree
+                // (at least one should be available -- probably always the former, but...)
+                if (nModel) { isApp = (id == nModel.get('applicationId')); }
+                else if (!isApp && nEl && nEl.parent().data('depth')==0)
isApp = true;
+            }
 
-        render:function () {
+            if (!isApp && !parentId && nModel) parentId = nModel.get('parentId');
+            if (!isApp && !parentId && nEl) parentId = nEl.closest("entity_tree_node_wrapper").data('parentId');
+            if (!isApp && !parentId) {
+                log("no parentId yet available for "+id+"; skipping;")
+                return false;                
+            }
+            
+            var statusIconUrl = nModel ? ViewUtils.computeStatusIcon(nModel.get("serviceUp"),nModel.get("serviceState"))
: null;
+            
+            var nEl2 = this.template({
+                id:id,
+                parentId:parentId,
+                model:nModel,
+                statusIconUrl:statusIconUrl
+            })
+
+            if (!nEl.length) {
+                // node does not exist, so add it
+                var pElC, depth;
+                
+                if (isApp) {
+                    pElC = $('.lozenge-app-tree-wrapper', that.$el);
+                    if (!pElC.length) {
+                        // entire view must be created
+                        that.$el.html(
+                                '<div class="navbar_main_wrapper treeloz">'+
+                                '<div id="tree-list" class="navbar_main treeloz">'+
+                                '<div class="lozenge-app-tree-wrapper">'+
+                                '</div></div></div>');
+                        pElC = $('.lozenge-app-tree-wrapper', that.$el);
+                    }
+                    depth = 0;
+                } else {
+                    var pEl = $('#'+parentId, that.$el)
+                    if (!pEl.length) {
+                        // see if we can load the parent
+                        if (this.updateNode(parentId)) {
+                            pEl = $('#'+parentId, that.$el);
+                            if (!pEl.length) {
+                                log("no parent element yet available for "+id+" ("+parentId+")
after parent load; skipping")
+                                return false;                                
+                            }
+                        } else {
+                            log("no parent element yet available for "+id+" ("+parentId+");
skipping")
+                            return false;
+                        }
+                    }
+                    pElC = pEl.parent().children('.node-children')
+                    depth = pEl.parent().data("depth")+1
+                }
+
+                // add it, with surrounding html, in parent's node-children child
+                var nEl3 = $(
+                        '<div class="toggler-group tree-box '+
+                            (depth==0 ? "outer" : "inner "+(depth%2==1 ? "depth-odd" : "depth-even")+
+                                (depth==1 ? " depth-first" : "")) + '" data-depth="'+depth+'">'+
+                        '<div id="'+id+'" class="entity_tree_node_wrapper"></div>'+
+                        '<div class="toggler-target hide node-children"></div>'+
+                        '</div>')
+                        
+                $('#'+id, nEl3).html(nEl2);
+                $(pElC).append(nEl3);
+                this.addEventsToNode($(pElC))
+            } else {
+                // updating
+                $(nEl).html(nEl2)
+                this.addEventsToNode($(nEl))
+            }
+            return true
+        },
+        
+        renderFull:function () {
             var that = this
             this.$el.empty()
 
@@ -41,16 +155,13 @@ define([
             if (this.collection.isEmpty()) {
                 that.$el.append(_.template(TreeEmptyHtml))
             } else {
-                that.$el.append(
-                        '<div class="navbar_main_wrapper treeloz">'+
-                        '<div id="tree-list" class="navbar_main treeloz">'+
-                        '<div class="lozenge-app-tree-wrapper">');
-                var node = $('div.lozenge-app-tree-wrapper', that.$el);
+                _.each(this.collection.getApplications(),
+                        function(appId) { that.updateNode(appId, null, true) })
                 
-                this.collection.each(function (app) {
-                    node.append(that.buildTree(app))
-                })
+                _.each(this.collection.getNonApplications(),
+                        function(id) { that.updateNode(id) })
             }
+            
             this.highlightEntity();
 
             // Render the details for the selected entity.
@@ -74,61 +185,15 @@ define([
             return this
         },
 
-        buildTree:function (application) {
-            var that = this,
-                $template = $(this.template({
-                    id:application.get("id"),
-                    type:"application",
-                    hasChildren: application.hasChildren(),
-                    parentApp:application.get("id"),
-                    displayName:application.get("name"),
-                    iconUrl:application.get("iconUrl"),
-                    statusIconUrl: ViewUtils.computeStatusIcon(application.get("serviceUp"),application.get("serviceState")),
-                    depth: 0
-                })),
-                treeFromEntity = function (entity, depth) {
-                    var $entityTpl
-
-                    if (entity.hasChildren()) {
-                        $entityTpl = $(that.template({
-                            id:entity.get("id"),
-                            type:"entity",
-                            hasChildren: true,
-                            parentApp:application.get("id"),
-                            displayName:entity.getDisplayName(),
-                            iconUrl:entity.get("iconUrl"),
-                            statusIconUrl: ViewUtils.computeStatusIcon(entity.get("serviceUp"),entity.get("serviceState")),
-                            depth: depth
-                        }))
-                        var $parentTpl = $entityTpl.find("#children")
-                        _.each(entity.get("children"), function (childEntity) {
-                            $parentTpl.append(treeFromEntity(new AppTree.Model(childEntity),
depth+1))
-                        })
-                    } else {
-                        $entityTpl = $(that.template({
-                            id:entity.get("id"),
-                            type:"leaf",
-                            hasChildren: false,
-                            parentApp:application.get("id"),
-                            displayName:entity.getDisplayName(),
-                            iconUrl:entity.get("iconUrl"),
-                            statusIconUrl: ViewUtils.computeStatusIcon(entity.get("serviceUp"),entity.get("serviceState")),
-                            depth: depth
-                        }))
-                    }
-                    return $entityTpl
-                }
-
-            // start rendering from initial children of the application
-            var $tree = $template.find("#children")
-            _.each(application.get("children"), function (entity) {
-                $tree.append(treeFromEntity(new AppTree.Model(entity), 1))
-            })
-            $('a', $tree).click(function(e) { e.preventDefault(); })
+        addEventsToNode: function($node) {
+            var that = this;
+            
+            // prevent default click-handling (not sure needed?)
+            $('a', $node).click(function(e) { e.preventDefault(); })
             
             // show the "light-popup" (expand / expand all / etc) menu
             // if user hovers for 500ms. surprising there is no option for this.
-            $('.light-popup', $template).parent().parent().hover(
+            $('.light-popup', $node).parent().parent().hover(
                     function (parent) {
                         that.cancelHoverTimer();
                         that.hoverTimer = setTimeout(function() {
@@ -142,8 +207,6 @@ define([
                         menu.hide()
                         $('.light-popup').hide()
                     })
-
-            return $template
         },
         cancelHoverTimer: function() {
             var that = this;
@@ -157,7 +220,7 @@ define([
             event.preventDefault();
             var nodeSpan = $(event.currentTarget)
             var nodeA = $(event.currentTarget).children('a').first()
-            var entityId = nodeSpan.attr("id"),
+            var entityId = nodeSpan.parent().attr("id"),
                 stateId = entityId,
                 href = nodeA.attr('href'),
                 tab = (this.detailsView)
@@ -170,16 +233,14 @@ define([
                     this.preselectTab(tab)
                 }
                 window.history.pushState(stateId, "", href)
-                this.displayEntityId(entityId, $(event.currentTarget).data("parent-app"));
+                this.displayEntityId(entityId, nodeSpan.data("app-id"));
             } else {
                 log("no a.href in clicked target")
                 log(nodeSpan)
             }
         },
-
-        displayEntityId:function (id, appName) {
+        displayEntityId:function (id, appName, afterLoad) {
             var that = this;
-            console.debug("Displaying entity: " + id);
             this.highlightEntity(id)
 
             var entityLoadFailed = function() {
@@ -187,14 +248,25 @@ define([
             };
 
             if (appName === undefined) {
-                appName = $("span.entity_tree_node#"+id).data("parent-app")
+                appName = $("#span-"+id).data("app-id")
             }
             if (appName === undefined) {
-                // no such app
-                console.error("Couldn't find a parent application for entity: " + id);
-                return entityLoadFailed();
+                if (!afterLoad) {
+                    // try a reload if given an ID we don't recognise
+                    this.collection.includeEntities([id]);
+                    this.collection.fetch({
+                        success: function() { _.defer(function() { that.displayEntityId(id,
appName, true); }); },
+                        error: function() { _.defer(function() { that.displayEntityId(id,
appName, true); }); }
+                    });
+                    ViewUtils.fadeToIndicateInitialLoad($("div#details"))
+                    return;
+                } else {
+                    // no such app
+                    entityLoadFailed();
+                    return; 
+                }
             }
-
+            
             var app = new Application.Model(),
                 entitySummary = new EntitySummary.Model;
 
@@ -203,11 +275,10 @@ define([
 
             // in case the server response time is low, fade out while it refreshes
             // (since we can't show updated details until we've retrieved app + entity details)
-            $("div#details").fadeTo(1000, 0.3)
+            ViewUtils.fadeToIndicateInitialLoad($("div#details"))
             
             $.when(app.fetch(), entitySummary.fetch())
                 .done(function() {
-                    $("div#details").stop().fadeTo(200, 1)
                     that.showDetails(app, entitySummary);
                 })
                 .fail(entityLoadFailed);
@@ -215,6 +286,7 @@ define([
 
         displayEntityNotFound: function(id) {
             $("div#details").html(notFoundTemplate({"id": id}));
+            ViewUtils.cancelFadeOnceLoaded($("div#details"))
         },
 
         treeChange: function(event) {
@@ -230,7 +302,7 @@ define([
                 this.hideChildrenOf($treeBox, true)
             } else {
                 // default - toggle
-                if ($treeBox.children('#children').is(':visible')) {
+                if ($treeBox.children('.node-children').is(':visible')) {
                     this.hideChildrenOf($treeBox, false)
                 } else {
                     this.showChildrenOf($treeBox, false)
@@ -244,20 +316,40 @@ define([
         },
         hideChildrenOf: function($treeBox, recurse) {
             var that = this;
-            $treeBox.children('#children').slideUp(300)
-            $treeBox.children('.tree-node').find('.tree-node-state').removeClass('icon-chevron-down').addClass('icon-chevron-right')
             if (recurse) {
-                $treeBox.children('#children').children().each(function (index, childBox)
{
+                $treeBox.children('.node-children').children().each(function (index, childBox)
{
                     that.hideChildrenOf($(childBox), recurse)
                 })
             }
+            $treeBox.children('.node-children').slideUp(300)
+            $treeBox.children('.entity_tree_node_wrapper').find('.tree-node-state').removeClass('icon-chevron-down').addClass('icon-chevron-right')
         },
         showChildrenOf: function($treeBox, recurse) {
             var that = this;
-            $treeBox.children('#children').slideDown(300)
-            $treeBox.children('.tree-node').find('.tree-node-state').removeClass('icon-chevron-right').addClass('icon-chevron-down')
           
+            var idToExpand = $treeBox.children('.entity_tree_node_wrapper').attr('id');
+            var model = this.collection.get(idToExpand);
+            if (model==null) {
+                // not yet loaded; parallel thread should load
+                return;
+            }
+            var childrenIds = model.get('childrenIds');
+            _.each(childrenIds, function(id) { that.updateNode(id, idToExpand) })
+            if (this.collection.includeEntities(childrenIds)) {
+                // we have to load entities before we can proceed
+                this.collection.fetch({
+                    success: function() {
+                        if (recurse) {
+                            $treeBox.children('.node-children').children().each(function
(index, childBox) {
+                                _.defer( function() { that.showChildrenOf($(childBox), recurse)
} );
+                            })
+                        }                        
+                    }
+                })
+            }
+            $treeBox.children('.node-children').slideDown(300)
+            $treeBox.children('.entity_tree_node_wrapper').find('.tree-node-state').removeClass('icon-chevron-right').addClass('icon-chevron-down')
           
             if (recurse) {
-                $treeBox.children('#children').children().each(function (index, childBox)
{
+                $treeBox.children('.node-children').children().each(function (index, childBox)
{
                     that.showChildrenOf($(childBox), recurse)
                 })
             }
@@ -272,6 +364,8 @@ define([
         },
 
         showDetails: function(app, entitySummary) {
+            ViewUtils.cancelFadeOnceLoaded($("div#details"))
+            
             var whichTab = this.currentTab
             if (whichTab === undefined) {
                 whichTab = "summary";
@@ -295,12 +389,22 @@ define([
         highlightEntity:function (id) {
         	if (id) this.selectedEntityId = id
         	else id = this.selectedEntityId
-        	$("span.entity_tree_node").removeClass("active")
+        	
+        	$(".entity_tree_node_wrapper").removeClass("active")
         	if (id) {
-        	    var $selectedNode = $("span.entity_tree_node#"+id);
-        		$selectedNode.addClass("active")
-        		// if we wanted to auto-expand the children of the selected node:
-//        		this.showChildrenOf($selectedNode.parents('#app-tree .tree-box'), false)
+        	    var $selectedNode = $(".entity_tree_node_wrapper#"+id);
+        	    // make this node active
+        	    $selectedNode.addClass("active")
+        	    
+        		// open the parent nodes if needed
+        		var $nodeToOpenInParent = $selectedNode;
+        		while ($nodeToOpenInParent.length && !$nodeToOpenInParent.is(':visible'))
{
+        		    $nodeToOpenInParent = $nodeToOpenInParent.closest('.node-children').closest('.tree-box');
+        		    this.showChildrenOf($nodeToOpenInParent)
+        		}
+        		
+        		// if we want to auto-expand the children of the selected node:
+//        		this.showChildrenOf($selectedNode.closest('.tree-box'), false)
         	}
         }
     })

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/869239d1/usage/jsgui/src/main/webapp/assets/js/view/entity-details.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/view/entity-details.js b/usage/jsgui/src/main/webapp/assets/js/view/entity-details.js
index 11aa62e..0028b40 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/entity-details.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/entity-details.js
@@ -61,8 +61,8 @@ define([
         },
         tabSelected: function(event) {
             var tabName = $(event.currentTarget).attr("href").slice(1)
-            var entityId = $("#app-tree span.active").attr("id")
-            var entityHref = $("#app-tree span.active a").attr("href")
+            var entityId = $("#app-tree .entity_tree_node_wrapper.active").attr("id")
+            var entityHref = $("#app-tree .entity_tree_node_wrapper.active a").attr("href")
             if (entityId && entityHref) {                
                 window.history.pushState(entityId+"/"+tabName, "", 
                     entityHref+"/"+tabName);

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/869239d1/usage/jsgui/src/main/webapp/assets/js/view/viewutils.js
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/js/view/viewutils.js b/usage/jsgui/src/main/webapp/assets/js/view/viewutils.js
index ae9dbb7..a30635c 100644
--- a/usage/jsgui/src/main/webapp/assets/js/view/viewutils.js
+++ b/usage/jsgui/src/main/webapp/assets/js/view/viewutils.js
@@ -226,18 +226,18 @@ define([
         processTooltips: function($el) {
             $el.find('*[rel="tooltip"]').tooltip();
         },
-        fadeToIndicateInitialLoad: function($table) {
+        fadeToIndicateInitialLoad: function($el) {
             // in case the server response time is low, fade out while it refreshes
             // (since we can't show updated details until we've retrieved app + entity details)
             try {                
-                $table.fadeTo(1000, 0.3);
+                $el.fadeTo(1000, 0.3);
             } catch (e) {
                 // ignore - normal during tests
             }
         },
-        cancelFadeOnceLoaded: function($table) {
+        cancelFadeOnceLoaded: function($el) {
             try {
-                $table.stop().fadeTo(200, 1);
+                $el.stop(true, false).fadeTo(200, 1);
             } catch (e) {
                 // ignore - normal during tests
             }

http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/869239d1/usage/jsgui/src/main/webapp/assets/tpl/apps/tree-item.html
----------------------------------------------------------------------
diff --git a/usage/jsgui/src/main/webapp/assets/tpl/apps/tree-item.html b/usage/jsgui/src/main/webapp/assets/tpl/apps/tree-item.html
index 82fcef3..4eb7e50 100644
--- a/usage/jsgui/src/main/webapp/assets/tpl/apps/tree-item.html
+++ b/usage/jsgui/src/main/webapp/assets/tpl/apps/tree-item.html
@@ -1,26 +1,34 @@
-<div class="toggler-group tree-box <%= 
-    depth==0 ? "outer" : "inner "+(depth%2==1 ? "depth-odd" : "depth-even")+(depth==1 ? "
depth-first" : "") %>">
-  <div class="tree-node">
-    <span class="entity_tree_node name entity" id="<%= id %>" data-entity-type="<%=
type %>" data-parent-app="<%= parentApp %>">
-      <a href="#/v1/applications/<%= parentApp %>/entities/<%= id %>">
+<%
+    var isLoaded = (model ? true : false);
+    var isApp = (parentId ? false : true);
     
-    <%
-        var isApp = type == "application";
+    if (!isLoaded) {
+%>
+        <i>Loading... (<%= id %>)</i>
+<%  } else {
+        var hasChildren = model.hasChildren();
+        var iconUrl = model.get('iconUrl');
+                 
         var entityIconSize = isApp ? 40 : 30;
         var statusIconSize = isApp ? 24 : 16;
         
-        var chevronLeft = isApp ? 5.5 : 1.5;
+        var chevronLeft = (isApp ? 5.5 : 1.5);
         var minHeight = hasChildren && statusIconUrl ? entityIconSize : 24;
         var statusColumnWidth = hasChildren || statusIconUrl || (!isApp && !iconUrl
/* for children, insert space so things line up */) ? statusIconSize : 0;
-    %>
-    <div style="min-width: <%= statusColumnWidth + (iconUrl ? entityIconSize : 6)%>px;
min-height: <%= minHeight %>px; max-height: 40px; display: inline-block; margin-right:
4px; vertical-align: middle;">
+%>
+  
+  <span class="entity_tree_node name entity" id="span-<%= id %>" 
+        data-entity-type="<%= model.get('type') %>" data-parent-id="<%= parentId
%>" data-app-id="<%= model.get('applicationId') %>">
+    <a href="#/v1/applications/<%= model.get('applicationId') %>/entities/<%=
id %>">
+    
+      <div style="min-width: <%= statusColumnWidth + (iconUrl ? entityIconSize : 6)%>px;
min-height: <%= minHeight %>px; max-height: 40px; display: inline-block; margin-right:
4px; vertical-align: middle;">
         <% if (statusIconUrl) { %>
         <div style="position: absolute; left: 0px; margin: auto; top: <%= isApp &&
hasChildren ? 3 : 2 %>px;<% if (!hasChildren) { %> bottom: 0px;<% } %>">
-            <img src="<%= statusIconUrl %>" style="max-width: <%= statusIconSize
%>px; max-height: <%= statusIconSize %>px; margin: auto; position: absolute; top:
0px;<% if (!hasChildren) { %> bottom: 0px;<% } %>">
+            <img src="<%= statusIconUrl %>" style="max-width: <%= statusIconSize
%>px; max-height: <%= statusIconSize %>px; margin: auto; position: absolute; top:
-1px;<% if (!hasChildren) { %> bottom: 0px;<% } %>">
         </div>
         <% } %>
         <% if (hasChildren) { %>
-        <div style="position: absolute; left: <%= chevronLeft %>px; margin: auto;
<%= statusIconUrl ? "bottom: 1px;" : isApp ? "top: 6px;" : "top: 6px;" %>">
+        <div style="position: absolute; left: <%= chevronLeft %>px; margin: auto;
<%= statusIconUrl ? "bottom: -1px;" : isApp ? "top: 6px;" : "top: 6px;" %>">
             <div class="toggler-icon icon-chevron-right tree-node-state tree-change">
                 <div class="light-popup">
                     <div class="light-popup-body">
@@ -34,16 +42,14 @@
             </div>
         </div>
         <% } %>
-    <% if (iconUrl) { %>
-        <img src="<%= iconUrl %>" style="max-width: <%= entityIconSize %>px;
max-height: <%= entityIconSize %>px; position: absolute; left: <%= statusColumnWidth
%>px; top: 0; bottom: 0; margin: auto;">
-    <% } %>
-    </div>
+        <% if (iconUrl) { %>
+            <img src="<%= iconUrl %>" style="max-width: <%= entityIconSize %>px;
max-height: <%= entityIconSize %>px; position: absolute; left: <%= statusColumnWidth
%>px; top: 0; bottom: 0; margin: auto;">
+        <% } %>
+      </div>
      
-        <span style="max-height: 18px; position: relative; margin: auto; top: 2px; bottom:
0;"><%= displayName %></span>
+      <span style="max-height: 18px; padding-right: 6px; position: relative; margin: auto;
top: 2px; bottom: 0;"><%= model.get('name') %></span>
          
-      </a>
-    </span>
-  </div>
-  <div id="children" class="toggler-target hide">
-  </div>
-</div>
+    </a>
+  </span>
+
+<% } %>
\ No newline at end of file


Mime
View raw message