From 9ec30860b0632fb54fd834dc61cc6b7a99b576e6 Mon Sep 17 00:00:00 2001 From: mortenbock Date: Wed, 2 Oct 2013 17:48:44 +0200 Subject: [PATCH 01/25] Wrap all ViewEngines in a profiler Wrap all ViewEngines in a custom profiler view engine, using the ProfilerResolver to track performance --- src/Umbraco.Core/Profiling/ProfilingView.cs | 28 +++++++++++ .../Profiling/ProfilingViewEngine.cs | 48 +++++++++++++++++++ src/Umbraco.Core/Umbraco.Core.csproj | 2 + src/Umbraco.Web/WebBootManager.cs | 18 ++++--- 4 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 src/Umbraco.Core/Profiling/ProfilingView.cs create mode 100644 src/Umbraco.Core/Profiling/ProfilingViewEngine.cs diff --git a/src/Umbraco.Core/Profiling/ProfilingView.cs b/src/Umbraco.Core/Profiling/ProfilingView.cs new file mode 100644 index 0000000000..110ab14925 --- /dev/null +++ b/src/Umbraco.Core/Profiling/ProfilingView.cs @@ -0,0 +1,28 @@ +using System.IO; +using System.Web.Mvc; + +namespace Umbraco.Core.Profiling +{ + public class ProfilingView : IView + { + private readonly IView _inner; + private readonly string _name; + private readonly string _viewPath; + + public ProfilingView(IView inner) + { + _inner = inner; + _name = inner.GetType().Name; + var razorView = inner as RazorView; + _viewPath = razorView != null ? razorView.ViewPath : "Unknown"; + } + + public void Render(ViewContext viewContext, TextWriter writer) + { + using (ProfilerResolver.Current.Profiler.Step(string.Format("{0}.Render: {1}", _name, _viewPath))) + { + _inner.Render(viewContext, writer); + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Profiling/ProfilingViewEngine.cs b/src/Umbraco.Core/Profiling/ProfilingViewEngine.cs new file mode 100644 index 0000000000..5df2b6f811 --- /dev/null +++ b/src/Umbraco.Core/Profiling/ProfilingViewEngine.cs @@ -0,0 +1,48 @@ +using System.Web.Mvc; + +namespace Umbraco.Core.Profiling +{ + public class ProfilingViewEngine: IViewEngine + { + private readonly IViewEngine _inner; + private readonly string _name; + + public ProfilingViewEngine(IViewEngine inner) + { + _inner = inner; + _name = inner.GetType().Name; + } + + public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) + { + using (ProfilerResolver.Current.Profiler.Step(string.Format("{0}.FindPartialView, {1}, {2}", _name, partialViewName, useCache))) + { + return WrapResult(_inner.FindPartialView(controllerContext, partialViewName, useCache)); + } + } + + public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) + { + using (ProfilerResolver.Current.Profiler.Step(string.Format("{0}.FindView, {1}, {2}, {3}", _name, viewName, masterName, useCache))) + { + return WrapResult(_inner.FindView(controllerContext, viewName, masterName, useCache)); + } + } + + private static ViewEngineResult WrapResult(ViewEngineResult innerResult) + { + var profiledResult = innerResult.View != null ? + new ViewEngineResult(new ProfilingView(innerResult.View), innerResult.ViewEngine) : + new ViewEngineResult(innerResult.SearchedLocations); + return profiledResult; + } + + public void ReleaseView(ControllerContext controllerContext, IView view) + { + using (ProfilerResolver.Current.Profiler.Step(string.Format("{0}.ReleaseView, {1}", _name, view.GetType().Name))) + { + _inner.ReleaseView(controllerContext, view); + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index dc95d29ab4..1386f52e2a 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -562,6 +562,8 @@ + + diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs index 35869fb76b..cca270acd3 100644 --- a/src/Umbraco.Web/WebBootManager.cs +++ b/src/Umbraco.Web/WebBootManager.cs @@ -9,7 +9,6 @@ using StackExchange.Profiling.MVCHelpers; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Dictionary; -using Umbraco.Core.Dynamics; using Umbraco.Core.Logging; using Umbraco.Core.ObjectResolution; using Umbraco.Core.Profiling; @@ -25,9 +24,8 @@ using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.WebApi; using umbraco.BusinessLogic; -using umbraco.businesslogic; -using umbraco.cms.businesslogic; using umbraco.presentation.cache; +using ProfilingViewEngine = Umbraco.Core.Profiling.ProfilingViewEngine; namespace Umbraco.Web @@ -73,9 +71,9 @@ namespace Umbraco.Web new MasterControllerFactory(FilteredControllerFactoriesResolver.Current)); //set the render view engine - ViewEngines.Engines.Add(new ProfilingViewEngine(new RenderViewEngine())); + ViewEngines.Engines.Add(new RenderViewEngine()); //set the plugin view engine - ViewEngines.Engines.Add(new ProfilingViewEngine(new PluginViewEngine())); + ViewEngines.Engines.Add(new PluginViewEngine()); //set model binder ModelBinders.Binders.Add(new KeyValuePair(typeof(RenderModel), new RenderModelBinder())); @@ -129,7 +127,15 @@ namespace Umbraco.Web /// public override IBootManager Complete(Action afterComplete) { - //set routes + //Wrap viewengines in the profiling engine + IViewEngine[] engines = ViewEngines.Engines.Select(e => e).ToArray(); + ViewEngines.Engines.Clear(); + foreach (var engine in engines) + { + ViewEngines.Engines.Add(new ProfilingViewEngine(engine)); + } + + //set routes CreateRoutes(); base.Complete(afterComplete); From 24020cfea35bd1592fd68a28fb89ee9243a94e2d Mon Sep 17 00:00:00 2001 From: mortenbock Date: Wed, 2 Oct 2013 18:30:59 +0200 Subject: [PATCH 02/25] Make sure the profilingengine doesn't wrap itself --- src/Umbraco.Web/WebBootManager.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs index cca270acd3..4c9757fe95 100644 --- a/src/Umbraco.Web/WebBootManager.cs +++ b/src/Umbraco.Web/WebBootManager.cs @@ -132,7 +132,8 @@ namespace Umbraco.Web ViewEngines.Engines.Clear(); foreach (var engine in engines) { - ViewEngines.Engines.Add(new ProfilingViewEngine(engine)); + var wrappedEngine = engine is ProfilingViewEngine ? engine : new ProfilingViewEngine(engine); + ViewEngines.Engines.Add(wrappedEngine); } //set routes From b09a743beba2f5d7b5e6cb0db1239bfb30c2ab22 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 3 Oct 2013 11:25:26 +1000 Subject: [PATCH 03/25] Gets view paths to load in dynamically based on whether a core or plugin tree is rendering, this allows us to store view files based on conventions for packages. Completes: U4-2849 Ensure editor views, etc... can exist outside of the /umbraco folder for package devs --- .../common/mocks/umbraco.servervariables.js | 5 ++ .../src/common/services/navigation.service.js | 13 ++-- .../src/common/services/tree.service.js | 27 +++++++++ src/Umbraco.Web.UI.Client/src/routes.js | 31 +++++++--- .../unit/common/services/tree-service.spec.js | 18 +++++- .../MyPackage/Trees/LegacyTestTree.cs | 8 ++- .../Editors/BackOfficeController.cs | 34 +++++++++++ src/Umbraco.Web/PluginManagerExtensions.cs | 3 +- .../Trees/ApplicationTreeRegistrar.cs | 3 + .../Trees/ContentTreeController.cs | 1 + .../Trees/DataTypeTreeController.cs | 1 + src/Umbraco.Web/Trees/MediaTreeController.cs | 1 + src/Umbraco.Web/Trees/MemberTreeController.cs | 1 + .../Trees/Menu/MenuItemCollection.cs | 36 ++--------- .../Trees/Menu/MenuItemExtensions.cs | 15 ----- src/Umbraco.Web/Trees/TreeAttribute.cs | 12 ++++ src/Umbraco.Web/Trees/TreeController.cs | 59 +------------------ 17 files changed, 146 insertions(+), 122 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js b/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js index 058a8366ae..d4fe75e80c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js @@ -23,5 +23,10 @@ Umbraco.Sys.ServerVariables = { "appPluginsPath" : "/App_Plugins", "imageFileTypes": "jpeg,jpg,gif,bmp,png,tiff,tif" }, + umbracoPlugins: { + trees: [ + { alias: "myTree", packageFolder: "MyPackage" } + ] + }, isDebuggingEnabled: true }; \ No newline at end of file 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 eca8f70576..70d7dc577c 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 @@ -364,16 +364,19 @@ angular.module('umbraco.services') //by convention we will look into the /views/{treetype}/{action}.html // for example: /views/content/create.html - //we will also check for a 'packageName' in metaData, if it exists, we'll look by convention in that folder + //we will also check for a 'packageName' for the current tree, if it exists then the convention will be: // for example: /App_Plugins/{mypackage}/umbraco/{treetype}/create.html - if (args.action.metaData["packageName"]) { + var treeAlias = treeService.getTreeAlias(args.node); + var packageTreeFolder = treeService.getTreePackageFolder(treeAlias); - templateUrl = Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath + - "/umbraco/views/" + treeService.getTreeAlias(args.node) + "/" + args.action.alias + ".html"; + if (packageTreeFolder) { + templateUrl = Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath + + "/" + packageTreeFolder + + "/umbraco/" + treeAlias + "/" + args.action.alias + ".html"; } else { - templateUrl = "views/" + treeService.getTreeAlias(args.node) + "/" + args.action.alias + ".html"; + templateUrl = "views/" + treeAlias + "/" + args.action.alias + ".html"; } iframe = false; 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 f241ea6cab..b34cd72c79 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 @@ -58,6 +58,33 @@ function treeService($q, treeResource, iconHelper, notificationsService, $rootSc } }, + /** + * @ngdoc method + * @name umbraco.services.treeService#getTreePackageFolder + * @methodOf umbraco.services.treeService + * @function + * + * @description + * Determines if the current tree is a plugin tree and if so returns the package folder it has declared + * so we know where to find it's views, otherwise it will just return undefined. + * + * @param {String} treeAlias The tree alias to check + */ + getTreePackageFolder: function(treeAlias) { + //we determine this based on the server variables + if (Umbraco.Sys.ServerVariables.umbracoPlugins && + Umbraco.Sys.ServerVariables.umbracoPlugins.trees && + angular.isArray(Umbraco.Sys.ServerVariables.umbracoPlugins.trees)) { + + var found = _.find(Umbraco.Sys.ServerVariables.umbracoPlugins.trees, function(item) { + return item.alias === treeAlias; + }); + + return found ? found.packageFolder : undefined; + } + return undefined; + }, + /** clears the tree cache */ clearCache: function() { treeArray = []; diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index 792fa23bd7..94ec046e81 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -84,21 +84,34 @@ app.config(function ($routeProvider) { resolve: checkAuth(true) }) .when('/:section/:tree/:method/:id', { - templateUrl: function (rp) { - if (!rp.tree || !rp.method) { - return "views/common/dashboard.html"; + //This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method. + template: "
", + //This controller will execute for this route, then we replace the template dynamnically based on the current tree. + controller: function ($scope, $route, $routeParams, treeService) { + + if (!$routeParams.tree || !$routeParams.method) { + $scope.templateUrl = "views/common/dashboard.html"; } - - //TODO: Here we need to figure out if this route is for a package and if so then we need + + // Here we need to figure out if this route is for a package tree and if so then we need // to change it's convention view path to: // /App_Plugins/{mypackage}/umbraco/{treetype}/{method}.html + // otherwise if it is a core tree we use the core paths: + // views/{treetype}/{method}.html - //we don't need to put views into section folders since theoretically trees - // could be moved among sections, we only need folders for specific trees. + var packageTreeFolder = treeService.getTreePackageFolder($routeParams.tree); + + if (packageTreeFolder) { + $scope.templateUrl = Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath + + "/" + packageTreeFolder + + "/umbraco/" + $routeParams.tree + "/" + $routeParams.method + ".html"; + } + else { + $scope.templateUrl = 'views/' + $routeParams.tree + '/' + $routeParams.method + '.html'; + } - return 'views/' + rp.tree + '/' + rp.method + '.html'; - }, + }, resolve: checkAuth(true) }) .otherwise({ redirectTo: '/login' }); diff --git a/src/Umbraco.Web.UI.Client/test/unit/common/services/tree-service.spec.js b/src/Umbraco.Web.UI.Client/test/unit/common/services/tree-service.spec.js index f5ed2935a4..230a5ad015 100644 --- a/src/Umbraco.Web.UI.Client/test/unit/common/services/tree-service.spec.js +++ b/src/Umbraco.Web.UI.Client/test/unit/common/services/tree-service.spec.js @@ -40,7 +40,23 @@ describe('tree service tests', function () { beforeEach(inject(function ($injector) { treeService = $injector.get('treeService'); - })); + })); + + describe('lookup plugin based trees', function() { + + it('can find a plugin based tree', function () { + //we know this exists in the mock umbraco server vars + var found = treeService.getTreePackageFolder("myTree"); + expect(found).toBe("MyPackage"); + }); + + it('returns undefined for a not found tree', function () { + //we know this exists in the mock umbraco server vars + var found = treeService.getTreePackageFolder("asdfasdf"); + expect(found).not.toBeDefined(); + }); + + }); describe('query existing node structure of the tree', function () { diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/Trees/LegacyTestTree.cs b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Trees/LegacyTestTree.cs index 347c55503a..4971384529 100644 --- a/src/Umbraco.Web.UI/App_Plugins/MyPackage/Trees/LegacyTestTree.cs +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Trees/LegacyTestTree.cs @@ -30,9 +30,11 @@ namespace Umbraco.Web.UI.App_Plugins.MyPackage.Trees } protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) - { - MenuItems.AddMenuItem(new MenuItem("create", "Create")); - return MenuItems; + { + var menu = new MenuItemCollection(); + + menu.AddMenuItem(new MenuItem("create", "Create")); + return menu; } } diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 641d809ca7..dabbd6b12c 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using System.Web.Mvc; using Umbraco.Core.Configuration; @@ -85,12 +86,45 @@ namespace Umbraco.Web.Editors string.Join(",",UmbracoConfig.For.UmbracoSettings().Content.ImageFileTypes)}, } }, + { + "umbracoPlugins", new Dictionary + { + {"trees", GetTreePluginsMetaData()} + } + }, { "isDebuggingEnabled", HttpContext.IsDebuggingEnabled } }; return JavaScript(ServerVariablesParser.Parse(d)); } + private IEnumerable> GetTreePluginsMetaData() + { + var treeTypes = PluginManager.Current.ResolveAttributedTreeControllers(); + //get all plugin trees with their attributes + var treesWithAttributes = treeTypes.Select(x => new + { + tree = x, attributes = + x.GetCustomAttributes(false) + }).ToArray(); + + var pluginTreesWithAttributes = treesWithAttributes + //don't resolve any tree decorated with CoreTreeAttribute + .Where(x => x.attributes.All(a => (a is CoreTreeAttribute) == false)) + //we only care about trees with the PluginControllerAttribute + .Where(x => x.attributes.Any(a => a is PluginControllerAttribute)) + .ToArray(); + + return (from p in pluginTreesWithAttributes + let treeAttr = p.attributes.OfType().Single() + let pluginAttr = p.attributes.OfType().Single() + select new Dictionary + { + {"alias", treeAttr.Alias}, {"packageFolder", pluginAttr.AreaName} + }).ToArray(); + + } + /// /// Returns the JavaScript blocks for any legacy trees declared /// diff --git a/src/Umbraco.Web/PluginManagerExtensions.cs b/src/Umbraco.Web/PluginManagerExtensions.cs index ab0846f530..bda4b3a95f 100644 --- a/src/Umbraco.Web/PluginManagerExtensions.cs +++ b/src/Umbraco.Web/PluginManagerExtensions.cs @@ -25,8 +25,7 @@ namespace Umbraco.Web /// internal static IEnumerable ResolveAttributedTreeControllers(this PluginManager resolver) { - //don't cache the result of this because it is only used once during app startup, caching will just add a bit more mem overhead for no reason - return resolver.ResolveTypesWithAttribute(cacheResult: false); + return resolver.ResolveTypesWithAttribute(); } internal static IEnumerable ResolveSurfaceControllers(this PluginManager resolver) diff --git a/src/Umbraco.Web/Trees/ApplicationTreeRegistrar.cs b/src/Umbraco.Web/Trees/ApplicationTreeRegistrar.cs index 2cdd43be38..6666936c70 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeRegistrar.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeRegistrar.cs @@ -7,6 +7,9 @@ using umbraco.businesslogic; namespace Umbraco.Web.Trees { + //TODO: Is there any way to get this to execute lazily when needed? + // i.e. When the back office loads so that this doesn't execute on startup for a content request. + /// /// A startup handler for putting the tree config in the config file based on attributes found /// diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs index 080ca2a559..1d66121de2 100644 --- a/src/Umbraco.Web/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTreeController.cs @@ -22,6 +22,7 @@ namespace Umbraco.Web.Trees [LegacyBaseTree(typeof(loadContent))] [Tree(Constants.Applications.Content, Constants.Trees.Content, "Content")] [PluginController("UmbracoTrees")] + [CoreTree] public class ContentTreeController : ContentTreeControllerBase { protected override TreeNode CreateRootNode(FormDataCollection queryStrings) diff --git a/src/Umbraco.Web/Trees/DataTypeTreeController.cs b/src/Umbraco.Web/Trees/DataTypeTreeController.cs index 348fa88628..a5203da563 100644 --- a/src/Umbraco.Web/Trees/DataTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/DataTypeTreeController.cs @@ -15,6 +15,7 @@ namespace Umbraco.Web.Trees { [Tree(Constants.Applications.Developer, Constants.Trees.DataTypes, "Data Types")] [PluginController("UmbracoTrees")] + [CoreTree] public class DataTypeTreeController : TreeController { protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) diff --git a/src/Umbraco.Web/Trees/MediaTreeController.cs b/src/Umbraco.Web/Trees/MediaTreeController.cs index 8f806f980e..22fabe5da8 100644 --- a/src/Umbraco.Web/Trees/MediaTreeController.cs +++ b/src/Umbraco.Web/Trees/MediaTreeController.cs @@ -18,6 +18,7 @@ namespace Umbraco.Web.Trees [LegacyBaseTree(typeof(loadMedia))] [Tree(Constants.Applications.Media, Constants.Trees.Media, "Media")] [PluginController("UmbracoTrees")] + [CoreTree] public class MediaTreeController : ContentTreeControllerBase { protected override TreeNode CreateRootNode(FormDataCollection queryStrings) diff --git a/src/Umbraco.Web/Trees/MemberTreeController.cs b/src/Umbraco.Web/Trees/MemberTreeController.cs index 50c22812eb..8350662265 100644 --- a/src/Umbraco.Web/Trees/MemberTreeController.cs +++ b/src/Umbraco.Web/Trees/MemberTreeController.cs @@ -17,6 +17,7 @@ namespace Umbraco.Web.Trees [LegacyBaseTree(typeof (loadMembers))] [Tree(Constants.Applications.Members, Constants.Trees.Members, "Members")] [PluginController("UmbracoTrees")] + [CoreTree] public class MemberTreeController : TreeController { protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) diff --git a/src/Umbraco.Web/Trees/Menu/MenuItemCollection.cs b/src/Umbraco.Web/Trees/Menu/MenuItemCollection.cs index 5e4f305848..bd71a8d595 100644 --- a/src/Umbraco.Web/Trees/Menu/MenuItemCollection.cs +++ b/src/Umbraco.Web/Trees/Menu/MenuItemCollection.cs @@ -12,7 +12,7 @@ namespace Umbraco.Web.Trees.Menu [DataContract(Name = "menuItems", Namespace = "")] public class MenuItemCollection { - private readonly string _packageFolderName; + //private readonly string _packageFolderName; private readonly List _menuItems; public MenuItemCollection() @@ -24,19 +24,7 @@ namespace Umbraco.Web.Trees.Menu { _menuItems = new List(items); } - - public MenuItemCollection(string packageFolderName) - : this() - { - _packageFolderName = packageFolderName; - } - - public MenuItemCollection(string packageFolderName, IEnumerable items) - { - _packageFolderName = packageFolderName; - _menuItems = new List(items); - } - + /// /// Sets the default menu item alias to be shown when the menu is launched - this is optional and if not set then the menu will just be shown normally. /// @@ -63,7 +51,7 @@ namespace Umbraco.Web.Trees.Menu DetectLegacyActionMenu(action.GetType(), item); - AddItemToCollection(item); + _menuItems.Add(item); return item; } @@ -81,7 +69,7 @@ namespace Umbraco.Web.Trees.Menu /// public void AddMenuItem(MenuItem item) { - AddItemToCollection(item); + _menuItems.Add(item); } /// @@ -109,7 +97,7 @@ namespace Umbraco.Web.Trees.Menu Action = item.Action }; - AddItemToCollection(customMenuItem); + _menuItems.Add(customMenuItem); return customMenuItem; } @@ -152,7 +140,7 @@ namespace Umbraco.Web.Trees.Menu var item = CreateMenuItem(name, hasSeparator, additionalData); if (item != null) { - AddItemToCollection(item); + _menuItems.Add(item); return item; } return null; @@ -224,18 +212,6 @@ namespace Umbraco.Web.Trees.Menu } } - /// - /// This handles adding a menu item to the internal collection and will configure it accordingly - /// - /// - private void AddItemToCollection(MenuItem menuItem) - { - if (_packageFolderName.IsNullOrWhiteSpace() == false) - { - menuItem.SetPackageFolder(_packageFolderName); - } - _menuItems.Add(menuItem); - } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/Menu/MenuItemExtensions.cs b/src/Umbraco.Web/Trees/Menu/MenuItemExtensions.cs index 019b42ab19..32dfecc13a 100644 --- a/src/Umbraco.Web/Trees/Menu/MenuItemExtensions.cs +++ b/src/Umbraco.Web/Trees/Menu/MenuItemExtensions.cs @@ -6,11 +6,6 @@ namespace Umbraco.Web.Trees.Menu { public static class MenuItemExtensions { - /// - /// Used as a key for the AdditionalData to specify which package folder the menu launcher should look in for views - /// - internal const string PackageName = "packageName"; - /// /// Used as a key for the AdditionalData to specify a specific dialog title instead of the menu title /// @@ -32,16 +27,6 @@ namespace Umbraco.Web.Trees.Menu /// internal const string ActionViewKey = "actionView"; - /// - /// Sets the package folder to look for views in - /// - /// - /// - internal static void SetPackageFolder(this MenuItem menuItem, string packageFolder) - { - menuItem.AdditionalData[PackageName] = packageFolder; - } - /// /// Sets the menu item to display a dialog based on an angular view path /// diff --git a/src/Umbraco.Web/Trees/TreeAttribute.cs b/src/Umbraco.Web/Trees/TreeAttribute.cs index 72ae4044e9..5acf367738 100644 --- a/src/Umbraco.Web/Trees/TreeAttribute.cs +++ b/src/Umbraco.Web/Trees/TreeAttribute.cs @@ -2,6 +2,18 @@ namespace Umbraco.Web.Trees { + /// + /// Indicates that a tree is a core tree and shouldn't be treated as a plugin tree + /// + /// + /// This ensures that umbraco will look in the umbraco folders for views for this tree + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] + internal class CoreTreeAttribute : Attribute + { + + } + /// /// Identifies an application tree /// diff --git a/src/Umbraco.Web/Trees/TreeController.cs b/src/Umbraco.Web/Trees/TreeController.cs index e7df099c53..c624d75656 100644 --- a/src/Umbraco.Web/Trees/TreeController.cs +++ b/src/Umbraco.Web/Trees/TreeController.cs @@ -18,7 +18,6 @@ namespace Umbraco.Web.Trees public abstract class TreeController : UmbracoAuthorizedApiController { private readonly TreeAttribute _attribute; - private readonly MenuItemCollection _menuItemCollection; /// /// Remove the xml formatter... only support JSON! @@ -45,21 +44,8 @@ namespace Umbraco.Web.Trees //assign the properties of this object to those of the metadata attribute _attribute = treeAttributes.First(); - - //Create the menu item collection with the area nem already specified - _menuItemCollection = Metadata.AreaName.IsNullOrWhiteSpace() - ? new MenuItemCollection() - : new MenuItemCollection(Metadata.AreaName); } - - /// - /// Returns a menu item collection to be used to return the menu items from GetMenuForNode - /// - public MenuItemCollection MenuItems - { - get { return _menuItemCollection; } - } - + /// /// The method called to render the contents of the tree structure /// @@ -334,47 +320,6 @@ namespace Umbraco.Web.Trees if (handler != null) handler(instance, e); } #endregion - - #region Metadata - /// - /// stores the metadata about plugin controllers - /// - private static readonly ConcurrentDictionary MetadataStorage = new ConcurrentDictionary(); - - /// - /// Returns the metadata for this instance - /// - internal PluginControllerMetadata Metadata - { - get { return GetMetadata(this.GetType()); } - } - - /// - /// Returns the metadata for a PluginController - /// - /// - /// - internal static PluginControllerMetadata GetMetadata(Type type) - { - - return MetadataStorage.GetOrAdd(type, type1 => - { - var attribute = type.GetCustomAttribute(false); - - var meta = new PluginControllerMetadata() - { - AreaName = attribute == null ? null : attribute.AreaName, - ControllerName = ControllerExtensions.GetControllerName(type), - ControllerNamespace = type.Namespace, - ControllerType = type - }; - - MetadataStorage.TryAdd(type, meta); - - return meta; - }); - - } - #endregion + } } From b0dfc90557aaf34fbeb224bc4977391ddfaffb44 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 3 Oct 2013 12:11:22 +1000 Subject: [PATCH 04/25] Added docs on creating trees and view path location conventions. --- .../tutorials/Creating-Editors-Trees.ngdoc | 165 ++++++++++++++++++ .../MyPackage/Trees/LegacyTestTree.cs | 25 +-- src/Umbraco.Web/Trees/Menu/MenuItem.cs | 1 + 3 files changed, 179 insertions(+), 12 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/docs/src/tutorials/Creating-Editors-Trees.ngdoc diff --git a/src/Umbraco.Web.UI.Client/docs/src/tutorials/Creating-Editors-Trees.ngdoc b/src/Umbraco.Web.UI.Client/docs/src/tutorials/Creating-Editors-Trees.ngdoc new file mode 100644 index 0000000000..095719b05f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/docs/src/tutorials/Creating-Editors-Trees.ngdoc @@ -0,0 +1,165 @@ +@ngdoc overview +@name Creating a custom tree with an editor and dialog +@description + +##Overview + +This guide will explain how to create a simple custom tree an angular editor & dialog using standard conventions. This guide does not go into detail about how to persist data in your editors, it is a simple tutorial defining how routing interacts with your views and where your views need to be stored. + +So all the steps we will go through: + +- Creating a tree with a menu item +- Create an editor +- Create a dialog for the menu item + +##Create a tree + +First you need to define a tree class that inherits from `Umbraco.Web.Trees.TreeController` + + public class MyCustomTreeController : TreeController + { + } + +The name of your tree must be suffixed with the term 'Controller'. + +Next we need to add some attributes to the tree. The first one defines the section it belongs to, the tree alias and it's name. Ensure your tree alias is unique, tree aliases cannot overlap. + + [Tree("settings", "myTree", "My Tree")] + +The 2nd attribute does 2 things - Tells Umbraco how to route the tree and tells Umbraco where to find the view files. This attribute is not required but if you do not specify it then the view location conventions will not work. + + [PluginController("MyPackage")] + +There are 2 methods that need to be overriden from the TreeController class: `GetTreeNodes` & `GetMenuForNode`. This example will create 3 nodes underneath the root node: + + protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + { + //check if we're rendering the root node's children + if (id == Constants.System.Root.ToInvariantString()) + { + var tree = new TreeNodeCollection + { + CreateTreeNode("1", queryStrings, "My Node 1"), + CreateTreeNode("2", queryStrings, "My Node 2"), + CreateTreeNode("3", queryStrings, "My Node 3") + }; + return tree; + } + //this tree doesn't suport rendering more than 1 level + throw new NotSupportedException(); + } + +Next we'll create a menu item for each node, in this case its a 'Create' menu item + + protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + { + var menu = new MenuItemCollection(); + menu.AddMenuItem(new MenuItem("create", "Create")); + return menu; + } + +That's it, the whole tree looks like this: + + [Tree("settings", "myTree", "My Tree")] + [PluginController("MyPackage")] + public class MyCustomTreeController : TreeController + { + protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) + { + //check if we're rendering the root node's children + if (id == Constants.System.Root.ToInvariantString()) + { + var tree = new TreeNodeCollection + { + CreateTreeNode("1", queryStrings, "My Node 1"), + CreateTreeNode("2", queryStrings, "My Node 2"), + CreateTreeNode("3", queryStrings, "My Node 3") + }; + return tree; + } + //this tree doesn't suport rendering more than 1 level + throw new NotSupportedException(); + } + protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) + { + var menu = new MenuItemCollection(); + menu.AddMenuItem(new MenuItem("create", "Create")); + return menu; + } + } + +##View path conventions + +Now that we've created our tree it is important to understand Umbraco conventions and where it will look for your views for editors and dialogs. + +###Angular editor routes + +The main angular route to load in editors is */:section/:tree/:method/:id* + +Umbraco will load in views for this route based on these conventions: + + * If it is a core tree - views will be loaded from: */umbraco/views/{treetype}/{method}.html* + * If it is a custom (package) tree - views will be loaded from: */App_Plugins/{mypackage}/umbraco/{treetype}/{method}.html* + +###Editor locations + +By default each tree node's 'method' is assigned as 'edit' therefore these are the view paths for an editor when a tree node is clicked: + + * If it is a core tree - views will be loaded from: */umbraco/views/{treetype}/edit.html* + * If it is a custom (package) tree - views will be loaded from: */App_Plugins/{mypackage}/umbraco/{treetype}/edit.html* + +Developers can specify a custom `RoutePath` for any tree node which will cause umbraco to route to that specific location. + +###Dialog locations + +Dialog view path locations are similar to editors: + + * If it is a core tree - views will be loaded from: umbraco/views/{treetype}/{action}.html + * If it is a custom (package) tree - views will be loaded from: /App_Plugins/{mypackage}/umbraco/{treetype}/{action}.html + +'action' is the alias of your menu item, for example in the menu item in the example above this would be 'create'. + +##Create an editor + +An editor is simply an angular view (html file) so you can really do whatever you'd like! This tutorial will simply create a hello world editor showing the id of the item being edited. + +###Create a controller + +First thing we'll do is create an angular controller for the editor, this controller will be contained in a file found beside the view - *the file naming conventions are based on the controller file naming conventions in the Umbraco core*. + +/App_Plugins/MyPackage/Umbraco/MyTree/mypackage.mytree.edit.controller.js + +The controller is super simple, at it is going to do is assign a property to the $scope which shows the current item id being edited: + + 'use strict'; + (function () { + //create the controller + function myTreeEditController($scope, $routeParams) { + //set a property on the scope equal to the current route id + $scope.id = $routeParams.id; + }; + //register the controller + angular.module("umbraco").controller('MyPackage.MyTree.EditController', myTreeEditController); + })(); + +###Create a view + +As per the conventions above our editor view will need to be located at: + +/App_Plugins/MyPackage/Umbraco/MyTree/edit.html + +The view is simple, it is just going to show the current id being edited + +
+

Hello world!

+

+ You are current editing an item with id {{id}} +

+
+ +##Create a dialog + +This is the same principle as an editor, you just need to follow conventions. Based on the above conventions the 'create' dialog view will be located here: + +/App_Plugins/MyPackage/Umbraco/MyTree/create.html + diff --git a/src/Umbraco.Web.UI/App_Plugins/MyPackage/Trees/LegacyTestTree.cs b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Trees/LegacyTestTree.cs index 4971384529..1dfaf4da44 100644 --- a/src/Umbraco.Web.UI/App_Plugins/MyPackage/Trees/LegacyTestTree.cs +++ b/src/Umbraco.Web.UI/App_Plugins/MyPackage/Trees/LegacyTestTree.cs @@ -10,29 +10,29 @@ using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.UI.App_Plugins.MyPackage.Trees { - [Tree(Constants.Applications.Settings, "myTree", "My Tree")] + [Tree("settings", "myTree", "My Tree")] [PluginController("MyPackage")] public class MyCustomTreeController : TreeController { protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) { + //check if we're rendering the root node's children if (id == Constants.System.Root.ToInvariantString()) { var tree = new TreeNodeCollection - { - CreateTreeNode("1", queryStrings, "My Node 1"), - CreateTreeNode("2", queryStrings, "My Node 2"), - CreateTreeNode("3", queryStrings, "My Node 3") - }; + { + CreateTreeNode("1", queryStrings, "My Node 1"), + CreateTreeNode("2", queryStrings, "My Node 2"), + CreateTreeNode("3", queryStrings, "My Node 3") + }; return tree; } + //this tree doesn't suport rendering more than 1 level throw new NotSupportedException(); } - protected override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { var menu = new MenuItemCollection(); - menu.AddMenuItem(new MenuItem("create", "Create")); return menu; } @@ -40,7 +40,8 @@ namespace Umbraco.Web.UI.App_Plugins.MyPackage.Trees public class LegacyTestTree : BaseTree { - public LegacyTestTree(string application) : base(application) + public LegacyTestTree(string application) + : base(application) { } @@ -52,10 +53,10 @@ namespace Umbraco.Web.UI.App_Plugins.MyPackage.Trees public override int StartNodeID { get { return -1; } - } + } public override void RenderJS(ref StringBuilder javascript) - { + { } public override void Render(ref XmlTree tree) @@ -70,7 +71,7 @@ namespace Umbraco.Web.UI.App_Plugins.MyPackage.Trees protected override void CreateRootNode(ref XmlTreeNode rootNode) { - + } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/Menu/MenuItem.cs b/src/Umbraco.Web/Trees/Menu/MenuItem.cs index ed5d9c5778..031c585930 100644 --- a/src/Umbraco.Web/Trees/Menu/MenuItem.cs +++ b/src/Umbraco.Web/Trees/Menu/MenuItem.cs @@ -15,6 +15,7 @@ namespace Umbraco.Web.Trees.Menu public MenuItem() { AdditionalData = new Dictionary(); + Icon = "folder"; } public MenuItem(string alias, string name) From 6ac724951bc17071c64d54ad1ca30e8b2ff3d532 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 3 Oct 2013 12:18:21 +1000 Subject: [PATCH 05/25] Explicitly adds automapper to the UI proj so we don't get that strange YSOD that says it's not there sometimes. --- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 8 ++++++++ src/Umbraco.Web.UI/packages.config | 1 + 2 files changed, 9 insertions(+) diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 06b5f301ab..b79510e0e8 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -107,6 +107,14 @@ {07fbc26b-2927-4a22-8d96-d644c667fecc} UmbracoExamine + + False + ..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.dll + + + False + ..\packages\AutoMapper.3.0.0\lib\net40\AutoMapper.Net4.dll + False ..\packages\ClientDependency.1.7.0.4\lib\ClientDependency.Core.dll diff --git a/src/Umbraco.Web.UI/packages.config b/src/Umbraco.Web.UI/packages.config index 0e8d39bbe0..b4df6b2899 100644 --- a/src/Umbraco.Web.UI/packages.config +++ b/src/Umbraco.Web.UI/packages.config @@ -1,5 +1,6 @@  + From 55247fe31dac59ce7f2aa9adf1d39fb900a90564 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 3 Oct 2013 12:45:40 +1000 Subject: [PATCH 06/25] Finally got around to changing all calls to umbraco.IO to Umbraco.Core.IO - that'll clear up several hundreds of warnings :) --- src/Umbraco.Tests/BusinessLogic/BaseTest.cs | 2 +- .../Routing/UmbracoModuleTests.cs | 2 +- src/Umbraco.Web.UI/install/steps/theend.ascx | 4 +-- src/Umbraco.Web.UI/umbraco/Default.aspx | 2 +- .../umbraco/Search/QuickSearch.ascx | 2 +- .../GenericProperties/GenericProperty.ascx | 4 +-- .../umbraco/controls/ProgressBar.ascx | 2 +- .../umbraco/controls/Tree/TreeControl.ascx | 4 +-- .../umbraco/developer/Xslt/editXslt.aspx | 2 +- .../umbraco/dialogs/ChangeDocType.aspx | 2 +- .../umbraco/plugins/uGoLive/Dashboard.ascx | 2 +- .../umbraco/settings/editTemplate.aspx | 4 +-- src/Umbraco.Web.UI/umbraco/umbraco.aspx | 4 +-- .../FileExtensionIconThumbnailProvider.cs | 2 +- .../ImageThumbnailProvider.cs | 2 +- .../MediaTypeIconThumbnailProvider.cs | 2 +- src/Umbraco.Web/UI/Controls/FolderBrowser.cs | 2 +- src/Umbraco.Web/UmbracoContext.cs | 2 +- .../umbraco.presentation/LegacyClasses.cs | 2 +- .../umbraco.presentation/NotFoundHandlers.cs | 2 +- .../UmbracoServerUtility.cs | 2 +- .../steps/Definitions/LegacyClasses.cs | 12 +++---- .../install/steps/LegacyClasses.cs | 18 +++++------ .../umbraco.presentation/library.cs | 4 +-- .../umbraco.presentation/python.cs | 2 +- .../umbraco.presentation/requestModule.cs | 2 +- .../umbraco.presentation/template.cs | 2 +- .../Controls/LiveEditingToolbar.cs | 2 +- .../Modules/CreateModule/CreateModule.cs | 2 +- .../Modules/DeleteModule/DeleteModule.cs | 2 +- .../Modules/MacroModule/MacroModule.cs | 2 +- .../Modules/SkinModule/ImageUploader.aspx.cs | 11 ++++--- .../Modules/SkinModule/SkinCustomizer.ascx.cs | 4 +-- .../Modules/SkinModule/SkinModule.cs | 2 +- .../UnpublishModule/UnpublishModule.cs | 2 +- .../umbraco/Trees/TreeService.cs | 2 +- .../umbraco/Trees/XmlTree.cs | 2 +- .../umbraco/Trees/loadDLRScripts.cs | 2 +- .../umbraco/Trees/loadPython.cs | 2 +- .../umbraco/Trees/loadScripts.cs | 2 +- .../umbraco/Trees/loadTemplates.cs | 7 +++-- .../umbraco/Trees/loadXslt.cs | 2 +- .../umbraco/actions/preview.aspx.cs | 4 +-- .../umbraco/channels/UmbracoMetaWeblogAPI.cs | 2 +- .../umbraco/channels/config.cs | 2 +- .../umbraco/controls/ContentTypeControl.cs | 2 +- .../GenericProperties/GenericProperty.ascx | 4 +-- .../GenericPropertyWrapper.cs | 2 +- .../Images/ImageViewerUpdater.asmx.cs | 2 +- .../umbraco/controls/ProgressBar.ascx | 2 +- .../umbraco/controls/SaveClickEventArgs.cs | 2 +- .../controls/Tree/CustomTreeControl.cs | 2 +- .../umbraco/controls/Tree/TreeControl.ascx | 4 +-- .../umbraco/controls/macroParameterControl.cs | 2 +- .../umbraco/create/CreatedPackageTasks.cs | 2 +- .../umbraco/create/DLRScripting.ascx.cs | 5 +-- .../umbraco/create/DLRScriptingTasks.cs | 4 +-- .../umbraco/create/DataTypeTasks.cs | 2 +- .../umbraco/create/MediaTypeTasks.cs | 2 +- .../umbraco/create/MemberGroupTasks.cs | 2 +- .../umbraco/create/MemberTypeTasks.cs | 2 +- .../umbraco/create/NewMemberUIEventArgs.cs | 2 +- .../umbraco/create/PythonTasks.cs | 2 +- .../umbraco/create/ScriptTasks.cs | 2 +- .../umbraco/create/StylesheetTasks.cs | 2 +- .../umbraco/create/contentItemTasks.cs | 2 +- .../umbraco/create/contentItemTypeTasks.cs | 2 +- .../umbraco/create/contentTasks.cs | 2 +- .../umbraco/create/dictionaryTasks.cs | 2 +- .../umbraco/create/languageTasks.cs | 2 +- .../umbraco/create/macroTasks.cs | 2 +- .../umbraco/create/mediaTasks.cs | 2 +- .../umbraco/create/memberTasks.cs | 2 +- .../umbraco/create/nodetypeTasks.cs | 2 +- .../umbraco/create/script.ascx.cs | 2 +- .../umbraco/create/stylesheetPropertyTasks.cs | 2 +- .../umbraco/create/templateTasks.cs | 2 +- .../umbraco/create/userTasks.cs | 2 +- .../umbraco/dashboard.aspx.cs | 2 +- .../umbraco/dashboard/FeedProxy.aspx.cs | 2 +- .../umbraco/dashboard/LatestEdits.ascx.cs | 2 +- .../developer/DataTypes/editDatatype.aspx.cs | 2 +- .../Packages/BrowseRepository.aspx.cs | 2 +- .../developer/Packages/editPackage.aspx.cs | 4 +-- .../developer/Xslt/getXsltStatus.asmx.cs | 2 +- .../developer/Xslt/xsltVisualize.aspx.cs | 2 +- .../umbraco/dialogs/imageViewer.aspx.cs | 2 +- .../umbraco/dialogs/uploadImage.aspx.cs | 2 +- .../umbraco/login.aspx.cs | 2 +- .../masterpages/umbracoDialog.Master.cs | 3 +- .../umbraco/plugins/tinymce3/GzipModule.cs | 4 +-- .../settings/EditDictionaryItem.aspx.cs | 2 +- .../umbraco/settings/editTemplate.aspx.cs | 10 +++--- .../settings/scripts/editScript.aspx.cs | 2 +- .../umbraco/templateControls/ItemRenderer.cs | 2 +- .../umbraco/translation/default.aspx.cs | 2 +- .../umbraco/translation/xml.aspx.cs | 2 +- .../umbraco/umbraco.aspx.cs | 4 +-- .../umbraco/users/EditUser.aspx.cs | 2 +- .../umbraco/users/EditUserType.aspx.cs | 2 +- .../umbraco/users/PermissionEditor.aspx.cs | 2 +- .../umbraco/users/PermissionsHandler.asmx.cs | 2 +- .../umbracobase/baseHttpModule.cs | 7 +++-- .../umbracobase/restExtension.cs | 2 +- .../RazorCore/RazorMacroEngine.cs | 2 +- .../BasePages/ClientTools.cs | 2 +- src/umbraco.businesslogic/GlobalSettings.cs | 2 +- src/umbraco.businesslogic/Utils/TypeFinder.cs | 2 +- src/umbraco.businesslogic/xmlHelper.cs | 2 +- src/umbraco.cms/businesslogic/CMSNode.cs | 4 +-- .../businesslogic/CMSPreviewNode.cs | 2 +- .../businesslogic/Packager/Installer.cs | 10 +++--- .../PackageActions/addDashboardSection.cs | 2 +- .../PackageActions/addProxyFeedHost.cs | 2 +- .../PackageActions/addRestExtension.cs | 2 +- .../PackageActions/addXsltExtension.cs | 2 +- .../PackageInstance/CreatedPackage.cs | 6 ++-- .../PackageInstance/InstalledPackage.cs | 2 +- .../Packager/PackageInstance/utill.cs | 2 +- .../Packager/Repositories/Repository.cs | 2 +- .../businesslogic/Packager/Settings.cs | 2 +- .../businesslogic/Packager/data.cs | 13 ++++---- .../businesslogic/skinning/Skin.cs | 31 ++++++++++--------- .../skinning/tasks/AddStyleSheetToTemplate.cs | 10 +++--- .../businesslogic/skinning/tasks/ModifyCss.cs | 8 ++--- .../skinning/tasks/ModifyTemplate.cs | 6 ++-- .../businesslogic/translation/Translation.cs | 2 +- src/umbraco.cms/businesslogic/web/Access.cs | 2 +- .../businesslogic/web/DocumentVersionList.cs | 2 +- .../businesslogic/workflow/Notification.cs | 2 +- src/umbraco.controls/CodeArea.cs | 2 +- src/umbraco.controls/ProgressBar.cs | 3 +- src/umbraco.controls/Splitter.cs | 4 +-- .../TreePicker/BaseTreePicker.cs | 2 +- src/umbraco.controls/TreeUrlGenerator.cs | 6 ++-- .../SelectedItemsTemplate.cs | 2 +- src/umbraco.editorControls/XmlData.cs | 3 +- .../colorpicker/colorPicker.cs | 2 +- .../imagecropper/ImageInfo.cs | 2 +- .../macrocontainer/Editor.cs | 4 +-- .../relatedlinks/RelatedLinksDataEditor.cs | 2 +- .../simpleEditor/simpleEditor.cs | 8 ++--- .../tinyMCE3/TinyMCE.cs | 4 +-- .../tinyMCE3/webcontrol/plugin/GzipModule.cs | 2 +- .../tinymce/tinyMCEConfiguration.cs | 4 +-- .../ultimatePickerDataEditor.cs | 2 +- .../usercontrolPrevalueEditor.cs | 10 +++--- src/umbraco.macroRenderings/content.cs | 2 +- src/umbraco.macroRenderings/media.cs | 1 - 149 files changed, 245 insertions(+), 237 deletions(-) diff --git a/src/Umbraco.Tests/BusinessLogic/BaseTest.cs b/src/Umbraco.Tests/BusinessLogic/BaseTest.cs index 73d51e7816..50e6a43331 100644 --- a/src/Umbraco.Tests/BusinessLogic/BaseTest.cs +++ b/src/Umbraco.Tests/BusinessLogic/BaseTest.cs @@ -7,7 +7,7 @@ using Umbraco.Core; using Umbraco.Tests.TestHelpers; using umbraco.BusinessLogic; using umbraco.DataLayer; -using umbraco.IO; +using Umbraco.Core.IO; using GlobalSettings = umbraco.GlobalSettings; namespace Umbraco.Tests.BusinessLogic diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index d31e6dbec8..ea62370655 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -10,7 +10,7 @@ using Umbraco.Tests.TestHelpers; using Umbraco.Web; using Umbraco.Web.Routing; using umbraco.BusinessLogic; -using umbraco.IO; +using Umbraco.Core.IO; using umbraco.cms.businesslogic.cache; using umbraco.cms.businesslogic.template; diff --git a/src/Umbraco.Web.UI/install/steps/theend.ascx b/src/Umbraco.Web.UI/install/steps/theend.ascx index b2b4ffe395..ea0d00696c 100644 --- a/src/Umbraco.Web.UI/install/steps/theend.ascx +++ b/src/Umbraco.Web.UI/install/steps/theend.ascx @@ -31,8 +31,8 @@ jQuery(document).ready(function () {
If you installed a starter kit you can start by configuring your new site, just click "Preview your new website" and follow the instructions. Or to start adding content right away click "Set up your new website"

diff --git a/src/Umbraco.Web.UI/umbraco/Default.aspx b/src/Umbraco.Web.UI/umbraco/Default.aspx index 963ced80c2..d3421e3997 100644 --- a/src/Umbraco.Web.UI/umbraco/Default.aspx +++ b/src/Umbraco.Web.UI/umbraco/Default.aspx @@ -12,7 +12,7 @@ } - +