diff --git a/src/Umbraco.Web/Editors/CodeFileController.cs b/src/Umbraco.Web/Editors/CodeFileController.cs
index 6775f84a61..c197f4eef0 100644
--- a/src/Umbraco.Web/Editors/CodeFileController.cs
+++ b/src/Umbraco.Web/Editors/CodeFileController.cs
@@ -1,5 +1,6 @@
using AutoMapper;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
@@ -266,29 +267,46 @@ namespace Umbraco.Web.Editors
{
if (string.IsNullOrWhiteSpace(type) == false && string.IsNullOrWhiteSpace(virtualPath) == false)
{
+ virtualPath = System.Web.HttpUtility.UrlDecode(virtualPath);
+
switch (type)
{
case Core.Constants.Trees.PartialViews:
+ if (IsDirectory(virtualPath, SystemDirectories.PartialViews))
+ {
+ Services.FileService.DeletePartialViewFolder(virtualPath);
+ return Request.CreateResponse(HttpStatusCode.OK);
+ }
if (Services.FileService.DeletePartialView(virtualPath, Security.CurrentUser.Id))
{
return Request.CreateResponse(HttpStatusCode.OK);
}
- return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No Partial View found with the specified path");
+ return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No Partial View or folder found with the specified path");
case Core.Constants.Trees.PartialViewMacros:
+ if (IsDirectory(virtualPath, SystemDirectories.MacroPartials))
+ {
+ Services.FileService.DeletePartialViewMacroFolder(virtualPath);
+ return Request.CreateResponse(HttpStatusCode.OK);
+ }
if (Services.FileService.DeletePartialViewMacro(virtualPath, Security.CurrentUser.Id))
{
return Request.CreateResponse(HttpStatusCode.OK);
}
- return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No Partial View Macro found with the specified path");
+ return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No Partial View Macro or folder found with the specified path");
case Core.Constants.Trees.Scripts:
+ if (IsDirectory(virtualPath, SystemDirectories.Scripts))
+ {
+ Services.FileService.DeleteScriptFolder(virtualPath);
+ return Request.CreateResponse(HttpStatusCode.OK);
+ }
if (Services.FileService.GetScriptByName(virtualPath) != null)
{
Services.FileService.DeleteScript(virtualPath, Security.CurrentUser.Id);
return Request.CreateResponse(HttpStatusCode.OK);
}
- return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No Script found with the specified path");
+ return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No Script or folder found with the specified path");
default:
return Request.CreateResponse(HttpStatusCode.NotFound);
@@ -442,5 +460,12 @@ namespace Umbraco.Web.Editors
return value;
}
+
+ private bool IsDirectory(string virtualPath, string systemDirectory)
+ {
+ var path = IOHelper.MapPath(systemDirectory + "/" + virtualPath);
+ var dirInfo = new DirectoryInfo(path);
+ return dirInfo.Attributes == FileAttributes.Directory;
+ }
}
}
diff --git a/src/Umbraco.Web/Trees/FileSystemTreeController.cs b/src/Umbraco.Web/Trees/FileSystemTreeController.cs
index 61ee8c4ff9..88f322971d 100644
--- a/src/Umbraco.Web/Trees/FileSystemTreeController.cs
+++ b/src/Umbraco.Web/Trees/FileSystemTreeController.cs
@@ -1,10 +1,10 @@
using System;
-using System.Collections.Generic;
using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Net.Http.Formatting;
+using umbraco.BusinessLogic.Actions;
+using Umbraco.Core;
using Umbraco.Core.IO;
+using Umbraco.Core.Services;
using Umbraco.Web.Models.Trees;
namespace Umbraco.Web.Trees
@@ -27,7 +27,7 @@ namespace Umbraco.Web.Trees
///
protected virtual void OnRenderFolderNode(ref TreeNode treeNode) { }
- protected override Models.Trees.TreeNodeCollection GetTreeNodes(string id, System.Net.Http.Formatting.FormDataCollection queryStrings)
+ protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings)
{
string orgPath = "";
string path = "";
@@ -90,6 +90,64 @@ namespace Umbraco.Web.Trees
}
return nodes;
- }
+ }
+
+ protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
+ {
+ var menu = new MenuItemCollection();
+
+ //if root node no need to visit the filesystem so lets just create the menu and return it
+ if (id == Constants.System.Root.ToInvariantString())
+ {
+ //set the default to create
+ menu.DefaultMenuAlias = ActionNew.Instance.Alias;
+ //create action
+ menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
+ //refresh action
+ menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
+
+ return menu;
+ }
+
+ string path;
+ if (string.IsNullOrEmpty(id) == false)
+ {
+ var orgPath = System.Web.HttpUtility.UrlDecode(id);
+ path = IOHelper.MapPath(FilePath + "/" + orgPath);
+ }
+ else
+ {
+ path = IOHelper.MapPath(FilePath);
+ }
+
+ var dirInfo = new DirectoryInfo(path);
+ //check if it's a directory
+ if (dirInfo.Attributes == FileAttributes.Directory)
+ {
+ //set the default to create
+ menu.DefaultMenuAlias = ActionNew.Instance.Alias;
+ //create action
+ menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
+
+ var hasChildren = dirInfo.GetFiles().Length > 0 || dirInfo.GetDirectories().Length > 0;
+ //We can only delete folders if it doesn't have any children (folders or files)
+ if (hasChildren == false)
+ {
+ //delete action
+ menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)), true);
+ }
+
+ //refresh action
+ menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
+ }
+ //if it's not a directory then we only allow to delete the item
+ else
+ {
+ //delete action
+ menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)));
+ }
+
+ return menu;
+ }
}
}
diff --git a/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs b/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs
index 61d9c17cef..9643823e7b 100644
--- a/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs
+++ b/src/Umbraco.Web/Trees/PartialViewMacrosTreeController.cs
@@ -1,16 +1,13 @@
using Umbraco.Core;
using Umbraco.Core.IO;
-using umbraco.BusinessLogic.Actions;
using Umbraco.Web.Models.Trees;
-using System.Net.Http.Formatting;
-using Umbraco.Core.Services;
namespace Umbraco.Web.Trees
{
- ///
- /// Tree for displaying partial view macros in the developer app
- ///
- [Tree(Constants.Applications.Developer, "partialViewMacros", "Partial View Macro Files", sortOrder: 6)]
+ ///
+ /// Tree for displaying partial view macros in the developer app
+ ///
+ [Tree(Constants.Applications.Developer, "partialViewMacros", "Partial View Macro Files", sortOrder: 6)]
public class PartialViewMacrosTreeController : FileSystemTreeController
{
protected override string FilePath
@@ -28,37 +25,6 @@ namespace Umbraco.Web.Trees
get { return "icon-article"; }
}
- protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
- {
- var menu = new MenuItemCollection();
-
- if (id == Constants.System.Root.ToInvariantString())
- {
- //set the default to create
- menu.DefaultMenuAlias = ActionNew.Instance.Alias;
- //create action
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
- //refresh action
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
-
- return menu;
- }
-
- if (id.EndsWith(FileSearchPattern.TrimStart("*")) == false)
- {
- //set the default to create
- menu.DefaultMenuAlias = ActionNew.Instance.Alias;
- //create action
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
- //refresh action
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
- }
-
- // TODO: Wire up new delete dialog
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)));
- return menu;
- }
-
protected override void OnRenderFileNode(ref TreeNode treeNode)
{
base.OnRenderFileNode(ref treeNode);
diff --git a/src/Umbraco.Web/Trees/PartialViewsTreeController.cs b/src/Umbraco.Web/Trees/PartialViewsTreeController.cs
index 96da9a2e33..07a0a557af 100644
--- a/src/Umbraco.Web/Trees/PartialViewsTreeController.cs
+++ b/src/Umbraco.Web/Trees/PartialViewsTreeController.cs
@@ -1,9 +1,6 @@
using Umbraco.Core;
using Umbraco.Core.IO;
-using umbraco.BusinessLogic.Actions;
using Umbraco.Web.Models.Trees;
-using System.Net.Http.Formatting;
-using Umbraco.Core.Services;
namespace Umbraco.Web.Trees
{
@@ -27,37 +24,6 @@ namespace Umbraco.Web.Trees
get { return "icon-article"; }
}
- protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
- {
- var menu = new MenuItemCollection();
-
- if (id == Constants.System.Root.ToInvariantString())
- {
- //set the default to create
- menu.DefaultMenuAlias = ActionNew.Instance.Alias;
- //create action
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
- //refresh action
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
-
- return menu;
- }
-
- if (id.EndsWith(FileSearchPattern.TrimStart("*")) == false)
- {
- //set the default to create
- menu.DefaultMenuAlias = ActionNew.Instance.Alias;
- //create action
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
- //refresh action
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
- }
-
- // TODO: Wire up new delete dialog
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)));
- return menu;
- }
-
protected override void OnRenderFileNode(ref TreeNode treeNode)
{
base.OnRenderFileNode(ref treeNode);
diff --git a/src/Umbraco.Web/Trees/ScriptTreeController.cs b/src/Umbraco.Web/Trees/ScriptTreeController.cs
index c7d4e728aa..f491989228 100644
--- a/src/Umbraco.Web/Trees/ScriptTreeController.cs
+++ b/src/Umbraco.Web/Trees/ScriptTreeController.cs
@@ -1,10 +1,6 @@
-using System.Linq;
-using Umbraco.Core;
+using Umbraco.Core;
using Umbraco.Core.IO;
-using umbraco.BusinessLogic.Actions;
using Umbraco.Web.Models.Trees;
-using System.Net.Http.Formatting;
-using Umbraco.Core.Services;
namespace Umbraco.Web.Trees
{
@@ -25,37 +21,6 @@ namespace Umbraco.Web.Trees
get { return "icon-script"; }
}
- protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings)
- {
- var menu = new MenuItemCollection();
-
- if (id == Constants.System.Root.ToInvariantString())
- {
- //set the default to create
- menu.DefaultMenuAlias = ActionNew.Instance.Alias;
- //create action
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
- //refresh action
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
-
- return menu;
- }
-
- if (id.EndsWith(FileSearchPattern.TrimStart("*")) == false)
- {
- //set the default to create
- menu.DefaultMenuAlias = ActionNew.Instance.Alias;
- //create action
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
- //refresh action
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
- }
-
- // TODO: Wire up new delete dialog
- menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)));
- return menu;
- }
-
protected override void OnRenderFolderNode(ref TreeNode treeNode)
{
//TODO: This isn't the best way to ensure a noop process for clicking a node but it works for now.