Gets delete and empty recycle bin working, adds unit tests for tree service, ensures that the recycle bin shows children whenever something is deleted (though, i now realize i need to refresh the recycle bin node and expand it when something is deleted). Renames some namespaces for content/media/etc... controllers and makes the file names more readable.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -88,3 +88,5 @@ src/Umbraco.Web.UI.Client/src/[Ll]ess/*.css
|
||||
tools/NDepend/
|
||||
|
||||
src/Umbraco.Web.UI/App_Plugins/*
|
||||
src/*.psess
|
||||
src/*.vspx
|
||||
|
||||
@@ -51,24 +51,26 @@ angular.module('umbraco.mocks').
|
||||
|
||||
return {
|
||||
register: function() {
|
||||
$httpBackend
|
||||
.whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Content/GetById'))
|
||||
.respond(returnNodebyId);
|
||||
$httpBackend
|
||||
.whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Content/GetById'))
|
||||
.respond(returnNodebyId);
|
||||
|
||||
|
||||
$httpBackend
|
||||
.whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Content/GetEmpty'))
|
||||
.respond(returnEmptyNode);
|
||||
$httpBackend
|
||||
.whenGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Content/GetEmpty'))
|
||||
.respond(returnEmptyNode);
|
||||
|
||||
$httpBackend
|
||||
.whenDELETE(mocksUtils.urlRegex('/umbraco/UmbracoApi/Content/DeleteById'))
|
||||
.respond(returnDeletedNode);
|
||||
|
||||
$httpBackend
|
||||
.whenDELETE(mocksUtils.urlRegex('/umbraco/UmbracoApi/Content/EmptyRecycleBin'))
|
||||
.respond(returnDeletedNode);
|
||||
},
|
||||
|
||||
|
||||
expectGetById: function() {
|
||||
$httpBackend
|
||||
.expectGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Content/GetById'));
|
||||
$httpBackend
|
||||
.expectGET(mocksUtils.urlRegex('/umbraco/UmbracoApi/Content/GetById'));
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -26,7 +26,9 @@ angular.module('umbraco.mocks').
|
||||
{ seperator: true, name: "Hostnames", cssclass: "home", alias: "hostnames", metaData: {} },
|
||||
{ name: "Public Access", cssclass: "group", alias: "publicaccess", metaData: {} },
|
||||
|
||||
{ seperator: true, name: "Reload", cssclass: "refresh", alias: "users", metaData: {} }
|
||||
{ seperator: true, name: "Reload", cssclass: "refresh", alias: "users", metaData: {} },
|
||||
|
||||
{ seperator: true, name: "Empty Recycle Bin", cssclass: "trash", alias: "emptyrecyclebin", metaData: {} }
|
||||
];
|
||||
|
||||
return [200, menu, null];
|
||||
@@ -52,10 +54,10 @@ angular.module('umbraco.mocks').
|
||||
}
|
||||
|
||||
var children = [
|
||||
{ name: "child-of-" + section, childNodesUrl: url, id: level + "" + 1234, icon: "icon-file-alt", view: section + "/edit/" + level + "" + 1234, children: [], expanded: false, hasChildren: true, level: level, defaultAction: action, menuUrl: menuUrl },
|
||||
{ name: "random-name-" + section, childNodesUrl: url, id: level + "" + 1235, icon: "icon-file-alt", view: section + "/edit/" + level + "" + 1235, children: [], expanded: false, hasChildren: true, level: level, defaultAction: action, menuUrl: menuUrl },
|
||||
{ name: "random-name-" + section, childNodesUrl: url, id: level + "" + 1236, icon: "icon-file-alt", view: section + "/edit/" + level + "" + 1236, children: [], expanded: false, hasChildren: true, level: level, defaultAction: action, menuUrl: menuUrl },
|
||||
{ name: "random-name-" + section, childNodesUrl: url, id: level + "" + 1237, icon: "icon-file-alt", view: "common/legacy/1237?p=" + encodeURI("developer/contentType.aspx?idequal1234"), children: [], expanded: false, hasChildren: true, level: level, defaultAction: action, menuUrl: menuUrl }
|
||||
{ name: "child-of-" + section, childNodesUrl: url, id: level + "" + 1234, icon: "icon-file-alt", children: [], expanded: false, hasChildren: true, level: level, defaultAction: action, menuUrl: menuUrl },
|
||||
{ name: "random-name-" + section, childNodesUrl: url, id: level + "" + 1235, icon: "icon-file-alt", children: [], expanded: false, hasChildren: true, level: level, defaultAction: action, menuUrl: menuUrl },
|
||||
{ name: "random-name-" + section, childNodesUrl: url, id: level + "" + 1236, icon: "icon-file-alt", children: [], expanded: false, hasChildren: true, level: level, defaultAction: action, menuUrl: menuUrl },
|
||||
{ name: "random-name-" + section, childNodesUrl: url, id: level + "" + 1237, icon: "icon-file-alt", routePath: "common/legacy/1237?p=" + encodeURI("developer/contentType.aspx?idequal1234"), children: [], expanded: false, hasChildren: true, level: level, defaultAction: action, menuUrl: menuUrl }
|
||||
];
|
||||
|
||||
return [200, children, null];
|
||||
@@ -78,15 +80,16 @@ angular.module('umbraco.mocks').
|
||||
name: "content",
|
||||
id: -1,
|
||||
children: [
|
||||
{ name: "My website", id: 1234, childNodesUrl: url, icon: "icon-home", view: section + "/edit/" + 1234, children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create", menuUrl: menuUrl },
|
||||
{ name: "Components", id: 1235, childNodesUrl: url, icon: "icon-cogs", view: section + "/edit/" + 1235, children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create", menuUrl: menuUrl },
|
||||
{ name: "Archieve", id: 1236, childNodesUrl: url, icon: "icon-folder-close", view: section + "/edit/" + 1236, children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create", menuUrl: menuUrl },
|
||||
{ name: "Recycle Bin", id: 1237, childNodesUrl: url, icon: "icon-trash", view: section + "/trash/view/", children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create", menuUrl: menuUrl }
|
||||
{ name: "My website", id: 1234, childNodesUrl: url, icon: "icon-home", children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create", menuUrl: menuUrl },
|
||||
{ name: "Components", id: 1235, childNodesUrl: url, icon: "icon-cogs", children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create", menuUrl: menuUrl },
|
||||
{ name: "Archieve", id: 1236, childNodesUrl: url, icon: "icon-folder-close", children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create", menuUrl: menuUrl },
|
||||
{ name: "Recycle Bin", id: -20, childNodesUrl: url, icon: "icon-trash", routePath: section + "/recyclebin", children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create", menuUrl: menuUrl }
|
||||
],
|
||||
expanded: true,
|
||||
hasChildren: true,
|
||||
level: 0,
|
||||
menuUrl: menuUrl
|
||||
menuUrl: menuUrl,
|
||||
metaData: { treeType: "Umbraco.Web.Trees.ContentTreeController" }
|
||||
};
|
||||
|
||||
break;
|
||||
@@ -96,16 +99,16 @@ angular.module('umbraco.mocks').
|
||||
name: "developer",
|
||||
id: -1,
|
||||
children: [
|
||||
{ name: "Data types", childNodesUrl: url, id: -1, icon: "icon-folder-close", view: section + "/edit/" + 1234, children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "Macros", childNodesUrl: url, id: -1, icon: "icon-folder-close", view: section + "/edit/" + 1235, children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "Pacakges", childNodesUrl: url, id: -1, icon: "icon-folder-close", view: section + "/edit/" + 1236, children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "XSLT Files", childNodesUrl: url, id: -1, icon: "icon-folder-close", view: section + "/edit/" + 1237, children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "Razor Files", childNodesUrl: url, id: -1, icon: "icon-folder-close", view: section + "/edit/" + 1237, children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl }
|
||||
{ name: "Data types", childNodesUrl: url, id: -1, icon: "icon-folder-close", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl, metaData: { treeType: "Umbraco.Web.Trees.DataTypeTreeController" } },
|
||||
{ name: "Macros", childNodesUrl: url, id: -1, icon: "icon-folder-close", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl, metaData: { treeType: "Umbraco.Web.Trees.MacrosTreeController" } },
|
||||
{ name: "Pacakges", childNodesUrl: url, id: -1, icon: "icon-folder-close", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl, metaData: { treeType: "Umbraco.Web.Trees.PackagesTreeController" } },
|
||||
{ name: "XSLT Files", childNodesUrl: url, id: -1, icon: "icon-folder-close", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl, metaData: { treeType: "Umbraco.Web.Trees.XsltTreeController" } },
|
||||
{ name: "Razor Files", childNodesUrl: url, id: -1, icon: "icon-folder-close", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl, metaData: { treeType: "Umbraco.Web.Trees.RazorTreeController" } }
|
||||
],
|
||||
expanded: true,
|
||||
hasChildren: true,
|
||||
level: 0,
|
||||
isContainer: true
|
||||
isContainer: true
|
||||
};
|
||||
|
||||
break;
|
||||
@@ -114,11 +117,11 @@ angular.module('umbraco.mocks').
|
||||
name: "settings",
|
||||
id: -1,
|
||||
children: [
|
||||
{ name: "Stylesheets", childNodesUrl: url, id: -1, icon: "icon-folder-close", view: section + "/edit/" + 1234, children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "Templates", childNodesUrl: url, id: -1, icon: "icon-folder-close", view: section + "/edit/" + 1235, children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "Dictionary", childNodesUrl: url, id: -1, icon: "icon-folder-close", view: section + "/edit/" + 1236, children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "Media types", childNodesUrl: url, id: -1, icon: "icon-folder-close", view: section + "/edit/" + 1237, children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "Document types", childNodesUrl: url, id: -1, icon: "icon-folder-close", view: section + "/edit/" + 1237, children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl }
|
||||
{ name: "Stylesheets", childNodesUrl: url, id: -1, icon: "icon-folder-close", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl, metaData: { treeType: "Umbraco.Web.Trees.StylesheetTreeController" } },
|
||||
{ name: "Templates", childNodesUrl: url, id: -1, icon: "icon-folder-close", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl, metaData: { treeType: "Umbraco.Web.Trees.TemplatesTreeController" } },
|
||||
{ name: "Dictionary", childNodesUrl: url, id: -1, icon: "icon-folder-close", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl, metaData: { treeType: "Umbraco.Web.Trees.DictionaryTreeController" } },
|
||||
{ name: "Media types", childNodesUrl: url, id: -1, icon: "icon-folder-close", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl, metaData: { treeType: "Umbraco.Web.Trees.MediaTypesTreeController" } },
|
||||
{ name: "Document types", childNodesUrl: url, id: -1, icon: "icon-folder-close", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl, metaData: { treeType: "Umbraco.Web.Trees.ContentTypesTreeController" } }
|
||||
],
|
||||
expanded: true,
|
||||
hasChildren: true,
|
||||
@@ -133,15 +136,16 @@ angular.module('umbraco.mocks').
|
||||
name: "randomTree",
|
||||
id: -1,
|
||||
children: [
|
||||
{ name: "random-name-" + section, childNodesUrl: url, id: 1234, icon: "icon-home", defaultAction: "create", view: section + "/edit/" + 1234, children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "random-name-" + section, childNodesUrl: url, id: 1235, icon: "icon-folder-close", defaultAction: "create", view: section + "/edit/" + 1235, children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "random-name-" + section, childNodesUrl: url, id: 1236, icon: "icon-folder-close", defaultAction: "create", view: section + "/edit/" + 1236, children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "random-name-" + section, childNodesUrl: url, id: 1237, icon: "icon-folder-close", defaultAction: "create", view: section + "/edit/" + 1237, children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl }
|
||||
{ name: "random-name-" + section, childNodesUrl: url, id: 1234, icon: "icon-home", defaultAction: "create", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "random-name-" + section, childNodesUrl: url, id: 1235, icon: "icon-folder-close", defaultAction: "create", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "random-name-" + section, childNodesUrl: url, id: 1236, icon: "icon-folder-close", defaultAction: "create", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "random-name-" + section, childNodesUrl: url, id: 1237, icon: "icon-folder-close", defaultAction: "create", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl }
|
||||
],
|
||||
expanded: true,
|
||||
hasChildren: true,
|
||||
level: 0,
|
||||
menuUrl: menuUrl
|
||||
menuUrl: menuUrl,
|
||||
metaData: { treeType: "Umbraco.Web.Trees.RandomTreeController" }
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
@@ -16,6 +16,15 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
|
||||
return {
|
||||
|
||||
emptyRecycleBin: function() {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.delete(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"contentApiBaseUrl",
|
||||
"EmptyRecycleBin")),
|
||||
'Failed to empty the recycle bin');
|
||||
},
|
||||
|
||||
deleteById: function(id) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.delete(
|
||||
|
||||
@@ -12,7 +12,7 @@ function treeService($q, treeResource, iconHelper) {
|
||||
var treeArray = [];
|
||||
var currentSection = "content";
|
||||
|
||||
/** ensures there's a view and level property on each tree node */
|
||||
/** ensures there's a routePath, parent and level property on each tree node */
|
||||
function ensureParentLevelAndView(parentNode, treeNodes, section, level) {
|
||||
//if no level is set, then we make it 1
|
||||
var childLevel = (level ? level : 1);
|
||||
@@ -33,7 +33,60 @@ function treeService($q, treeResource, iconHelper) {
|
||||
throw "Cannot remove a node that doesn't have a parent";
|
||||
}
|
||||
//remove the current item from it's siblings
|
||||
treeNode.parent.children.splice(treeNode.parent.children.indexOf(treeNode), 1);
|
||||
treeNode.parent.children.splice(treeNode.parent.children.indexOf(treeNode), 1);
|
||||
},
|
||||
|
||||
removeChildNodes : function(treeNode) {
|
||||
treeNode.children = [];
|
||||
treeNode.hasChildren = false;
|
||||
},
|
||||
|
||||
/** Gets a child node by id */
|
||||
getChildNode: function(treeNode, id) {
|
||||
var found = _.find(treeNode.children, function (child) {
|
||||
return child.id === id;
|
||||
});
|
||||
return found === undefined ? null : found;
|
||||
},
|
||||
|
||||
/** Gets a descendant node by id */
|
||||
getDescendantNode: function(treeNode, id) {
|
||||
//check the first level
|
||||
var found = this.getChildNode(treeNode, id);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
|
||||
//check each child of this node
|
||||
for (var i = 0; i < treeNode.children.length; i++) {
|
||||
if (treeNode.children[i].hasChildren) {
|
||||
//recurse
|
||||
found = this.getDescendantNode(treeNode.children[i], id);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//not found
|
||||
return found === undefined ? null : found;
|
||||
},
|
||||
|
||||
/** Gets the root node of the current tree type for a given tree node */
|
||||
getTreeRoot: function(treeNode) {
|
||||
//all root nodes have metadata key 'treeType'
|
||||
var root = null;
|
||||
var current = treeNode;
|
||||
while (root === null && current !== undefined) {
|
||||
|
||||
if (current.metaData && current.metaData["treeType"]) {
|
||||
root = current;
|
||||
}
|
||||
else {
|
||||
current = current.parent;
|
||||
}
|
||||
}
|
||||
return root;
|
||||
},
|
||||
|
||||
getTree: function (options) {
|
||||
@@ -97,7 +150,6 @@ function treeService($q, treeResource, iconHelper) {
|
||||
*
|
||||
* @description
|
||||
* Attempts to return a tree node's menu item based on the alias supplied, otherwise returns null.
|
||||
|
||||
* @param {object} args An arguments object
|
||||
* @param {object} args.treeNode The tree node to get the menu item for
|
||||
* @param {object} args.menuItemAlias The menu item alias to attempt to find
|
||||
|
||||
@@ -33,6 +33,11 @@ app.config(function ($routeProvider) {
|
||||
if (!rp.method)
|
||||
return "views/common/dashboard.html";
|
||||
|
||||
////here we detect recycle bins, all recycle bins start with -2* (i.e. -20, -21)
|
||||
//if (rp.id.startsWith("-2")) {
|
||||
// return 'views/' + rp.section + '/recyclebin.html';
|
||||
//}
|
||||
|
||||
return 'views/' + rp.section + '/' + rp.method + '.html';
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
angular.module('umbraco')
|
||||
.controller("Umbraco.Editors.ContentCreateController",
|
||||
.controller("Umbraco.Editors.Content.CreateController",
|
||||
function ($scope, $routeParams, contentTypeResource, iconHelper) {
|
||||
|
||||
contentTypeResource.getAllowedTypes($scope.currentNode.id)
|
||||
@@ -17,6 +17,12 @@ function ContentDeleteController($scope, contentResource, treeService, navigatio
|
||||
$scope.currentNode.loading = false;
|
||||
//TODO: Need to sync tree, etc...
|
||||
treeService.removeNode($scope.currentNode);
|
||||
|
||||
//ensure the recycle bin has child nodes now
|
||||
var rootNode = treeService.getTreeRoot($scope.currentNode);
|
||||
var recycleBin = treeService.getDescendantNode(rootNode, -20);
|
||||
recycleBin.hasChildren = true;
|
||||
|
||||
navigationService.hideMenu();
|
||||
});
|
||||
|
||||
@@ -27,4 +33,4 @@ function ContentDeleteController($scope, contentResource, treeService, navigatio
|
||||
};
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.ContentDeleteController", ContentDeleteController);
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Content.DeleteController", ContentDeleteController);
|
||||
@@ -91,4 +91,4 @@ function ContentEditController($scope, $routeParams, $location, contentResource,
|
||||
};
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.ContentEditController", ContentEditController);
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Content.EditController", ContentEditController);
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name Umbraco.Editors.Content.EmptyRecycleBinController
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* The controller for deleting content
|
||||
*/
|
||||
function ContentEmptyRecycleBinController($scope, contentResource, treeService, navigationService) {
|
||||
|
||||
$scope.performDelete = function() {
|
||||
|
||||
//(used in the UI)
|
||||
$scope.currentNode.loading = true;
|
||||
|
||||
contentResource.emptyRecycleBin($scope.currentNode.id).then(function () {
|
||||
$scope.currentNode.loading = false;
|
||||
//TODO: Need to sync tree, etc...
|
||||
treeService.removeChildNodes($scope.currentNode);
|
||||
navigationService.hideMenu();
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
$scope.cancel = function() {
|
||||
navigationService.hideDialog();
|
||||
};
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Content.EmptyRecycleBinController", ContentEmptyRecycleBinController);
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="umb-dialog" ng-controller="Umbraco.Editors.ContentCreateController">
|
||||
<div class="umb-dialog" ng-controller="Umbraco.Editors.Content.CreateController">
|
||||
<div class="umb-dialog-body" auto-scale="90">
|
||||
<p class="umb-abstract">Create a page under {{currentNode.name}}</p>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="umb-dialog" ng-controller="Umbraco.Editors.ContentDeleteController">
|
||||
<div class="umb-dialog" ng-controller="Umbraco.Editors.Content.DeleteController">
|
||||
<div class="umb-dialog-body" auto-scale="90">
|
||||
|
||||
<umb-confirm on-confirm="performDelete" on-cancel="cancel">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<ng-form name="contentForm" ng-show="contentLoaded">
|
||||
<umb-panel ng-controller="Umbraco.Editors.ContentEditController" val-show-validation>
|
||||
<umb-panel ng-controller="Umbraco.Editors.Content.EditController" val-show-validation>
|
||||
<umb-header tabs="content.tabs">
|
||||
|
||||
<umb-content-name ng-model="content.name" placeholder="Enter a page title"></umb-content-name>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<div class="umb-dialog" ng-controller="Umbraco.Editors.Content.EmptyRecycleBinController">
|
||||
<div class="umb-dialog-body" auto-scale="90">
|
||||
|
||||
<umb-confirm on-confirm="performDelete" on-cancel="cancel">
|
||||
</umb-confirm>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,9 @@
|
||||
<umb-panel>
|
||||
<div class="umb-panel-header">
|
||||
<div class="row-fluid">
|
||||
<span class="span4 umb-panel-header-meta">
|
||||
<h1>Recycle bin</h1>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</umb-panel>
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="umb-dialog" ng-controller="Umbraco.Editors.MediaCreateController">
|
||||
<div class="umb-dialog" ng-controller="Umbraco.Editors.Media.CreateController">
|
||||
<div class="umb-dialog-body" auto-scale="90">
|
||||
<p class="umb-abstract">Create a page under {{currentNode.name}}</p>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<ng-form name="contentForm" ng-show="contentLoaded">
|
||||
<umb-panel ng-controller="Umbraco.Editors.MediaEditController" val-show-validation>
|
||||
<umb-panel ng-controller="Umbraco.Editors.Media.EditController" val-show-validation>
|
||||
<umb-header tabs="content.tabs">
|
||||
|
||||
<umb-content-name ng-model="content.name" placeholder="Enter a page title"></umb-content-name>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
function mediaCreateController ($scope, $routeParams,mediaTypeResource) {
|
||||
$scope.allowedTypes = mediaTypeResource.getAllowedTypes($scope.currentNode.id);
|
||||
}
|
||||
|
||||
angular.module('umbraco')
|
||||
.controller("Umbraco.Editors.MediaCreateController", mediaCreateController);
|
||||
function mediaCreateController ($scope, $routeParams,mediaTypeResource) {
|
||||
$scope.allowedTypes = mediaTypeResource.getAllowedTypes($scope.currentNode.id);
|
||||
}
|
||||
|
||||
angular.module('umbraco')
|
||||
.controller("Umbraco.Editors.Media.CreateController", mediaCreateController);
|
||||
@@ -1,63 +1,63 @@
|
||||
function mediaEditController($scope, $routeParams, mediaResource, notificationsService, angularHelper, serverValidationManager, contentEditingHelper) {
|
||||
|
||||
if ($routeParams.create) {
|
||||
|
||||
mediaResource.getScaffold($routeParams.id, $routeParams.doctype)
|
||||
.then(function (data) {
|
||||
$scope.contentLoaded = true;
|
||||
$scope.content = data;
|
||||
});
|
||||
}
|
||||
else {
|
||||
mediaResource.getById($routeParams.id)
|
||||
.then(function (data) {
|
||||
$scope.contentLoaded = true;
|
||||
$scope.content = data;
|
||||
|
||||
//in one particular special case, after we've created a new item we redirect back to the edit
|
||||
// route but there might be server validation errors in the collection which we need to display
|
||||
// after the redirect, so we will bind all subscriptions which will show the server validation errors
|
||||
// if there are any and then clear them so the collection no longer persists them.
|
||||
serverValidationManager.executeAndClearAllSubscriptions();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
$scope.files = [];
|
||||
$scope.addFiles = function (propertyId, files) {
|
||||
//this will clear the files for the current property and then add the new ones for the current property
|
||||
$scope.files = _.reject($scope.files, function (item) {
|
||||
return item.id == propertyId;
|
||||
});
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
//save the file object to the scope's files collection
|
||||
$scope.files.push({ id: propertyId, file: files[i] });
|
||||
}
|
||||
};
|
||||
|
||||
//ensure there is a form object assigned.
|
||||
var currentForm = angularHelper.getRequiredCurrentForm($scope);
|
||||
|
||||
$scope.save = function (cnt) {
|
||||
|
||||
$scope.$broadcast("saving", { scope: $scope });
|
||||
|
||||
//don't continue if the form is invalid
|
||||
if (currentForm.$invalid) return;
|
||||
|
||||
serverValidationManager.reset();
|
||||
|
||||
mediaResource.saveMedia(cnt, $routeParams.create, $scope.files)
|
||||
.then(function (data) {
|
||||
contentEditingHelper.handleSuccessfulSave({
|
||||
scope: $scope,
|
||||
newContent: data
|
||||
});
|
||||
}, function (err) {
|
||||
contentEditingHelper.handleSaveError(err, $scope);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Editors.MediaEditController", mediaEditController);
|
||||
function mediaEditController($scope, $routeParams, mediaResource, notificationsService, angularHelper, serverValidationManager, contentEditingHelper) {
|
||||
|
||||
if ($routeParams.create) {
|
||||
|
||||
mediaResource.getScaffold($routeParams.id, $routeParams.doctype)
|
||||
.then(function (data) {
|
||||
$scope.contentLoaded = true;
|
||||
$scope.content = data;
|
||||
});
|
||||
}
|
||||
else {
|
||||
mediaResource.getById($routeParams.id)
|
||||
.then(function (data) {
|
||||
$scope.contentLoaded = true;
|
||||
$scope.content = data;
|
||||
|
||||
//in one particular special case, after we've created a new item we redirect back to the edit
|
||||
// route but there might be server validation errors in the collection which we need to display
|
||||
// after the redirect, so we will bind all subscriptions which will show the server validation errors
|
||||
// if there are any and then clear them so the collection no longer persists them.
|
||||
serverValidationManager.executeAndClearAllSubscriptions();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
$scope.files = [];
|
||||
$scope.addFiles = function (propertyId, files) {
|
||||
//this will clear the files for the current property and then add the new ones for the current property
|
||||
$scope.files = _.reject($scope.files, function (item) {
|
||||
return item.id == propertyId;
|
||||
});
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
//save the file object to the scope's files collection
|
||||
$scope.files.push({ id: propertyId, file: files[i] });
|
||||
}
|
||||
};
|
||||
|
||||
//ensure there is a form object assigned.
|
||||
var currentForm = angularHelper.getRequiredCurrentForm($scope);
|
||||
|
||||
$scope.save = function (cnt) {
|
||||
|
||||
$scope.$broadcast("saving", { scope: $scope });
|
||||
|
||||
//don't continue if the form is invalid
|
||||
if (currentForm.$invalid) return;
|
||||
|
||||
serverValidationManager.reset();
|
||||
|
||||
mediaResource.saveMedia(cnt, $routeParams.create, $scope.files)
|
||||
.then(function (data) {
|
||||
contentEditingHelper.handleSuccessfulSave({
|
||||
scope: $scope,
|
||||
newContent: data
|
||||
});
|
||||
}, function (err) {
|
||||
contentEditingHelper.handleSaveError(err, $scope);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
angular.module("umbraco")
|
||||
.controller("Umbraco.Editors.Media.EditController", mediaEditController);
|
||||
@@ -20,7 +20,7 @@ describe('edit content controller tests', function () {
|
||||
//this controller requires an angular form controller applied to it
|
||||
scope.contentForm = angularHelper.getNullForm("contentForm");
|
||||
|
||||
controller = $controller('Umbraco.Editors.ContentEditController', {
|
||||
controller = $controller('Umbraco.Editors.Content.EditController', {
|
||||
$scope: scope,
|
||||
$routeParams: routeParams
|
||||
});
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
describe('tree service tests', function () {
|
||||
var treeService;
|
||||
|
||||
function ensureParentLevelAndView(parentNode, treeNodes, section, level) {
|
||||
//if no level is set, then we make it 1
|
||||
var childLevel = (level ? level : 1);
|
||||
for (var i = 0; i < treeNodes.length; i++) {
|
||||
treeNodes[i].level = childLevel;
|
||||
//if there is not route path specified, then set it automatically
|
||||
if (!treeNodes[i].routePath) {
|
||||
treeNodes[i].routePath = section + "/edit/" + treeNodes[i].id;
|
||||
}
|
||||
treeNodes[i].parent = parentNode;
|
||||
}
|
||||
}
|
||||
|
||||
function getContentTree() {
|
||||
|
||||
var url = "/umbraco/UmbracoTrees/ApplicationTreeApi/GetChildren?treeType=content&id=1234&level=1";
|
||||
var menuUrl = "/umbraco/UmbracoTrees/ApplicationTreeApi/GetMenu?treeType=content&id=1234&parentId=456";
|
||||
|
||||
var t = {
|
||||
name: "content",
|
||||
id: -1,
|
||||
children: [
|
||||
{
|
||||
name: "My website", id: 1234, childNodesUrl: url, icon: "icon-home", expanded: false, hasChildren: true, level: 1, defaultAction: "create", menuUrl: menuUrl,
|
||||
children: [
|
||||
{ name: "random-name-1", childNodesUrl: url, id: 11, icon: "icon-home", defaultAction: "create", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "random-name-2", childNodesUrl: url, id: 12, icon: "icon-folder-close", defaultAction: "create", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "random-name-3", childNodesUrl: url, id: 13, icon: "icon-folder-close", defaultAction: "create", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl },
|
||||
{ name: "random-name-4", childNodesUrl: url, id: 14, icon: "icon-folder-close", defaultAction: "create", children: [], expanded: false, hasChildren: true, level: 1, menuUrl: menuUrl }
|
||||
]
|
||||
},
|
||||
{ name: "Components", id: 1235, childNodesUrl: url, icon: "icon-cogs", children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create", menuUrl: menuUrl },
|
||||
{ name: "Archieve", id: 1236, childNodesUrl: url, icon: "icon-folder-close", children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create", menuUrl: menuUrl },
|
||||
{ name: "Recycle Bin", id: -20, childNodesUrl: url, icon: "icon-trash", routePath: "content/recyclebin", children: [], expanded: false, hasChildren: true, level: 1, defaultAction: "create", menuUrl: menuUrl }
|
||||
],
|
||||
expanded: true,
|
||||
hasChildren: true,
|
||||
level: 0,
|
||||
menuUrl: menuUrl,
|
||||
metaData: { treeType: "Umbraco.Web.Trees.ContentTreeController" }
|
||||
};
|
||||
|
||||
ensureParentLevelAndView(t, t.children, "content", 0);
|
||||
ensureParentLevelAndView(t.children[0], t.children[0].children, "content", 1);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
beforeEach(module('umbraco.services'));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
treeService = $injector.get('treeService');
|
||||
}));
|
||||
|
||||
describe('query existing node structure of the tree', function () {
|
||||
|
||||
it('can get a descendant node', function() {
|
||||
|
||||
var tree = getContentTree();
|
||||
var found = treeService.getDescendantNode(tree, 13);
|
||||
|
||||
expect(found).toBeDefined();
|
||||
expect(found).not.toBeNull();
|
||||
expect(found.id).toBe(13);
|
||||
expect(found.name).toBe("random-name-3");
|
||||
});
|
||||
|
||||
it('returns null for a descendant node that doesnt exist', function () {
|
||||
|
||||
var tree = getContentTree();
|
||||
var found = treeService.getDescendantNode(tree, 123456);
|
||||
|
||||
expect(found).toBeNull();
|
||||
});
|
||||
|
||||
it('can get a child node', function () {
|
||||
|
||||
var tree = getContentTree();
|
||||
var found = treeService.getChildNode(tree, 1235);
|
||||
|
||||
expect(found).toBeDefined();
|
||||
expect(found).not.toBeNull();
|
||||
expect(found.id).toBe(1235);
|
||||
expect(found.name).toBe("Components");
|
||||
});
|
||||
|
||||
it('returns null for a child node that doesnt exist', function () {
|
||||
|
||||
var tree = getContentTree();
|
||||
var found = treeService.getChildNode(tree, 123456);
|
||||
|
||||
expect(found).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null for a descendant node that doesnt exist', function () {
|
||||
|
||||
var tree = getContentTree();
|
||||
var found = treeService.getDescendantNode(tree, 123456);
|
||||
|
||||
expect(found).toBeNull();
|
||||
});
|
||||
|
||||
it('can get the root node from a child node', function () {
|
||||
|
||||
var tree = getContentTree();
|
||||
var testNode = tree.children[0].children[3];
|
||||
var root = treeService.getTreeRoot(testNode);
|
||||
|
||||
expect(root).toBeDefined();
|
||||
expect(root).not.toBeNull();
|
||||
expect(root.id).toBe(-1);
|
||||
expect(root.name).toBe("content");
|
||||
});
|
||||
|
||||
it('can get the root node from the root node', function () {
|
||||
|
||||
var tree = getContentTree();
|
||||
var root = treeService.getTreeRoot(tree);
|
||||
|
||||
expect(root).toBeDefined();
|
||||
expect(root).not.toBeNull();
|
||||
expect(root.id).toBe(-1);
|
||||
expect(root.name).toBe("content");
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
@@ -176,6 +176,33 @@ namespace Umbraco.Web.Editors
|
||||
return display;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an item
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public HttpResponseMessage DeleteById(int id)
|
||||
{
|
||||
var foundContent = Services.ContentService.GetById(id);
|
||||
if (foundContent == null)
|
||||
{
|
||||
HandleContentNotFound(id);
|
||||
}
|
||||
Services.ContentService.Delete(foundContent, UmbracoUser.Id);
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Empties the recycle bin
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpDelete]
|
||||
public HttpResponseMessage EmptyRecycleBin()
|
||||
{
|
||||
Services.ContentService.EmptyRecycleBin();
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
private void ShowMessageForStatus(PublishStatus status, ContentItemDisplay display)
|
||||
{
|
||||
switch (status.StatusType)
|
||||
|
||||
@@ -43,7 +43,8 @@ namespace Umbraco.Web.Trees
|
||||
queryStrings,
|
||||
ui.GetText("general", "recycleBin"),
|
||||
"icon-trash",
|
||||
RecycleBinSmells));
|
||||
RecycleBinSmells,
|
||||
queryStrings.GetValue<string>("application") + "/recyclebin"));
|
||||
return nodes;
|
||||
}
|
||||
|
||||
|
||||
@@ -280,8 +280,11 @@ namespace Umbraco.Web.Trees
|
||||
Icon = xmlTreeNode.Icon,
|
||||
Title = xmlTreeNode.Text,
|
||||
NodeType = xmlTreeNode.NodeType
|
||||
|
||||
};
|
||||
if (isRoot)
|
||||
{
|
||||
node.AdditionalData.Add("treeType", xmlTreeNode.TreeType);
|
||||
}
|
||||
|
||||
//This is a special case scenario, we know that content/media works based on the normal Belle routing/editing so we'll ensure we don't
|
||||
// pass in the legacy JS handler so we do it the new way, for all other trees (Currently, this is a WIP), we'll render
|
||||
|
||||
@@ -10,9 +10,7 @@ namespace umbraco.BusinessLogic.Actions
|
||||
public class ActionEmptyTranscan : IAction
|
||||
{
|
||||
//create singleton
|
||||
#pragma warning disable 612,618
|
||||
private static readonly ActionEmptyTranscan m_instance = new ActionEmptyTranscan();
|
||||
#pragma warning restore 612,618
|
||||
private static readonly ActionEmptyTranscan InnerInstance = new ActionEmptyTranscan();
|
||||
|
||||
/// <summary>
|
||||
/// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons.
|
||||
@@ -24,7 +22,7 @@ namespace umbraco.BusinessLogic.Actions
|
||||
|
||||
public static ActionEmptyTranscan Instance
|
||||
{
|
||||
get { return m_instance; }
|
||||
get { return InnerInstance; }
|
||||
}
|
||||
|
||||
#region IAction Members
|
||||
@@ -57,7 +55,7 @@ namespace umbraco.BusinessLogic.Actions
|
||||
{
|
||||
get
|
||||
{
|
||||
return "emptyTrashcan";
|
||||
return "emptyRecycleBin";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -203,7 +203,6 @@
|
||||
<Compile Include="Actions\ActionSort.cs" />
|
||||
<Compile Include="Actions\ActionToPublish.cs" />
|
||||
<Compile Include="Actions\ActionTranslate.cs" />
|
||||
<Compile Include="Actions\ActionTreeEditMode.cs" />
|
||||
<Compile Include="Actions\ActionUpdate.cs" />
|
||||
<Compile Include="Actions\ContextMenuSeperator.cs" />
|
||||
<Compile Include="Actions\ActionUnPublish.cs">
|
||||
|
||||
@@ -89,6 +89,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuSpecs", "NuSpecs", "{227C
|
||||
..\build\NuSpecs\UmbracoCms.nuspec = ..\build\NuSpecs\UmbracoCms.nuspec
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{245872FE-BA7D-494A-AFFF-B364BB8FF170}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Performance1.psess = Performance1.psess
|
||||
Performance2.psess = Performance2.psess
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -181,4 +187,7 @@ Global
|
||||
{73529637-28F5-419C-A6BB-D094E39DE614} = {DD32977B-EF54-475B-9A1B-B97A502C6E58}
|
||||
{B555AAE6-0F56-442F-AC9F-EF497DB38DE7} = {DD32977B-EF54-475B-9A1B-B97A502C6E58}
|
||||
EndGlobalSection
|
||||
GlobalSection(Performance) = preSolution
|
||||
HasPerformanceSessions = true
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Reference in New Issue
Block a user