You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2016/03/03 13:29:52 UTC
[07/10] brooklyn-ui git commit: fix browser forward-back navigation,
activity tab stale, and sort order
fix browser forward-back navigation, activity tab stale, and sort order
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/e22ba57e
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/e22ba57e
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/e22ba57e
Branch: refs/heads/master
Commit: e22ba57ed54e21f0b5bd492ab804da9731840e05
Parents: 3081c67
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Mar 3 01:48:58 2016 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Mar 3 01:49:54 2016 +0000
----------------------------------------------------------------------
src/main/webapp/assets/js/router.js | 6 +-
.../assets/js/view/application-explorer.js | 43 ++++---
.../webapp/assets/js/view/application-tree.js | 115 +++++++++++++------
.../webapp/assets/js/view/entity-details.js | 8 +-
4 files changed, 117 insertions(+), 55 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/e22ba57e/src/main/webapp/assets/js/router.js
----------------------------------------------------------------------
diff --git a/src/main/webapp/assets/js/router.js b/src/main/webapp/assets/js/router.js
index 1d6dae4..aaccf70 100644
--- a/src/main/webapp/assets/js/router.js
+++ b/src/main/webapp/assets/js/router.js
@@ -197,10 +197,12 @@ define([
this.appTree.fetch({success:function () {
var appExplorer = new ExplorerView({
collection:that.appTree,
- appRouter:that
- })
+ appRouter:that,
+ initialTrail:trail
+ });
that.showView("#application-content", appExplorer)
if (trail !== undefined) appExplorer.show(trail)
+ else appExplorer.showDefaultSelection();
}})
},
catalogPage: function (catalogItemKind, id) {
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/e22ba57e/src/main/webapp/assets/js/view/application-explorer.js
----------------------------------------------------------------------
diff --git a/src/main/webapp/assets/js/view/application-explorer.js b/src/main/webapp/assets/js/view/application-explorer.js
index 475432a..cc5eb0b 100644
--- a/src/main/webapp/assets/js/view/application-explorer.js
+++ b/src/main/webapp/assets/js/view/application-explorer.js
@@ -49,10 +49,12 @@ define([
collection:this.collection,
appRouter:this.options.appRouter
})
+ if (this.options.initialTrail) this.show(this.options.initialTrail, true);
this.treeView.on('entitySelected', function(e) {
this.displayEntityId(e.id, e.get('applicationId'), false);
}, this);
- this.$('div#app-tree').html(this.treeView.renderFull().el)
+ // don't draw these -- wait for the "show" command
+ this.$('div#app-tree').html(this.treeView.renderFull().el);
this.$('div#details').html(EntityDetailsEmptyHtml);
ViewUtils.fetchRepeatedlyWithDelay(this, this.collection)
@@ -68,7 +70,7 @@ define([
if (this.detailsView)
this.detailsView.close();
},
- show: function(entityId) {
+ show: function(entityId, isPre) {
var tab = "";
var tabDetails = "";
if (entityId) {
@@ -88,8 +90,15 @@ define([
this.preselectTab(tab, tabDetails);
}
if (!this.treeView.selectEntity(entityId)) {
- // needs a load
- this.displayEntityId(entityId);
+ // needs a load, but only allowed if not pre-loading
+ if (isPre) { /* don't allow loading if this is a "pre-show" */ }
+ else { this.displayEntityId(entityId); }
+ }
+ },
+ showDefaultSelection: function() {
+ if (!this.treeView.selectedEntityId && !this.treeView.requestedEntityId) {
+ var firstApp = _.first(this.collection.getApplications());
+ if (firstApp) this.treeView.selectEntity(firstApp);
}
},
createApplication:function () {
@@ -124,22 +133,27 @@ define([
var that = this;
ViewUtils.cancelFadeOnceLoaded($("div#details"));
- var whichTab = this.currentTab;
- if (!whichTab) {
- whichTab = "summary";
- if (this.detailsView) {
- whichTab = this.detailsView.$el.find(".tab-pane.active").attr("id");
- this.detailsView.close();
- }
- }
if (this.detailsView) {
+ // if view open, take that tab, but clear the details if the id is different
+ if (this.detailsView.model && this.detailsView.model.id && this.detailsView.model.id != entitySummary.id)
+ this.detailsView.options.preselectTabDetails = null;
+ this.preselectTab(
+ //this.detailsView.$el.find(".tab-pane.active").attr("id")
+ this.detailsView.options.preselectTab,
+ this.detailsView.options.preselectTabDetails
+ );
this.detailsView.close();
}
+ if (!this.currentTab) {
+ // else if nothing preselect, use summary
+ this.preselectTab("summary");
+ }
+
this.detailsView = new EntityDetailsView({
model: entitySummary,
application: app,
appRouter: this.options.appRouter,
- preselectTab: whichTab,
+ preselectTab: this.currentTab,
preselectTabDetails: this.currentTabDetails,
});
@@ -159,6 +173,9 @@ define([
that.collection.fetch();
});
this.detailsView.render( $("div#details") );
+ // force the routes to be updated, and clear activities detail possibly (the tab is already shown)
+ // (this causes activities view to lose selected sub-tasks, but that's okay)
+ this.detailsView.openTab(this.currentTab + (this.currentTabDetails ? '/'+this.currentTabDetails : ''));
},
displayEntityId: function (id, appName, afterLoad) {
var that = this;
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/e22ba57e/src/main/webapp/assets/js/view/application-tree.js
----------------------------------------------------------------------
diff --git a/src/main/webapp/assets/js/view/application-tree.js b/src/main/webapp/assets/js/view/application-tree.js
index 5a6d114..0d9f4fb 100644
--- a/src/main/webapp/assets/js/view/application-tree.js
+++ b/src/main/webapp/assets/js/view/application-tree.js
@@ -33,8 +33,8 @@ define([
return $('.tree-box[data-entity-id="' + id + '"]', $scope);
};
- var findRootTreebox = function(id) {
- return $('.lozenge-app-tree-wrapper').children('.tree-box[data-entity-id="' + id + '"]', this.$el);
+ var findRootTreebox = function(id, $scope) {
+ return $('.lozenge-app-tree-wrapper', $scope).children('.tree-box[data-entity-id="' + id + '"]', this.$el);
};
var findChildTreebox = function(id, $parentTreebox) {
@@ -45,24 +45,17 @@ define([
return $('.tree-box[data-entity-id="' + id + '"]:not(.indirect)', $scope);
};
- var createEntityTreebox = function(id, name, $domParent, depth, indirect) {
- // Tildes in sort key force entities with no name to bottom of list (z < ~).
- var sortKey = (name ? name.toLowerCase() : "~~~") + " " + id.toLowerCase();
-
- // Create the wrapper.
- var $treebox = $(
- '<div data-entity-id="'+id+'" data-sort-key="'+sortKey+'" data-depth="'+depth+'" ' +
- 'class="tree-box toggler-group' +
- (indirect ? " indirect" : "") +
- (depth == 0 ? " outer" : " inner " + (depth % 2 ? " depth-odd" : " depth-even")+
- (depth == 1 ? " depth-first" : "")) + '">'+
- '<div class="entity_tree_node_wrapper"></div>'+
- '<div class="node-children toggler-target hide"></div>'+
- '</div>');
-
- // Insert into the passed DOM parent, maintaining sort order relative to siblings: name then id.
+ var sortKeyOfIdName = function(id, name) {
+ return (name ? name.toLowerCase() : "~~~") + " " + id.toLowerCase();
+ };
+ var sortKeyOfEntity = function(entity) {
+ return sortKeyOfIdName(entity.id, entity.get('name'));
+ };
+
+ var insertSorted = function($treebox, $domParent) {
var placed = false;
var contender = $(".toggler-group", $domParent).first();
+ var sortKey = $treebox.data('sort-key');
while (contender.length && !placed) {
var contenderKey = contender.data("sort-key");
if (sortKey < contenderKey) {
@@ -77,11 +70,29 @@ define([
}
return $treebox;
};
+ var createEntityTreebox = function(id, name, $domParent, depth, indirect) {
+ // Tildes in sort key force entities with no name to bottom of list (z < ~).
+ var sortKey = sortKeyOfIdName(id, name);
+ // Create the wrapper.
+ var $treebox = $(
+ '<div data-entity-id="'+id+'" data-sort-key="'+sortKey+'" data-depth="'+depth+'" ' +
+ 'class="tree-box toggler-group' +
+ (indirect ? " indirect" : "") +
+ (depth == 0 ? " outer" : " inner " + (depth % 2 ? " depth-odd" : " depth-even")+
+ (depth == 1 ? " depth-first" : "")) + '">'+
+ '<div class="entity_tree_node_wrapper"></div>'+
+ '<div class="node-children toggler-target hide"></div>'+
+ '</div>');
- var getOrCreateApplicationTreebox = function(id, name, treeView) {
- var $treebox = findRootTreebox(id);
+ // Insert into the passed DOM parent, maintaining sort order relative to siblings: name then id.
+ return insertSorted($treebox, $domParent);
+ }
+
+ var getOrCreateApplicationTreebox = function(id, name, treeView, $el) {
+ if (!($el)) $el = treeView.$el;
+ var $treebox = findRootTreebox(id, $el);
if (!$treebox.length) {
- var $insertionPoint = $('.lozenge-app-tree-wrapper', treeView.$el);
+ var $insertionPoint = $('.lozenge-app-tree-wrapper', $el);
if (!$insertionPoint.length) {
// entire view must be created
treeView.$el.html(
@@ -89,7 +100,7 @@ define([
'<div id="tree-list" class="navbar_main treeloz">'+
'<div class="lozenge-app-tree-wrapper">'+
'</div></div></div>');
- $insertionPoint = $('.lozenge-app-tree-wrapper', treeView.$el);
+ $insertionPoint = $('.lozenge-app-tree-wrapper', $el);
}
$treebox = createEntityTreebox(id, name, $insertionPoint, 0, false);
}
@@ -105,6 +116,9 @@ define([
};
var updateTreeboxContent = function(entity, $treebox, treeView) {
+ oldSortKey = $treebox.data('sort-key');
+ newSortKey = sortKeyOfEntity(entity);
+
var $newContent = $(treeView.template({
id: entity.get('id'),
parentId: entity.get('parentId'),
@@ -122,6 +136,14 @@ define([
$wrapper.html($newContent);
addEventsToNode($treebox, treeView);
+
+ if (newSortKey !== oldSortKey) {
+ // move this treebox to the right place in its parent
+ $treebox.data('sort-key', newSortKey);
+ $parent = $treebox.parent();
+ $treebox.detach();
+ insertSorted($treebox, $parent);
+ }
};
var addEventsToNode = function($node, treeView) {
@@ -148,22 +170,31 @@ define([
if (!($treebox.length)) return false;
if ($treebox.is(':visible')) return true;
var $parentTreebox = $treebox.parent().closest('.tree-box');
- if (!($parentTreebox) || $parentTreebox==$treebox) return false;
+ if (!($parentTreebox.length)) return true; //means item is being rendered offscreen
+ if ($parentTreebox==$treebox) return false; //should never happen
if (!ensureTreeboxVisible($parentTreebox, treeView)) return false;
treeView.showChildrenOf($parentTreebox, false);
return true;
};
var selectTreebox = function(id, $treebox, treeView) {
- $('.entity_tree_node_wrapper').removeClass('active');
+ treeView.requestedEntityId = id;
+ $('.entity_tree_node_wrapper', treeView.$el).removeClass('active');
$treebox.children('.entity_tree_node_wrapper').addClass('active');
var entity = treeView.collection.get(id);
if (entity) {
- ensureTreeboxVisible($treebox, treeView);
- treeView.selectedEntityId = id;
- treeView.trigger('entitySelected', entity);
- return true;
+ if (ensureTreeboxVisible($treebox, treeView)) {
+ treeView.selectedEntityId = id;
+ treeView.requestedEntityId = null;
+ treeView.trigger('entitySelected', entity);
+ return true;
+ } else {
+ // children DOM nodes not yet existing; probably the model is not populated,
+ // e.g. using browser forward/back, maybe also if invoked before selected;
+ // callers should populate then re-select
+ return false;
+ }
} else {
// probably needs a load
return false;
@@ -196,7 +227,6 @@ define([
// Called when the full entity model is fetched into our collection, at which time we can replace
// the empty contents of any placeholder tree nodes (.tree-box) that were created earlier.
// The entity may have multiple 'treebox' views (in the case of group members).
-
var $treebox;
var parentId = entity.get('parentId');
if (!parentId) {
@@ -204,8 +234,7 @@ define([
$treebox = getOrCreateApplicationTreebox(entity.id, entity.get('name'), this);
// Select the new app if there's no current selection.
- if (!this.selectedEntityId)
- selectTreebox(entity.id, $treebox, this);
+ if (!this.selectedEntityId && !this.requestedEntityId) selectTreebox(entity.id, $treebox, this);
} else {
// else create in parent
var parent = this.collection.get(parentId);
@@ -263,6 +292,8 @@ define([
renderFull: function() {
var that = this;
+
+ // build up the new element in a hidden node
this.$el.empty();
// Display tree and highlight the selected entity.
@@ -275,14 +306,22 @@ define([
var $treebox = getOrCreateApplicationTreebox(entity.id, entity.name, that);
updateTreeboxContent(entity, $treebox, that);
});
+
+ // expand to show selected or requested id
+ var target = this.selectedEntityId;
+ if (!target) target = this.requestedEntityId;
+ if (target) {
+ // ensure this treebox is added and reselected
+ var item = this.collection.get(target);
+ if (item) {
+ this.initialRender = true;
+ this.entityAdded(item);
+ this.selectEntity(target);
+ this.initialRender = false;
+ }
+ }
}
- // Select the first app if there's no current selection.
- if (!this.selectedEntityId) {
- var firstApp = _.first(this.collection.getApplications());
- if (firstApp)
- this.selectEntity(firstApp);
- }
return this;
},
@@ -377,7 +416,7 @@ define([
});
}
- $childContainer.slideDown(300);
+ $childContainer.slideDown(this.initialRender ? 0 : 300);
$wrapper.find('.tree-node-state').removeClass('icon-chevron-right').addClass('icon-chevron-down');
if (recurse) {
$childContainer.children('.tree-box').each(function () {
http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/e22ba57e/src/main/webapp/assets/js/view/entity-details.js
----------------------------------------------------------------------
diff --git a/src/main/webapp/assets/js/view/entity-details.js b/src/main/webapp/assets/js/view/entity-details.js
index f54c572..54e6d1b 100644
--- a/src/main/webapp/assets/js/view/entity-details.js
+++ b/src/main/webapp/assets/js/view/entity-details.js
@@ -107,11 +107,12 @@ define([
$(a).attr('href',entityHref+"/"+$(a).attr("data-target").slice(1));
});
} else {
- log("could not find entity href for tab");
+ // entity not available yet -- should be soon
+// log("could not find entity href for tab");
}
if (this.options.preselectTab) {
var tabLink = this.$('a[data-target="#'+this.options.preselectTab+'"]');
- var showFn = function() { tabLink.tab('show'); };
+ var showFn = function() { tabLink.tab('show', { duration: 0 }); };
if (optionalParent) showFn();
else _.defer(showFn);
}
@@ -126,6 +127,9 @@ define([
event.preventDefault();
var tabName = $(event.currentTarget).attr("data-target").slice(1);
+ this.options.preselectTab = tabName;
+ this.options.preselectTabDetails = null;
+
var route = this.getTab(tabName);
if (route) {
if (route[0]=='#') route = route.substring(1);