Gets the feature in v7 based on #2682 that wasn't merged upwards to v8 and found some issues along the way like not filtering the mini list view properly along with not returning the content type alias in the entity controller

This commit is contained in:
Shannon
2019-06-19 16:42:04 +10:00
parent c7a725ad94
commit 5c2b0647f3
5 changed files with 73 additions and 37 deletions

View File

@@ -38,7 +38,7 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use
treeOptionsClick: [],
treeNodeAltSelect: []
};
//this is the API exposed by this directive, for either hosting controllers or for other directives
vm.callbacks = {
treeNodeExpanded: function (f) {
@@ -82,7 +82,7 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use
// since it saves on data retreival and DOM processing.
// TODO: This isn't used!?
var lastSection = "";
/** Helper function to emit tree events */
function emitEvent(eventName, args) {
if (registeredCallbacks[eventName] && angular.isArray(registeredCallbacks[eventName])) {
@@ -119,7 +119,7 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use
$scope.cachekey = args.cacheKey;
}
}
return loadTree();
}
@@ -148,7 +148,7 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use
if (!args.path) {
throw "args.path cannot be null";
}
if (angular.isString(args.path)) {
args.path = args.path.replace('"', '').split(',');
}
@@ -172,8 +172,16 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use
emitEvent("treeSynced", { node: data, activate: args.activate });
return $q.when({ node: data, activate: args.activate });
}, function (data) {
return $q.reject(data);
}, function (data) {
//on notification
if (data.type === "treeNodeExpanded") {
//raise the event
emitEvent("treeNodeExpanded", { tree: $scope.tree, node: data.node, children: data.children });
}
});
}
/** This will check the section tree loaded and return all actual root nodes based on a tree type (non group nodes, non section groups) */
@@ -201,7 +209,7 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use
//given a tree alias, this will search the current section tree for the specified tree alias and set the current active tree to it's root node
function loadActiveTree(treeAlias) {
if (!$scope.tree) {
throw "Err in umbtree.directive.loadActiveTree, $scope.tree is null";
}
@@ -233,7 +241,7 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use
function loadTree() {
if (!$scope.loading && $scope.section) {
$scope.loading = true;
//default args
var args = { section: $scope.section, tree: $scope.treealias, cacheKey: $scope.cachekey, isDialog: $scope.isdialog ? $scope.isdialog : false };
@@ -279,7 +287,7 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use
if (forceReload || (node.hasChildren && node.children.length === 0)) {
//get the children from the tree service
return treeService.loadNodeChildren({ node: node, section: $scope.section, isDialog: $scope.isdialog })
.then(function(data) {
.then(function (data) {
//emit expanded event
emitEvent("treeNodeExpanded", { tree: $scope.tree, node: node, children: data });
@@ -302,7 +310,7 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use
// TODO: This is called constantly because as a method in a template it's re-evaluated pretty much all the time
// it would be better if we could cache the processing. The problem is that some of these things are dynamic.
var css = [];
if (node.cssClasses) {
_.each(node.cssClasses, function (c) {
@@ -322,7 +330,7 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use
};
/* helper to force reloading children of a tree node */
$scope.loadChildren = function(node, forceReload) {
$scope.loadChildren = function (node, forceReload) {
return loadChildren(node, forceReload);
};
@@ -359,7 +367,7 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use
$scope.altSelect = function (n, ev) {
emitEvent("treeNodeAltSelect", { element: $element, tree: $scope.tree, node: n, event: ev });
};
//call the onInit method, if the result is a promise then load the tree after that resolves (if it's not a promise this will just resolve automatically).
//NOTE: The promise cannot be rejected, else the tree won't be loaded and we'll get exceptions if some API calls syncTree or similar.
$q.when($scope.onInit(), function (args) {

View File

@@ -41,7 +41,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
return {
/** Internal method to return the tree cache */
_getTreeCache: function() {
_getTreeCache: function () {
return treeCache;
},
@@ -97,7 +97,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
}
//create a method outside of the loop to return the parent - otherwise jshint blows up
var funcParent = function() {
var funcParent = function () {
return parentNode;
};
@@ -168,7 +168,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
*
* @param {String} treeAlias The tree alias to check
*/
getTreePackageFolder: function(treeAlias) {
getTreePackageFolder: function (treeAlias) {
//we determine this based on the server variables
if (Umbraco.Sys.ServerVariables.umbracoPlugins &&
Umbraco.Sys.ServerVariables.umbracoPlugins.trees &&
@@ -220,7 +220,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
var self = this;
this.clearCache({
cacheKey: args.cacheKey,
filter: function(cc) {
filter: function (cc) {
//get the new parent node from the tree cache
var parent = self.getDescendantNode(cc.root, args.childrenOf);
if (parent) {
@@ -288,7 +288,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
* @param {object} args.node The tree node
* @param {object} args.section The current section
*/
loadNodeChildren: function(args) {
loadNodeChildren: function (args) {
if (!args) {
throw "No args object defined for loadNodeChildren";
}
@@ -303,7 +303,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
args.node.loading = true;
return this.getChildren(args)
.then(function(data) {
.then(function (data) {
//set state to done and expand (only if there actually are children!)
args.node.loading = false;
@@ -320,10 +320,10 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
return $q.when(data);
}, function(reason) {
}, function (reason) {
//in case of error, emit event
eventsService.emit("treeService.treeNodeLoadError", {error: reason } );
eventsService.emit("treeService.treeNodeLoadError", { error: reason });
//stop show the loading indicator
args.node.loading = false;
@@ -346,7 +346,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
* Removes a given node from the tree
* @param {object} treeNode the node to remove
*/
removeNode: function(treeNode) {
removeNode: function (treeNode) {
if (!angular.isFunction(treeNode.parent)) {
return;
}
@@ -359,7 +359,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
parent.children.splice(parent.children.indexOf(treeNode), 1);
parent.hasChildren = parent.children.length !== 0;
//Notify that the node has been removed
eventsService.emit("treeService.removeNode", { node: treeNode });
},
@@ -374,7 +374,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
* Removes all child nodes from a given tree node
* @param {object} treeNode the node to remove children from
*/
removeChildNodes : function(treeNode) {
removeChildNodes: function (treeNode) {
treeNode.expanded = false;
treeNode.children = [];
treeNode.hasChildren = false;
@@ -413,7 +413,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
* @param {int} id id of descendant node
* @param {string} treeAlias - optional tree alias, if fetching descendant node from a child of a listview document
*/
getDescendantNode: function(treeNode, id, treeAlias) {
getDescendantNode: function (treeNode, id, treeAlias) {
//validate if it is a section container since we'll need a treeAlias if it is one
if (treeNode.isContainer === true && !treeAlias) {
@@ -432,7 +432,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
var root = getTreeRoot(tn.children[c]);
//only return if we found the root in this child, otherwise continue.
if(root){
if (root) {
return root;
}
}
@@ -531,7 +531,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
* Gets the node's tree alias, this is done by looking up the meta-data of the current node's root node
* @param {object} treeNode to retrive tree alias from
*/
getTreeAlias : function(treeNode) {
getTreeAlias: function (treeNode) {
var root = this.getTreeRoot(treeNode);
if (root) {
return root.metaData["treeAlias"];
@@ -570,7 +570,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
var self = this;
return treeResource.loadApplication(args)
.then(function(data) {
.then(function (data) {
//this will be called once the tree app data has loaded
var result = {
name: data.name,
@@ -624,7 +624,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
}
return treeResource.loadMenu(args.treeNode)
.then(function(data) {
.then(function (data) {
//need to convert the icons to new ones
for (var i = 0; i < data.length; i++) {
data[i].cssclass = iconHelper.convertFromLegacyIcon(data[i].cssclass);
@@ -677,7 +677,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
* Re-loads the single node from the server
* @param {object} node Tree node to reload
*/
reloadNode: function(node) {
reloadNode: function (node) {
if (!node) {
throw "node cannot be null";
}
@@ -691,10 +691,10 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
//set the node to loading
node.loading = true;
return this.getChildren({ node: node.parent(), section: node.section }).then(function(data) {
return this.getChildren({ node: node.parent(), section: node.section }).then(function (data) {
//ok, now that we have the children, find the node we're reloading
var found = _.find(data, function(item) {
var found = _.find(data, function (item) {
return item.id === node.id;
});
if (found) {
@@ -720,7 +720,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
else {
return $q.reject();
}
}, function() {
}, function () {
return $q.reject();
});
},
@@ -735,7 +735,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
* This will return the current node's path by walking up the tree
* @param {object} node Tree node to retrieve path for
*/
getPath: function(node) {
getPath: function (node) {
if (!node) {
throw "node cannot be null";
}
@@ -760,7 +760,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
return reversePath.reverse();
},
syncTree: function(args) {
syncTree: function (args) {
if (!args) {
throw "No args object defined for syncTree";
@@ -800,6 +800,8 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
}
}
var deferred = $q.defer();
//now that we have the first id to lookup, we can start the process
var self = this;
@@ -831,6 +833,10 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
else {
//couldn't find it in the
return self.loadNodeChildren({ node: node, section: node.section }).then(function (children) {
//send back some progress to allow the caller to deal with expanded nodes
deferred.notify({ type: "treeNodeExpanded", node: node, children: children })
//ok, got the children, let's find it
var found = self.getChildNode(node, args.path[currPathIndex]);
if (found) {
@@ -858,8 +864,16 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
};
//start
return doSync();
var wrappedPromise = doSync();
//then wrap it
wrappedPromise.then(function (args) {
deferred.resolve(args);
}, function (args) {
deferred.reject(args);
});
return deferred.promise;
}
};

View File

@@ -59,6 +59,8 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController",
vm.submit = submit;
vm.close = close;
var currentNode = $scope.model.currentNode;
function initDialogTree() {
vm.dialogTreeApi.callbacks.treeLoaded(treeLoadedHandler);
// TODO: Also deal with unexpanding!!
@@ -160,6 +162,12 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController",
}
}
}
vm.filter = {
filterAdvanced: $scope.model.filterAdvanced,
filterExclude: $scope.model.filterExclude,
filter: $scope.model.filter
};
}
/**
@@ -256,6 +264,12 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController",
vm.hasItems = args.tree.root.children.length > 0;
tree = args.tree;
var nodeHasPath = currentNode && currentNode.path;
var startNodeNotDefined = !vm.startNodeId;
if (startNodeNotDefined && nodeHasPath) {
vm.dialogTreeApi.syncTree({ path: currentNode.path, activate: false });
}
}
//wires up selection

View File

@@ -74,7 +74,7 @@
start-node-id="vm.startNodeId"
on-select="vm.selectListViewNode(node)"
on-close="vm.closeMiniListView()"
entity-type-filter="filter">
entity-type-filter="vm.filter">
</umb-mini-list-view>
</umb-box-content>

View File

@@ -45,10 +45,10 @@ namespace Umbraco.Web.Models.Mapping
if (source.NodeObjectType == Constants.ObjectTypes.Member && target.Icon.IsNullOrWhiteSpace())
target.Icon = "icon-user";
if (source.NodeObjectType == Constants.ObjectTypes.Media && source is IContentEntitySlim contentSlim)
if (source is IContentEntitySlim contentSlim)
source.AdditionalData["ContentTypeAlias"] = contentSlim.ContentTypeAlias;
if (source.NodeObjectType == Constants.ObjectTypes.Media && source is IMediaEntitySlim mediaSlim)
if (source is IMediaEntitySlim mediaSlim)
source.AdditionalData["MediaPath"] = mediaSlim.MediaPath;
// NOTE: we're mapping the objects in AdditionalData by object reference here.