diff --git a/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js b/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js
index bfc7ddebac..8d382596f2 100644
--- a/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js
+++ b/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js
@@ -83,6 +83,7 @@ Umbraco.Sys.registerNamespace("Umbraco.Application");
mainTree: function() {
var injector = getRootInjector();
var navService = injector.get("navigationService");
+ var appState = injector.get("appState");
var angularHelper = injector.get("angularHelper");
var $rootScope = injector.get("$rootScope");
@@ -116,9 +117,10 @@ Umbraco.Sys.registerNamespace("Umbraco.Application");
},
moveNode: function (id, path) {
angularHelper.safeApply($rootScope, function() {
- if (navService.ui.currentNode) {
+ var currentMenuNode = appState.getMenuState("currentNode");
+ if (currentMenuNode) {
var treeService = injector.get("treeService");
- var treeRoot = treeService.getTreeRoot(navService.ui.currentNode);
+ var treeRoot = treeService.getTreeRoot(currentMenuNode);
if (treeRoot) {
var found = treeService.getDescendantNode(treeRoot, id);
if (found) {
@@ -131,12 +133,17 @@ Umbraco.Sys.registerNamespace("Umbraco.Application");
},
getActionNode: function () {
//need to replicate the legacy tree node
+ var currentMenuNode = appState.getMenuState("currentNode");
+ if (!currentMenuNode) {
+ return null;
+ }
+
var legacyNode = {
- nodeId: navService.ui.currentNode.id,
- nodeName: navService.ui.currentNode.name,
- nodeType: navService.ui.currentNode.nodeType,
- treeType: navService.ui.currentNode.nodeType,
- sourceUrl: navService.ui.currentNode.childNodesUrl,
+ nodeId: currentMenuNode.id,
+ nodeName: currentMenuNode.name,
+ nodeType: currentMenuNode.nodeType,
+ treeType: currentMenuNode.nodeType,
+ sourceUrl: currentMenuNode.childNodesUrl,
updateDefinition: function() {
throw "'updateDefinition' method is not supported in Umbraco 7, consider upgrading to the new v7 APIs";
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/umbtree.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/umbtree.directive.js
index 2b3798481c..abf22e5979 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/umbtree.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/umbtree.directive.js
@@ -133,11 +133,11 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
}
//reset current node selection
- scope.currentNode = undefined;
+ //scope.currentNode = null;
//filter the path for root node ids
args.path = _.filter(args.path, function (item) { return (item !== "init" && item !== "-1"); });
- loadPath(args.path, args.forceReload);
+ loadPath(args.path, args.forceReload, args.activate);
return deferred.promise;
};
@@ -157,18 +157,14 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
//helper to load a specific path on the active tree as soon as its ready
- function loadPath(path, forceReload) {
-
- function _load(tree, path, forceReload) {
- syncTree(tree, path, forceReload);
- }
+ function loadPath(path, forceReload, activate) {
if (scope.activeTree) {
- _load(scope.activeTree, path, forceReload);
+ syncTree(scope.activeTree, path, forceReload, activate);
}
else {
- scope.eventhandler.one("activeTreeLoaded", function(e, args) {
- _load(args.tree, path, forceReload);
+ scope.eventhandler.one("activeTreeLoaded", function (e, args) {
+ syncTree(args.tree, path, forceReload, activate);
});
}
}
@@ -181,8 +177,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
function loadActiveTree(treeAlias, loadChildren) {
scope.activeTree = undefined;
- function _load(tree) {
-
+ function doLoad(tree) {
var childrenAndSelf = [tree].concat(tree.children);
scope.activeTree = _.find(childrenAndSelf, function (node) {
return node.metaData.treeAlias === treeAlias;
@@ -205,11 +200,11 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
}
if (scope.tree) {
- _load(scope.tree.root);
+ doLoad(scope.tree.root);
}
else {
scope.eventhandler.one("treeLoaded", function(e, args) {
- _load(args.tree);
+ doLoad(args.tree);
});
}
}
@@ -245,7 +240,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
}
/** syncs the tree, the treeNode can be ANY tree node in the tree that requires syncing */
- function syncTree(treeNode, path, forceReload) {
+ function syncTree(treeNode, path, forceReload, activate) {
deleteAnimations = false;
@@ -254,8 +249,12 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
path: path,
forceReload: forceReload
}).then(function (data) {
- scope.currentNode = data;
- emitEvent("treeSynced", { node: data });
+
+ if (activate === undefined || activate === true) {
+ scope.currentNode = data;
+ }
+
+ emitEvent("treeSynced", { node: data, activate: activate });
enableDeleteAnimations();
});
@@ -326,7 +325,12 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat
and emits it as a treeNodeSelect element if there is a callback object
defined on the tree
*/
- scope.select = function(e, n, ev) {
+ scope.select = function (e, n, ev) {
+ //on tree select we need to remove the current node -
+ // whoever handles this will need to make sure the correct node is selected
+ //reset current node selection
+ scope.currentNode = null;
+
emitEvent("treeNodeSelect", { element: e, node: n, event: ev });
};
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js
index d488810180..dd979ebb6a 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js
@@ -206,11 +206,12 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
//when a tree node is synced this event will fire, this allows us to set the currentNode
mainTreeEventHandler.bind("treeSynced", function (ev, args) {
- //set the global current node
- ui.currentNode = args.node;
- //not sure what this is doing
- scope.currentNode = args.node;
- //what the heck is going on here? - this seems really zany, allowing us to modify the
+ if (args.activate === undefined || args.activate === true) {
+ //set the current selected node
+ appState.setTreeState("selectedNode", args.node);
+ }
+
+ //TODO: what the heck is going on here? - this seems really zany, allowing us to modify the
// navigationController.scope from within the navigationService to assign back to the args
// so that we can change the navigationController.scope from within the umbTree directive. Hrm.
args.scope = scope;
@@ -225,6 +226,9 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
//Set the current action node (this is not the same as the current selected node!)
appState.setMenuState("currentNode", args.node);
+ //TODO: what the heck is going on here? - this seems really zany, allowing us to modify the
+ // navigationController.scope from within the navigationService to assign back to the args
+ // so that we can change the navigationController.scope from within the umbTree directive. Hrm.
args.scope = scope;
if (args.event && args.event.altKey) {
@@ -238,7 +242,9 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
ev.stopPropagation();
ev.preventDefault();
- scope.currentNode = args.node;
+ //TODO: what the heck is going on here? - this seems really zany, allowing us to modify the
+ // navigationController.scope from within the navigationService to assign back to the args
+ // so that we can change the navigationController.scope from within the umbTree directive. Hrm.
args.scope = scope;
args.skipDefault = true;
@@ -252,9 +258,6 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
ev.stopPropagation();
ev.preventDefault();
- //put this into the app state
- appState.setTreeState("selectedNode", args.node);
-
if (n.metaData && n.metaData["jsClickCallback"] && angular.isString(n.metaData["jsClickCallback"]) && n.metaData["jsClickCallback"] !== "") {
//this is a legacy tree node!
var jsPrefix = "javascript:";
@@ -279,9 +282,11 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
else if (n.routePath) {
//add action to the history service
historyService.add({ name: n.name, link: n.routePath, icon: n.icon });
- //not legacy, lets just set the route value and clear the query string if there is one.
+
+ //put this node into the tree state
+ appState.setTreeState("selectedNode", args.node);
- ui.currentNode = n;
+ //not legacy, lets just set the route value and clear the query string if there is one.
$location.path(n.routePath).search("");
}
else if (args.element.section) {
@@ -307,6 +312,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
* @param {String} args.tree the tree alias to sync to
* @param {Array} args.path the path to sync the tree to
* @param {Boolean} args.forceReload optional, specifies whether to force reload the node data from the server even if it already exists in the tree currently
+ * @param {Boolean} args.activate optional, specifies whether to set the synced node to be the active node, this will default to true if not specified
*/
syncTree: function (args) {
if (!args) {
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js
index cd94e15087..f8266168b1 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js
@@ -494,6 +494,29 @@ function treeService($q, treeResource, iconHelper, notificationsService, $rootSc
return deferred.promise;
},
+ /** This will return the current node's path by walking up the tree */
+ getPath: function(node) {
+ if (!node) {
+ throw "node cannot be null";
+ }
+ if (!angular.isFunction(node.parent)) {
+ throw "node.parent is not a function, the path cannot be resolved";
+ }
+ //all root nodes have metadata key 'treeAlias'
+ var reversePath = [];
+ var current = node;
+ while (current != null) {
+ reversePath.push(current.id);
+ if (current.metaData && current.metaData["treeAlias"]) {
+ current = null;
+ }
+ else {
+ current = current.parent();
+ }
+ }
+ return reversePath.reverse();
+ },
+
syncTree: function(args) {
if (!args) {
@@ -569,7 +592,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, $rootSc
}
}
else {
- //the current node doesn't have it's children loaded, so go get them
+ //couldn't find it in the
self.loadNodeChildren({ node: node, section: node.section }).then(function () {
//ok, got the children, let's find it
var found = self.getChildNode(node, args.path[currPathIndex]);
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.copy.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.copy.controller.js
index 486c1dda10..27a4bf0046 100644
--- a/src/Umbraco.Web.UI.Client/src/views/content/content.copy.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/content/content.copy.controller.js
@@ -1,6 +1,6 @@
angular.module("umbraco")
.controller("Umbraco.Editors.Content.CopyController",
- function ($scope, eventsService, contentResource, navigationService, $log) {
+ function ($scope, eventsService, contentResource, navigationService, appState, treeService) {
var dialogOptions = $scope.$parent.dialogOptions;
$scope.dialogTreeEventHandler = $({});
@@ -37,7 +37,19 @@ angular.module("umbraco")
$scope.error = false;
$scope.success = true;
- navigationService.syncTree({ tree: "content", path: path, forceReload: true });
+ //get the currently edited node (if any)
+ var activeNode = appState.getTreeState("selectedNode");
+
+ //we need to do a double sync here: first sync to the copied content - but don't activate the node,
+ //then sync to the currenlty edited content (note: this might not be the content that was copied!!)
+
+ navigationService.syncTree({ tree: "content", path: path, forceReload: true, activate: false }).then(function(args) {
+ if (activeNode) {
+ var activeNodePath = treeService.getPath(activeNode).join();
+ //sync to this node now - depending on what was copied this might already be synced but might not be
+ navigationService.syncTree({ tree: "content", path: activeNodePath, forceReload: false, activate: true });
+ }
+ });
},function(err){
$scope.success = false;
diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs
index a5fe178f34..6b3fdb1649 100644
--- a/src/Umbraco.Web/Editors/ContentController.cs
+++ b/src/Umbraco.Web/Editors/ContentController.cs
@@ -5,6 +5,7 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
+using System.Text;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using AutoMapper;
@@ -112,10 +113,14 @@ namespace Umbraco.Web.Editors
///
///
///
- public string GetNiceUrl(int id)
+ public HttpResponseMessage GetNiceUrl(int id)
{
var url = Umbraco.NiceUrl(id);
- return url;
+ var response = new HttpResponseMessage(HttpStatusCode.OK)
+ {
+ Content = new StringContent(url, Encoding.UTF8, "application/json")
+ };
+ return response;
}
///
@@ -458,12 +463,17 @@ namespace Umbraco.Web.Editors
///
///
[EnsureUserPermissionForContent("move.ParentId", 'M')]
- public string PostMove(MoveOrCopy move)
+ public HttpResponseMessage PostMove(MoveOrCopy move)
{
var toMove = ValidateMoveOrCopy(move);
Services.ContentService.Move(toMove, move.ParentId);
- return toMove.Path;
+
+ var response = new HttpResponseMessage(HttpStatusCode.OK)
+ {
+ Content = new StringContent(toMove.Path, Encoding.UTF8, "application/json")
+ };
+ return response;
}
///
@@ -472,12 +482,17 @@ namespace Umbraco.Web.Editors
///
///
[EnsureUserPermissionForContent("copy.ParentId", 'C')]
- public string PostCopy(MoveOrCopy copy)
+ public HttpResponseMessage PostCopy(MoveOrCopy copy)
{
var toCopy = ValidateMoveOrCopy(copy);
var c = Services.ContentService.Copy(toCopy, copy.ParentId, copy.RelateToOriginal);
- return c.Path;
+
+ var response = new HttpResponseMessage(HttpStatusCode.OK)
+ {
+ Content = new StringContent(c.Path, Encoding.UTF8, "application/json")
+ };
+ return response;
}
///
diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs
index 4339f03484..844d8d5fc8 100644
--- a/src/Umbraco.Web/Editors/MediaController.cs
+++ b/src/Umbraco.Web/Editors/MediaController.cs
@@ -7,6 +7,7 @@ using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Security.AccessControl;
+using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
@@ -280,12 +281,15 @@ namespace Umbraco.Web.Editors
[EnsureUserPermissionForMedia("move.Id")]
public HttpResponseMessage PostMove(MoveOrCopy move)
{
-
var toMove = ValidateMoveOrCopy(move);
Services.MediaService.Move(toMove, move.ParentId);
- return Request.CreateResponse(HttpStatusCode.OK);
+ var response = new HttpResponseMessage(HttpStatusCode.OK)
+ {
+ Content = new StringContent(toMove.Path, Encoding.UTF8, "application/json")
+ };
+ return response;
}
///