diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeFinderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeFinderTests.cs index bbe6519817..c55b577845 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeFinderTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Composing/TypeFinderTests.cs @@ -53,10 +53,10 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Composing Assert.AreEqual(0, typesFound.Count()); // 0 classes in _assemblies are marked with [Tree] typesFound = typeFinder.FindClassesWithAttribute(new[] { typeof(TreeAttribute).Assembly }); - Assert.AreEqual(22, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] + Assert.AreEqual(23, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] typesFound = typeFinder.FindClassesWithAttribute(); - Assert.AreEqual(22, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] + Assert.AreEqual(23, typesFound.Count()); // + classes in Umbraco.Web are marked with [Tree] } [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] diff --git a/src/Umbraco.Web.BackOffice/Trees/StaticFilesTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/StaticFilesTreeController.cs new file mode 100644 index 0000000000..474becaf17 --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Trees/StaticFilesTreeController.cs @@ -0,0 +1,78 @@ +using System.IO; +using System.Linq; +using System.Net; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Events; +using Umbraco.Cms.Core.IO; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Core.Trees; +using Umbraco.Extensions; + +namespace Umbraco.Cms.Web.BackOffice.Trees +{ + [Tree(Constants.Applications.Settings, "staticFiles", TreeTitle = "Static Files", TreeUse = TreeUse.Dialog)] + public class StaticFilesTreeController : TreeController + { + private readonly IFileSystem _fileSystem; + private const string AppPlugins = "App_Plugins"; + private const string Webroot = "wwwroot"; + + public StaticFilesTreeController(ILocalizedTextService localizedTextService, + UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, IEventAggregator eventAggregator, + IPhysicalFileSystem fileSystem) : + base(localizedTextService, umbracoApiControllerTypeCollection, eventAggregator) + { + _fileSystem = fileSystem; + } + + protected override ActionResult GetTreeNodes(string id, FormCollection queryStrings) + { + var path = string.IsNullOrEmpty(id) == false && id != Constants.System.RootString + ? WebUtility.UrlDecode(id).TrimStart("/") + : ""; + + var nodes = new TreeNodeCollection(); + var directories = _fileSystem.GetDirectories(path); + + foreach (var directory in directories) + { + // We don't want any other directories under the root node other than the ones serving static files - App_Plugins and wwwroot + if (id == Constants.System.RootString && directory != AppPlugins && directory != Webroot) + { + continue; + } + + var hasChildren = _fileSystem.GetFiles(directory).Any() || _fileSystem.GetDirectories(directory).Any(); + + var name = Path.GetFileName(directory); + var node = CreateTreeNode(WebUtility.UrlEncode(directory), path, queryStrings, name, "icon-folder", hasChildren); + + if (node != null) + { + nodes.Add(node); + } + } + + // Only get the files inside App_Plugins and wwwroot + var files = _fileSystem.GetFiles(path).Where(x => x.StartsWith(AppPlugins) || x.StartsWith(Webroot)); + + foreach (var file in files) + { + var name = Path.GetFileName(file); + var node = CreateTreeNode(WebUtility.UrlEncode(file), path, queryStrings, name, "icon-document", false); + + if (node != null) + { + nodes.Add(node); + } + } + + return nodes; + } + + // We don't have any menu item options (such as create/delete/reload) & only use the root node to load a custom UI + protected override ActionResult GetMenuForNode(string id, FormCollection queryStrings) => null; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js index cfeca6330c..c655ad3606 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js @@ -266,7 +266,7 @@ const thumbnailPicker = { title: localizedTitle, section: "settings", - treeAlias: "files", + treeAlias: "staticFiles", entityType: "file", isDialog: true, filter: function (i) { @@ -275,7 +275,7 @@ filterCssClass: "not-allowed", select: function (file) { const id = decodeURIComponent(file.id.replace(/\+/g, " ")); - block.thumbnail = "~/" + id; + block.thumbnail = "~/" + id.replace("wwwroot/", ""); editorService.close(); }, close: function () {