diff --git a/src/Umbraco.Core/ConfigsExtensions.cs b/src/Umbraco.Core/ConfigsExtensions.cs index 0fcea5f430..6fdf7ea3b9 100644 --- a/src/Umbraco.Core/ConfigsExtensions.cs +++ b/src/Umbraco.Core/ConfigsExtensions.cs @@ -2,7 +2,6 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Dashboard; using Umbraco.Core.Configuration.Grid; using Umbraco.Core.Configuration.HealthChecks; using Umbraco.Core.Configuration.UmbracoSettings; @@ -22,9 +21,6 @@ namespace Umbraco.Core public static IUmbracoSettingsSection Settings(this Configs configs) => configs.GetConfig(); - public static IDashboardSection Dashboards(this Configs configs) - => configs.GetConfig(); - public static IHealthChecks HealthChecks(this Configs configs) => configs.GetConfig(); @@ -40,7 +36,6 @@ namespace Umbraco.Core configs.Add(() => new GlobalSettings()); configs.Add("umbracoConfiguration/settings"); - configs.Add("umbracoConfiguration/dashBoard"); configs.Add("umbracoConfiguration/HealthChecks"); configs.Add(() => new CoreDebug()); diff --git a/src/Umbraco.Core/Configuration/Dashboard/AccessElement.cs b/src/Umbraco.Core/Configuration/Dashboard/AccessElement.cs deleted file mode 100644 index 01538c8e0b..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/AccessElement.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Xml.Linq; - -namespace Umbraco.Core.Configuration.Dashboard -{ - internal class AccessElement : RawXmlConfigurationElement, IAccess - { - public AccessElement() - { } - - public AccessElement(XElement rawXml) - : base(rawXml) - { } - - public IEnumerable Rules - { - get - { - var result = new List(); - if (RawXml == null) return result; - - result.AddRange(RawXml.Elements("deny").Select(x => new AccessRule {Type = AccessRuleType.Deny, Value = x.Value })); - result.AddRange(RawXml.Elements("grant").Select(x => new AccessRule { Type = AccessRuleType.Grant, Value = x.Value })); - result.AddRange(RawXml.Elements("grantBySection").Select(x => new AccessRule { Type = AccessRuleType.GrantBySection, Value = x.Value })); - return result; - } - } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/AreaCollection.cs b/src/Umbraco.Core/Configuration/Dashboard/AreaCollection.cs deleted file mode 100644 index 31cc3eaec8..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/AreaCollection.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Configuration; - -namespace Umbraco.Core.Configuration.Dashboard -{ - internal class AreaCollection : ConfigurationElementCollection, IEnumerable - { - protected override ConfigurationElement CreateNewElement() - { - return new AreaElement(); - } - - protected override object GetElementKey(ConfigurationElement element) - { - return ((AreaElement) element).Value; - } - - IEnumerator IEnumerable.GetEnumerator() - { - for (var i = 0; i < Count; i++) - { - yield return BaseGet(i) as IArea; - } - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/AreaElement.cs b/src/Umbraco.Core/Configuration/Dashboard/AreaElement.cs deleted file mode 100644 index 20393f89d8..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/AreaElement.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Configuration; - -namespace Umbraco.Core.Configuration.Dashboard -{ - internal class AreaElement : InnerTextConfigurationElement, IArea - { - string IArea.AreaName - { - get { return Value; } - } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/AreasElement.cs b/src/Umbraco.Core/Configuration/Dashboard/AreasElement.cs deleted file mode 100644 index 92e51c9b73..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/AreasElement.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Configuration; - -namespace Umbraco.Core.Configuration.Dashboard -{ - internal class AreasElement : ConfigurationElement - { - [ConfigurationCollection(typeof(SectionCollection), AddItemName = "area")] - [ConfigurationProperty("", IsDefaultCollection = true)] - public AreaCollection AreaCollection - { - get { return (AreaCollection)base[""]; } - set { base[""] = value; } - } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/ControlCollection.cs b/src/Umbraco.Core/Configuration/Dashboard/ControlCollection.cs deleted file mode 100644 index b8aa40da7f..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/ControlCollection.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Configuration; - -namespace Umbraco.Core.Configuration.Dashboard -{ - internal class ControlCollection : ConfigurationElementCollection, IEnumerable - { - internal void Add(ControlElement c) - { - BaseAdd(c); - } - - protected override ConfigurationElement CreateNewElement() - { - return new ControlElement(); - } - - protected override object GetElementKey(ConfigurationElement element) - { - return ((ControlElement)element).ControlPath; - } - - IEnumerator IEnumerable.GetEnumerator() - { - for (var i = 0; i < Count; i++) - { - yield return BaseGet(i) as IDashboardControl; - } - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/ControlElement.cs b/src/Umbraco.Core/Configuration/Dashboard/ControlElement.cs deleted file mode 100644 index 20dac7460e..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/ControlElement.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Configuration; -using System.Linq; -using System.Xml.Linq; - -namespace Umbraco.Core.Configuration.Dashboard -{ - - internal class ControlElement : RawXmlConfigurationElement, IDashboardControl - { - public string PanelCaption - { - get - { - var panelCaption = RawXml.Attribute("panelCaption"); - return panelCaption == null ? "" : panelCaption.Value; - } - } - - public AccessElement Access - { - get - { - var access = RawXml.Element("access"); - return access == null ? new AccessElement() : new AccessElement(access); - } - } - - public string ControlPath - { - get - { - //we need to return the first (and only) text element of the children (wtf... who designed this configuration ! :P ) - var txt = RawXml.Nodes().OfType().FirstOrDefault(); - if (txt == null) - { - throw new ConfigurationErrorsException("The control element must contain a text node indicating the control path"); - } - return txt.Value.Trim(); - } - } - - IAccess IDashboardControl.AccessRights => Access; - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/DashboardSection.cs b/src/Umbraco.Core/Configuration/Dashboard/DashboardSection.cs deleted file mode 100644 index 12bf0522e0..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/DashboardSection.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Text; -using System.Threading.Tasks; - -namespace Umbraco.Core.Configuration.Dashboard -{ - internal class DashboardSection : ConfigurationSection, IDashboardSection - { - [ConfigurationCollection(typeof(SectionCollection), AddItemName = "section")] - [ConfigurationProperty("", IsDefaultCollection = true)] - public SectionCollection SectionCollection - { - get { return (SectionCollection)base[""]; } - set { base[""] = value; } - } - - IEnumerable IDashboardSection.Sections - { - get { return SectionCollection; } - } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/IAccess.cs b/src/Umbraco.Core/Configuration/Dashboard/IAccess.cs deleted file mode 100644 index 8ac1b18cca..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/IAccess.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace Umbraco.Core.Configuration.Dashboard -{ - public interface IAccess - { - IEnumerable Rules { get; } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/IArea.cs b/src/Umbraco.Core/Configuration/Dashboard/IArea.cs deleted file mode 100644 index 25401db408..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/IArea.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Umbraco.Core.Configuration.Dashboard -{ - public interface IArea - { - string AreaName { get; } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/IDashboardControl.cs b/src/Umbraco.Core/Configuration/Dashboard/IDashboardControl.cs deleted file mode 100644 index cdf05af1ec..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/IDashboardControl.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Umbraco.Core.Configuration.Dashboard -{ - public interface IDashboardControl - { - string PanelCaption { get; } - - string ControlPath { get; } - - IAccess AccessRights { get; } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/IDashboardSection.cs b/src/Umbraco.Core/Configuration/Dashboard/IDashboardSection.cs deleted file mode 100644 index 32dfc6653d..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/IDashboardSection.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace Umbraco.Core.Configuration.Dashboard -{ - public interface IDashboardSection - { - IEnumerable Sections { get; } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/IDashboardTab.cs b/src/Umbraco.Core/Configuration/Dashboard/IDashboardTab.cs deleted file mode 100644 index 914b226265..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/IDashboardTab.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Collections.Generic; - -namespace Umbraco.Core.Configuration.Dashboard -{ - public interface IDashboardTab - { - string Caption { get; } - - IEnumerable Controls { get; } - - IAccess AccessRights { get; } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/ISection.cs b/src/Umbraco.Core/Configuration/Dashboard/ISection.cs deleted file mode 100644 index 1005c0750d..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/ISection.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; - -namespace Umbraco.Core.Configuration.Dashboard -{ - public interface ISection - { - string Alias { get; } - - IEnumerable Areas { get; } - - IEnumerable Tabs { get; } - - IAccess AccessRights { get; } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/SectionCollection.cs b/src/Umbraco.Core/Configuration/Dashboard/SectionCollection.cs deleted file mode 100644 index 5717bd28c3..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/SectionCollection.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Configuration; - -namespace Umbraco.Core.Configuration.Dashboard -{ - internal class SectionCollection : ConfigurationElementCollection, IEnumerable - { - internal void Add(SectionElement c) - { - BaseAdd(c); - } - - protected override ConfigurationElement CreateNewElement() - { - return new SectionElement(); - } - - protected override object GetElementKey(ConfigurationElement element) - { - return ((SectionElement)element).Alias; - } - - IEnumerator IEnumerable.GetEnumerator() - { - for (var i = 0; i < Count; i++) - { - yield return BaseGet(i) as ISection; - } - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/SectionElement.cs b/src/Umbraco.Core/Configuration/Dashboard/SectionElement.cs deleted file mode 100644 index 09049c13db..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/SectionElement.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Collections.Generic; -using System.Configuration; -using System.Linq; - -namespace Umbraco.Core.Configuration.Dashboard -{ - internal class SectionElement : ConfigurationElement, ISection - { - [ConfigurationProperty("alias", IsRequired = true)] - public string Alias - { - get { return (string) this["alias"]; } - } - - [ConfigurationProperty("areas", IsRequired = true)] - public AreasElement Areas - { - get { return (AreasElement)this["areas"]; } - } - - [ConfigurationProperty("access")] - public AccessElement Access - { - get { return (AccessElement)this["access"]; } - } - - [ConfigurationCollection(typeof(SectionCollection), AddItemName = "tab")] - [ConfigurationProperty("", IsDefaultCollection = true)] - public TabCollection TabCollection - { - get { return (TabCollection)base[""]; } - set { base[""] = value; } - } - - IEnumerable ISection.Tabs - { - get { return TabCollection; } - } - - IEnumerable ISection.Areas - { - get { return Areas.AreaCollection.Cast().Select(x => x.Value); } - } - - IAccess ISection.AccessRights - { - get { return Access; } - } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/TabCollection.cs b/src/Umbraco.Core/Configuration/Dashboard/TabCollection.cs deleted file mode 100644 index 1b77ffd3fb..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/TabCollection.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Configuration; - -namespace Umbraco.Core.Configuration.Dashboard -{ - internal class TabCollection : ConfigurationElementCollection, IEnumerable - { - internal void Add(TabElement c) - { - BaseAdd(c); - } - - protected override ConfigurationElement CreateNewElement() - { - return new TabElement(); - } - - protected override object GetElementKey(ConfigurationElement element) - { - return ((TabElement)element).Caption; - } - - IEnumerator IEnumerable.GetEnumerator() - { - for (var i = 0; i < Count; i++) - { - yield return BaseGet(i) as IDashboardTab; - } - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/TabElement.cs b/src/Umbraco.Core/Configuration/Dashboard/TabElement.cs deleted file mode 100644 index b92394596e..0000000000 --- a/src/Umbraco.Core/Configuration/Dashboard/TabElement.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Collections.Generic; -using System.Configuration; - -namespace Umbraco.Core.Configuration.Dashboard -{ - internal class TabElement : ConfigurationElement, IDashboardTab - { - [ConfigurationProperty("caption", IsRequired = true)] - public string Caption - { - get { return (string)this["caption"]; } - } - - [ConfigurationProperty("access")] - public AccessElement Access - { - get { return (AccessElement)this["access"]; } - } - - [ConfigurationCollection(typeof(ControlCollection), AddItemName = "control")] - [ConfigurationProperty("", IsDefaultCollection = true)] - public ControlCollection ControlCollection - { - get { return (ControlCollection)base[""]; } - set { base[""] = value; } - } - - IEnumerable IDashboardTab.Controls - { - get { return ControlCollection; } - } - - IAccess IDashboardTab.AccessRights - { - get { return Access; } - } - } -} diff --git a/src/Umbraco.Core/Configuration/Dashboard/AccessRule.cs b/src/Umbraco.Core/Dashboards/AccessRule.cs similarity index 85% rename from src/Umbraco.Core/Configuration/Dashboard/AccessRule.cs rename to src/Umbraco.Core/Dashboards/AccessRule.cs index fe6840ff64..70f9da8fa9 100644 --- a/src/Umbraco.Core/Configuration/Dashboard/AccessRule.cs +++ b/src/Umbraco.Core/Dashboards/AccessRule.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.Configuration.Dashboard +namespace Umbraco.Core.Dashboards { /// /// Implements . diff --git a/src/Umbraco.Core/Configuration/Dashboard/AccessRuleType.cs b/src/Umbraco.Core/Dashboards/AccessRuleType.cs similarity index 93% rename from src/Umbraco.Core/Configuration/Dashboard/AccessRuleType.cs rename to src/Umbraco.Core/Dashboards/AccessRuleType.cs index cb9ce983fe..efed361f6c 100644 --- a/src/Umbraco.Core/Configuration/Dashboard/AccessRuleType.cs +++ b/src/Umbraco.Core/Dashboards/AccessRuleType.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.Configuration.Dashboard +namespace Umbraco.Core.Dashboards { /// /// Defines dashboard access rules type. diff --git a/src/Umbraco.Core/Configuration/Dashboard/IAccessRule.cs b/src/Umbraco.Core/Dashboards/IAccessRule.cs similarity index 88% rename from src/Umbraco.Core/Configuration/Dashboard/IAccessRule.cs rename to src/Umbraco.Core/Dashboards/IAccessRule.cs index 8b51b1b73a..f44a846248 100644 --- a/src/Umbraco.Core/Configuration/Dashboard/IAccessRule.cs +++ b/src/Umbraco.Core/Dashboards/IAccessRule.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.Configuration.Dashboard +namespace Umbraco.Core.Dashboards { /// /// Represents an access rule. diff --git a/src/Umbraco.Core/Dashboards/IDashboardSection.cs b/src/Umbraco.Core/Dashboards/IDashboardSection.cs new file mode 100644 index 0000000000..90d351bcd2 --- /dev/null +++ b/src/Umbraco.Core/Dashboards/IDashboardSection.cs @@ -0,0 +1,30 @@ +namespace Umbraco.Core.Dashboards +{ + public interface IDashboardSection + { + /// + /// Display name of the dashboard tab + /// + string Name { get; } + + /// + /// Alias to refer to this dashboard via code + /// + string Alias { get; } + + /// + /// A collection of sections/application aliases that this dashboard will appear on + /// + string[] Sections { get; } + + /// + /// The HTML view to load for the dashboard + /// + string View { get; } + + /// + /// Dashboards can be shown/hidden based on access rights + /// + IAccessRule[] AccessRules { get; } + } +} diff --git a/src/Umbraco.Core/Manifest/DashboardAccessRuleConverter.cs b/src/Umbraco.Core/Manifest/DashboardAccessRuleConverter.cs index c627728a32..67c5a5824e 100644 --- a/src/Umbraco.Core/Manifest/DashboardAccessRuleConverter.cs +++ b/src/Umbraco.Core/Manifest/DashboardAccessRuleConverter.cs @@ -1,7 +1,7 @@ using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using Umbraco.Core.Configuration.Dashboard; +using Umbraco.Core.Dashboards; using Umbraco.Core.Serialization; namespace Umbraco.Core.Manifest diff --git a/src/Umbraco.Core/Manifest/ManifestDashboardDefinition.cs b/src/Umbraco.Core/Manifest/ManifestDashboardDefinition.cs index 83f047b264..b2b3fd5dfb 100644 --- a/src/Umbraco.Core/Manifest/ManifestDashboardDefinition.cs +++ b/src/Umbraco.Core/Manifest/ManifestDashboardDefinition.cs @@ -1,12 +1,12 @@ using System; using System.ComponentModel; using Newtonsoft.Json; -using Umbraco.Core.Configuration.Dashboard; +using Umbraco.Core.Dashboards; using Umbraco.Core.IO; namespace Umbraco.Core.Manifest { - public class ManifestDashboardDefinition + public class ManifestDashboardDefinition : IDashboardSection { private string _view; @@ -32,5 +32,6 @@ namespace Umbraco.Core.Manifest [JsonProperty("access")] public IAccessRule[] AccessRules { get; set; } = Array.Empty(); + } } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 0ff88da2f3..993797392f 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -211,26 +211,6 @@ - - - - - - - - - - - - - - - - - - - - @@ -331,6 +311,10 @@ + + + + diff --git a/src/Umbraco.Tests/Configurations/DashboardSettings/DashboardSettingsTests.cs b/src/Umbraco.Tests/Configurations/DashboardSettings/DashboardSettingsTests.cs index 920de683b4..219e6092d2 100644 --- a/src/Umbraco.Tests/Configurations/DashboardSettings/DashboardSettingsTests.cs +++ b/src/Umbraco.Tests/Configurations/DashboardSettings/DashboardSettingsTests.cs @@ -1,123 +1,124 @@ -using System.Configuration; +using System; +using System.Configuration; using System.IO; using System.Linq; using NUnit.Framework; -using Umbraco.Core.Configuration.Dashboard; -using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Dashboards; using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Configurations.DashboardSettings { - [TestFixture] - public class DashboardSettingsTests - { - [SetUp] - public void Init() - { - var config = new FileInfo(TestHelper.MapPathForTest("~/Configurations/DashboardSettings/web.config")); + //[Obsolete("Dashboard tests not in config/XML", true)] + //[TestFixture] + //public class DashboardSettingsTests + //{ + // [SetUp] + // public void Init() + // { + // var config = new FileInfo(TestHelper.MapPathForTest("~/Configurations/DashboardSettings/web.config")); - var fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = config.FullName }; - var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); + // var fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = config.FullName }; + // var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); - SettingsSection = configuration.GetSection("umbracoConfiguration/dashBoard") as DashboardSection; + // SettingsSection = configuration.GetSection("umbracoConfiguration/dashBoard") as DashboardSection; - Assert.IsNotNull(SettingsSection); - } + // Assert.IsNotNull(SettingsSection); + // } - protected IDashboardSection SettingsSection { get; private set; } + // protected IDashboardSection SettingsSection { get; private set; } - [Test] - public void Test_Sections() - { - Assert.AreEqual(5, SettingsSection.Sections.Count()); + // [Test] + // public void Test_Sections() + // { + // Assert.AreEqual(5, SettingsSection.Sections.Count()); - Assert.AreEqual("StartupSettingsDashboardSection", SettingsSection.Sections.ElementAt(0).Alias); - Assert.AreEqual("StartupDeveloperDashboardSection", SettingsSection.Sections.ElementAt(1).Alias); - Assert.AreEqual("StartupMediaDashboardSection", SettingsSection.Sections.ElementAt(2).Alias); - Assert.AreEqual("StartupDashboardSection", SettingsSection.Sections.ElementAt(3).Alias); - Assert.AreEqual("StartupMemberDashboardSection", SettingsSection.Sections.ElementAt(4).Alias); - } + // Assert.AreEqual("StartupSettingsDashboardSection", SettingsSection.Sections.ElementAt(0).Alias); + // Assert.AreEqual("StartupDeveloperDashboardSection", SettingsSection.Sections.ElementAt(1).Alias); + // Assert.AreEqual("StartupMediaDashboardSection", SettingsSection.Sections.ElementAt(2).Alias); + // Assert.AreEqual("StartupDashboardSection", SettingsSection.Sections.ElementAt(3).Alias); + // Assert.AreEqual("StartupMemberDashboardSection", SettingsSection.Sections.ElementAt(4).Alias); + // } - [Test] - public void Test_Section_Area() - { - Assert.AreEqual("settings", SettingsSection.Sections.ElementAt(0).Areas.First()); - Assert.AreEqual("developer", SettingsSection.Sections.ElementAt(1).Areas.First()); - Assert.AreEqual("media", SettingsSection.Sections.ElementAt(2).Areas.First()); - Assert.AreEqual("content", SettingsSection.Sections.ElementAt(3).Areas.First()); - Assert.AreEqual("default", SettingsSection.Sections.ElementAt(4).Areas.First()); - Assert.AreEqual("member", SettingsSection.Sections.ElementAt(4).Areas.Last()); - } + // [Test] + // public void Test_Section_Area() + // { + // Assert.AreEqual("settings", SettingsSection.Sections.ElementAt(0).Areas.First()); + // Assert.AreEqual("developer", SettingsSection.Sections.ElementAt(1).Areas.First()); + // Assert.AreEqual("media", SettingsSection.Sections.ElementAt(2).Areas.First()); + // Assert.AreEqual("content", SettingsSection.Sections.ElementAt(3).Areas.First()); + // Assert.AreEqual("default", SettingsSection.Sections.ElementAt(4).Areas.First()); + // Assert.AreEqual("member", SettingsSection.Sections.ElementAt(4).Areas.Last()); + // } - [Test] - public void Test_Section_Access() - { + // [Test] + // public void Test_Section_Access() + // { - Assert.AreEqual(3, SettingsSection.Sections.ElementAt(3).AccessRights.Rules.Count()); + // Assert.AreEqual(3, SettingsSection.Sections.ElementAt(3).AccessRights.Rules.Count()); - Assert.AreEqual("translator", SettingsSection.Sections.ElementAt(3).AccessRights.Rules.ElementAt(0).Value); - Assert.AreEqual(AccessRuleType.Deny, SettingsSection.Sections.ElementAt(3).AccessRights.Rules.ElementAt(0).Type); - Assert.AreEqual("hello", SettingsSection.Sections.ElementAt(3).AccessRights.Rules.ElementAt(1).Value); - Assert.AreEqual(AccessRuleType.Grant, SettingsSection.Sections.ElementAt(3).AccessRights.Rules.ElementAt(1).Type); - Assert.AreEqual("world", SettingsSection.Sections.ElementAt(3).AccessRights.Rules.ElementAt(2).Value); - Assert.AreEqual(AccessRuleType.GrantBySection, SettingsSection.Sections.ElementAt(3).AccessRights.Rules.ElementAt(2).Type); - } + // Assert.AreEqual("translator", SettingsSection.Sections.ElementAt(3).AccessRights.Rules.ElementAt(0).Value); + // Assert.AreEqual(AccessRuleType.Deny, SettingsSection.Sections.ElementAt(3).AccessRights.Rules.ElementAt(0).Type); + // Assert.AreEqual("hello", SettingsSection.Sections.ElementAt(3).AccessRights.Rules.ElementAt(1).Value); + // Assert.AreEqual(AccessRuleType.Grant, SettingsSection.Sections.ElementAt(3).AccessRights.Rules.ElementAt(1).Type); + // Assert.AreEqual("world", SettingsSection.Sections.ElementAt(3).AccessRights.Rules.ElementAt(2).Value); + // Assert.AreEqual(AccessRuleType.GrantBySection, SettingsSection.Sections.ElementAt(3).AccessRights.Rules.ElementAt(2).Type); + // } - [Test] - public void Test_Section_Tabs() - { - //Element 0 Alias "StartupSettingsDashboardSection" - Assert.AreEqual(2, SettingsSection.Sections.ElementAt(0).Tabs.Count()); + // [Test] + // public void Test_Section_Tabs() + // { + // //Element 0 Alias "StartupSettingsDashboardSection" + // Assert.AreEqual(2, SettingsSection.Sections.ElementAt(0).Tabs.Count()); - //Element 1 Alias "StartupDeveloperDashboardSection" - Assert.AreEqual(1, SettingsSection.Sections.ElementAt(1).Tabs.Count()); + // //Element 1 Alias "StartupDeveloperDashboardSection" + // Assert.AreEqual(1, SettingsSection.Sections.ElementAt(1).Tabs.Count()); - //Element 2 Alias "StartupMediaDashboardSection" - Assert.AreEqual(2, SettingsSection.Sections.ElementAt(2).Tabs.Count()); + // //Element 2 Alias "StartupMediaDashboardSection" + // Assert.AreEqual(2, SettingsSection.Sections.ElementAt(2).Tabs.Count()); - //Element 3 Alias "StartupDashboardSection" - Assert.AreEqual(3, SettingsSection.Sections.ElementAt(3).Tabs.Count()); + // //Element 3 Alias "StartupDashboardSection" + // Assert.AreEqual(3, SettingsSection.Sections.ElementAt(3).Tabs.Count()); - //Element 4 Alias "StartupMemberDashboardSection" - Assert.AreEqual(1, SettingsSection.Sections.ElementAt(4).Tabs.Count()); + // //Element 4 Alias "StartupMemberDashboardSection" + // Assert.AreEqual(1, SettingsSection.Sections.ElementAt(4).Tabs.Count()); - } + // } - [Test] - public void Test_Tab() - { - Assert.AreEqual("Get Started", SettingsSection.Sections.ElementAt(0).Tabs.ElementAt(0).Caption); - Assert.AreEqual(2, SettingsSection.Sections.ElementAt(0).Tabs.ElementAt(0).Controls.Count()); - } + // [Test] + // public void Test_Tab() + // { + // Assert.AreEqual("Get Started", SettingsSection.Sections.ElementAt(0).Tabs.ElementAt(0).Caption); + // Assert.AreEqual(2, SettingsSection.Sections.ElementAt(0).Tabs.ElementAt(0).Controls.Count()); + // } - [Test] - public void Test_Tab_Access() - { - Assert.AreEqual(1, SettingsSection.Sections.ElementAt(2).Tabs.ElementAt(1).AccessRights.Rules.Count()); - Assert.AreEqual(AccessRuleType.Grant, SettingsSection.Sections.ElementAt(2).Tabs.ElementAt(1).AccessRights.Rules.ElementAt(0).Type); - Assert.AreEqual("admin", SettingsSection.Sections.ElementAt(2).Tabs.ElementAt(1).AccessRights.Rules.ElementAt(0).Value); - } + // [Test] + // public void Test_Tab_Access() + // { + // Assert.AreEqual(1, SettingsSection.Sections.ElementAt(2).Tabs.ElementAt(1).AccessRights.Rules.Count()); + // Assert.AreEqual(AccessRuleType.Grant, SettingsSection.Sections.ElementAt(2).Tabs.ElementAt(1).AccessRights.Rules.ElementAt(0).Type); + // Assert.AreEqual("admin", SettingsSection.Sections.ElementAt(2).Tabs.ElementAt(1).AccessRights.Rules.ElementAt(0).Value); + // } - [Test] - public void Test_Control() - { - Assert.AreEqual("hello", SettingsSection.Sections.ElementAt(0).Tabs.ElementAt(0).Controls.ElementAt(0).PanelCaption); - Assert.AreEqual("views/dashboard/settings/settingsdashboardintro.html", - SettingsSection.Sections.ElementAt(0).Tabs.ElementAt(0).Controls.ElementAt(0).ControlPath); + // [Test] + // public void Test_Control() + // { + // Assert.AreEqual("hello", SettingsSection.Sections.ElementAt(0).Tabs.ElementAt(0).Controls.ElementAt(0).PanelCaption); + // Assert.AreEqual("views/dashboard/settings/settingsdashboardintro.html", + // SettingsSection.Sections.ElementAt(0).Tabs.ElementAt(0).Controls.ElementAt(0).ControlPath); - Assert.AreEqual("", SettingsSection.Sections.ElementAt(0).Tabs.ElementAt(0).Controls.ElementAt(1).PanelCaption); - Assert.AreEqual("views/dashboard/settings/settingsdashboardvideos.html", - SettingsSection.Sections.ElementAt(0).Tabs.ElementAt(0).Controls.ElementAt(1).ControlPath); - } + // Assert.AreEqual("", SettingsSection.Sections.ElementAt(0).Tabs.ElementAt(0).Controls.ElementAt(1).PanelCaption); + // Assert.AreEqual("views/dashboard/settings/settingsdashboardvideos.html", + // SettingsSection.Sections.ElementAt(0).Tabs.ElementAt(0).Controls.ElementAt(1).ControlPath); + // } - [Test] - public void Test_Control_Access() - { - Assert.AreEqual(2, SettingsSection.Sections.ElementAt(3).Tabs.ElementAt(0).Controls.ElementAt(1).AccessRights.Rules.Count()); - Assert.AreEqual(AccessRuleType.Deny, SettingsSection.Sections.ElementAt(3).Tabs.ElementAt(0).Controls.ElementAt(1).AccessRights.Rules.ElementAt(0).Type); - Assert.AreEqual("editor", SettingsSection.Sections.ElementAt(3).Tabs.ElementAt(0).Controls.ElementAt(1).AccessRights.Rules.ElementAt(0).Value); - Assert.AreEqual(AccessRuleType.Deny, SettingsSection.Sections.ElementAt(3).Tabs.ElementAt(0).Controls.ElementAt(1).AccessRights.Rules.ElementAt(1).Type); - Assert.AreEqual("writer", SettingsSection.Sections.ElementAt(3).Tabs.ElementAt(0).Controls.ElementAt(1).AccessRights.Rules.ElementAt(1).Value); - } - } + // [Test] + // public void Test_Control_Access() + // { + // Assert.AreEqual(2, SettingsSection.Sections.ElementAt(3).Tabs.ElementAt(0).Controls.ElementAt(1).AccessRights.Rules.Count()); + // Assert.AreEqual(AccessRuleType.Deny, SettingsSection.Sections.ElementAt(3).Tabs.ElementAt(0).Controls.ElementAt(1).AccessRights.Rules.ElementAt(0).Type); + // Assert.AreEqual("editor", SettingsSection.Sections.ElementAt(3).Tabs.ElementAt(0).Controls.ElementAt(1).AccessRights.Rules.ElementAt(0).Value); + // Assert.AreEqual(AccessRuleType.Deny, SettingsSection.Sections.ElementAt(3).Tabs.ElementAt(0).Controls.ElementAt(1).AccessRights.Rules.ElementAt(1).Type); + // Assert.AreEqual("writer", SettingsSection.Sections.ElementAt(3).Tabs.ElementAt(0).Controls.ElementAt(1).AccessRights.Rules.ElementAt(1).Value); + // } + //} } diff --git a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs index 4e791c0169..a12f90c4eb 100644 --- a/src/Umbraco.Tests/Manifest/ManifestParserTests.cs +++ b/src/Umbraco.Tests/Manifest/ManifestParserTests.cs @@ -7,12 +7,12 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core.Cache; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration.Dashboard; using Umbraco.Core.Logging; using Umbraco.Core.Manifest; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.Validators; using Umbraco.Core.Services; +using Umbraco.Core.Dashboards; namespace Umbraco.Tests.Manifest { diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index ed28a93caf..fe657ae470 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -937,7 +937,7 @@ }, "ansi-colors": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", "dev": true, "requires": { @@ -955,7 +955,7 @@ }, "ansi-escapes": { "version": "3.1.0", - "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", "dev": true }, @@ -1170,7 +1170,7 @@ "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", "dev": true }, "array-sort": { @@ -1216,7 +1216,7 @@ "arraybuffer.slice": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha1-O7xCdd1YTMGxCAm4nU6LY6aednU=", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", "dev": true }, "asap": { @@ -1269,7 +1269,7 @@ "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha1-ePrtjD0HSrgfIrTphdeehzj3IPg=", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", "dev": true }, "asynckit": { @@ -2379,7 +2379,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { @@ -2459,7 +2459,7 @@ "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", "dev": true }, "continuable-cache": { @@ -2502,7 +2502,7 @@ "core-js": { "version": "2.5.7", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha1-+XJgj/DOrWi4QaFqky0LGDeRgU4=", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", "dev": true }, "core-util-is": { @@ -3425,7 +3425,7 @@ "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha1-XNAfwQFiG0LEzX9dGmYkNxbT850=", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { "esutils": "^2.0.2" @@ -3953,7 +3953,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -3989,7 +3989,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -4153,7 +4153,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "optional": true } @@ -4248,7 +4248,7 @@ "eslint-scope": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha1-UL8wcekzi83EMzF5Sgy1M/ATYXI=", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", "dev": true, "requires": { "esrecurse": "^4.1.0", @@ -4258,13 +4258,13 @@ "eslint-utils": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", - "integrity": "sha1-moUbqJ7nxGA0b5fPiTnHKYgn5RI=", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", "dev": true }, "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", "dev": true }, "espree": { @@ -4287,7 +4287,7 @@ "esquery": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg=", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", "dev": true, "requires": { "estraverse": "^4.0.0" @@ -4296,7 +4296,7 @@ "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { "estraverse": "^4.1.0" @@ -4356,7 +4356,7 @@ "eventemitter3": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", - "integrity": "sha1-CQtNbNvWRe0Qv3UNS1QHlC17oWM=", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", "dev": true }, "exec-buffer": { @@ -4571,7 +4571,7 @@ "fill-range": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "integrity": "sha1-6x53OrsFbc2N8r/favWbizqTZWU=", "dev": true, "requires": { "is-number": "^2.1.0", @@ -5891,7 +5891,7 @@ "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "requires": { "global-prefix": "^1.0.1", @@ -6461,7 +6461,7 @@ "gulp-eslint": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-5.0.0.tgz", - "integrity": "sha1-KiaECV93Syz3kxAmIHjFbMehK1I=", + "integrity": "sha512-9GUqCqh85C7rP9120cpxXuZz2ayq3BZc85pCTuPJS03VQYxne0aWPIXWx6LSvsGPa3uRqtSO537vaugOh+5cXg==", "dev": true, "requires": { "eslint": "^5.0.1", @@ -7415,7 +7415,7 @@ "has-binary2": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha1-d3asYn8+p3JQz8My2rfd9eT10R0=", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", "dev": true, "requires": { "isarray": "2.0.1" @@ -7566,7 +7566,7 @@ "http-proxy": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha1-etOElGWPhGBeL220Q230EPTlvpo=", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", "dev": true, "requires": { "eventemitter3": "^3.0.0", @@ -7860,7 +7860,7 @@ "is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", "dev": true, "requires": { "is-relative": "^1.0.0", @@ -8155,7 +8155,7 @@ "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", "dev": true, "requires": { "is-unc-path": "^1.0.0" @@ -8164,7 +8164,7 @@ "is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", "dev": true }, "is-retry-allowed": { @@ -8212,7 +8212,7 @@ "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", "dev": true, "requires": { "unc-path-regex": "^0.1.2" @@ -8369,7 +8369,7 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "json-stable-stringify-without-jsonify": { @@ -8496,7 +8496,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } @@ -9146,7 +9146,7 @@ "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha1-KbM/MSqo9UfEpeSQ9Wr87JkTOtY=", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", "dev": true, "requires": { "kind-of": "^6.0.2" @@ -9327,7 +9327,7 @@ "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, "minimatch": { @@ -12855,7 +12855,7 @@ "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, "posix-character-classes": { @@ -13345,7 +13345,7 @@ "qjobs": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha1-xF6cYYAL0IfviNfiVkI73Unl0HE=", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", "dev": true }, "qs": { @@ -13541,7 +13541,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { @@ -14039,7 +14039,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, "sax": { @@ -14226,7 +14226,7 @@ "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true }, "shebang-command": { @@ -14516,7 +14516,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -14796,7 +14796,7 @@ "stream-consume": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha1-0721mMK9CugrjKx6xQsRB6eZbEg=", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", "dev": true }, "stream-shift": { @@ -14808,7 +14808,7 @@ "streamroller": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha1-odG3z4PTmvsNYwSaWsv5NJO99ks=", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", "dev": true, "requires": { "date-format": "^1.2.0", @@ -14835,7 +14835,7 @@ "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -14850,7 +14850,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -14867,7 +14867,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", @@ -15409,7 +15409,7 @@ "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { "os-tmpdir": "~1.0.2" @@ -15573,7 +15573,7 @@ "type-is": { "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha1-+JzjQVQcZysl7nrjxz3uOyvlAZQ=", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", "dev": true, "requires": { "media-typer": "0.3.0", @@ -15615,7 +15615,7 @@ "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha1-n+FTahCmZKZSZqHjzPhf02MCvJw=", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", "dev": true }, "unc-path-regex": { @@ -15777,13 +15777,13 @@ "upath": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha1-NSVll+RqWB20eT0M5H+prr/J+r0=", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", "dev": true }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "dev": true, "requires": { "punycode": "^2.1.0" @@ -16218,7 +16218,7 @@ "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha1-8c+E/i1ekB686U767OeF8YeiKPI=", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", "dev": true, "requires": { "async-limiter": "~1.0.0", diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dashboard.html b/src/Umbraco.Web.UI.Client/src/views/common/dashboard.html index 6453963670..c3b60e2f0a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dashboard.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dashboard.html @@ -17,16 +17,15 @@
- +
- +
-

{{property.caption}}

-
+
- +
- +
@@ -34,5 +33,5 @@ - + diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 0ff158dadb..c7b6540b3d 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -178,6 +178,7 @@ + @@ -205,6 +206,7 @@ + 404handlers.config diff --git a/src/Umbraco.Web.UI/config/Dashboard.config b/src/Umbraco.Web.UI/config/Dashboard.config index fec6ab34ae..94325913df 100644 --- a/src/Umbraco.Web.UI/config/Dashboard.config +++ b/src/Umbraco.Web.UI/config/Dashboard.config @@ -94,6 +94,7 @@ +
content diff --git a/src/Umbraco.Web/CompositionExtensions.cs b/src/Umbraco.Web/CompositionExtensions.cs index 246127b312..783c991ab4 100644 --- a/src/Umbraco.Web/CompositionExtensions.cs +++ b/src/Umbraco.Web/CompositionExtensions.cs @@ -10,6 +10,7 @@ using Umbraco.Web.Routing; using Umbraco.Web.ContentApps; using Umbraco.Web.Tour; using Umbraco.Web.Trees; +using Umbraco.Web.Dashboards; // the namespace here is intentional - although defined in Umbraco.Web assembly, // this class should be visible when using Umbraco.Core.Components, alongside @@ -92,6 +93,13 @@ namespace Umbraco.Core.Components public static BackOfficeSectionCollectionBuilder Sections(this Composition composition) => composition.WithCollectionBuilder(); + /// + /// Gets the backoffice dashboards collection builder. + /// + /// The composition. + public static DashboardCollectionBuilder Dashboards(this Composition composition) + => composition.WithCollectionBuilder(); + #endregion #region Uniques diff --git a/src/Umbraco.Web/Dashboards/ContentDashboard.cs b/src/Umbraco.Web/Dashboards/ContentDashboard.cs new file mode 100644 index 0000000000..c184e593aa --- /dev/null +++ b/src/Umbraco.Web/Dashboards/ContentDashboard.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Runtime.Serialization; +using Umbraco.Core.Composing; +using Umbraco.Core.Dashboards; + +namespace Umbraco.Web.Dashboards +{ + [Weight(10)] + //[HideFromTypeFinder] + [DataContract] + public class ContentDashboard : IDashboardSection + { + [DataMember(Name = "name")] + public string Name => "Get Started"; + + [DataMember(Name = "alias")] + public string Alias => "contentIntro"; + + [IgnoreDataMember] + public string[] Sections => new string[] { "content" }; + + [DataMember(Name = "view")] + public string View => "views/dashboard/default/startupdashboardintro.html"; + + [IgnoreDataMember] + public IAccessRule[] AccessRules + { + get + { + //TODO: WB Not convinced these rules work correctly?! + var rules = new List(); + rules.Add(new AccessRule { Type = AccessRuleType.Deny, Value = "translator" }); + rules.Add(new AccessRule { Type = AccessRuleType.Grant, Value = "admin" }); + return rules.ToArray(); + } + } + } +} diff --git a/src/Umbraco.Web/Dashboards/DashboardCollection.cs b/src/Umbraco.Web/Dashboards/DashboardCollection.cs new file mode 100644 index 0000000000..8d3bde622e --- /dev/null +++ b/src/Umbraco.Web/Dashboards/DashboardCollection.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using Umbraco.Core.Composing; +using Umbraco.Core.Dashboards; + +namespace Umbraco.Web.Dashboards +{ + public class DashboardCollection : BuilderCollectionBase + { + public DashboardCollection(IEnumerable items) + : base(items) + { } + } +} diff --git a/src/Umbraco.Web/Dashboards/DashboardCollectionBuilder.cs b/src/Umbraco.Web/Dashboards/DashboardCollectionBuilder.cs new file mode 100644 index 0000000000..d4a89a61b2 --- /dev/null +++ b/src/Umbraco.Web/Dashboards/DashboardCollectionBuilder.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Composing; +using Umbraco.Core.Dashboards; +using Umbraco.Core.Manifest; + +namespace Umbraco.Web.Dashboards +{ + public class DashboardCollectionBuilder : WeightedCollectionBuilderBase + { + protected override DashboardCollectionBuilder This => this; + + protected override IEnumerable CreateItems(IFactory factory) + { + // get the manifest parser just-in-time - injecting it in the ctor would mean that + // simply getting the builder in order to configure the collection, would require + // its dependencies too, and that can create cycles or other oddities + var manifestParser = factory.GetInstance(); + + //TODO WB: We will need to re-sort items from package manifest with the C# Types + return base.CreateItems(factory).Concat(manifestParser.Manifest.Dashboards); + } + } +} diff --git a/src/Umbraco.Web/Dashboards/ExamineDashboard.cs b/src/Umbraco.Web/Dashboards/ExamineDashboard.cs new file mode 100644 index 0000000000..5f04a4b78d --- /dev/null +++ b/src/Umbraco.Web/Dashboards/ExamineDashboard.cs @@ -0,0 +1,29 @@ +using System; +using System.Runtime.Serialization; +using Umbraco.Core.Composing; +using Umbraco.Core.Dashboards; + +namespace Umbraco.Web.Dashboards +{ + [Weight(20)] + [DataContract] + public class ExamineDashboard : IDashboardSection + { + [DataMember(Name = "name")] + public string Name => "Examine Management"; + + [DataMember(Name = "alias")] + public string Alias => "settingsExamine"; + + [IgnoreDataMember] + public string[] Sections => new string[] { "settings" }; + + [DataMember(Name = "view")] + public string View => "views/dashboard/settings/examinemanagement.html"; + + [IgnoreDataMember] + public IAccessRule[] AccessRules => Array.Empty(); + } + + +} diff --git a/src/Umbraco.Web/Dashboards/FormsDashboard.cs b/src/Umbraco.Web/Dashboards/FormsDashboard.cs new file mode 100644 index 0000000000..c9e8e06b7d --- /dev/null +++ b/src/Umbraco.Web/Dashboards/FormsDashboard.cs @@ -0,0 +1,27 @@ +using System; +using System.Runtime.Serialization; +using Umbraco.Core.Composing; +using Umbraco.Core.Dashboards; + +namespace Umbraco.Web.Dashboards +{ + [Weight(10)] + [DataContract] + public class FormsDashboard : IDashboardSection + { + [DataMember(Name = "name")] + public string Name => "Install Umbraco Forms"; + + [DataMember(Name = "alias")] + public string Alias => "formsInstall"; + + [IgnoreDataMember] + public string[] Sections => new string[] { "forms" }; + + [DataMember(Name = "view")] + public string View => "views/dashboard/forms/formsdashboardintro.html"; + + [IgnoreDataMember] + public IAccessRule[] AccessRules => Array.Empty(); + } +} diff --git a/src/Umbraco.Web/Dashboards/HealthCheckDashboard.cs b/src/Umbraco.Web/Dashboards/HealthCheckDashboard.cs new file mode 100644 index 0000000000..808dc099e8 --- /dev/null +++ b/src/Umbraco.Web/Dashboards/HealthCheckDashboard.cs @@ -0,0 +1,29 @@ +using System; +using System.Runtime.Serialization; +using Umbraco.Core.Composing; +using Umbraco.Core.Dashboards; + +namespace Umbraco.Web.Dashboards +{ + [Weight(50)] + [DataContract] + public class HealthCheckDashboard : IDashboardSection + { + [DataMember(Name="name")] + public string Name => "Health Check"; + + [DataMember(Name = "alias")] + public string Alias => "settingsHealthCheck"; + + [IgnoreDataMember] + public string[] Sections => new string[] { "settings" }; + + [DataMember(Name = "view")] + public string View => "views/dashboard/settings/healthcheck.html"; + + [IgnoreDataMember] + public IAccessRule[] AccessRules => Array.Empty(); + } + + +} diff --git a/src/Umbraco.Web/Dashboards/MediaDashboard.cs b/src/Umbraco.Web/Dashboards/MediaDashboard.cs new file mode 100644 index 0000000000..c122ba1f7f --- /dev/null +++ b/src/Umbraco.Web/Dashboards/MediaDashboard.cs @@ -0,0 +1,27 @@ +using System; +using System.Runtime.Serialization; +using Umbraco.Core.Composing; +using Umbraco.Core.Dashboards; + +namespace Umbraco.Web.Dashboards +{ + [Weight(10)] + [DataContract] + public class MediaDashboard : IDashboardSection + { + [DataMember(Name = "name")] + public string Name => "Content"; + + [DataMember(Name = "alias")] + public string Alias => "mediaFolderBrowser"; + + [IgnoreDataMember] + public string[] Sections => new string[] { "media" }; + + [DataMember(Name = "view")] + public string View => "views/dashboard/media/mediafolderbrowser.html"; + + [IgnoreDataMember] + public IAccessRule[] AccessRules => Array.Empty(); + } +} diff --git a/src/Umbraco.Web/Dashboards/MembersDashboard.cs b/src/Umbraco.Web/Dashboards/MembersDashboard.cs new file mode 100644 index 0000000000..9da6f59108 --- /dev/null +++ b/src/Umbraco.Web/Dashboards/MembersDashboard.cs @@ -0,0 +1,27 @@ +using System; +using System.Runtime.Serialization; +using Umbraco.Core.Composing; +using Umbraco.Core.Dashboards; + +namespace Umbraco.Web.Dashboards +{ + [Weight(10)] + [DataContract] + public class MembersDashboard : IDashboardSection + { + [DataMember(Name = "name")] + public string Name => "Get Started"; + + [DataMember(Name = "alias")] + public string Alias => "memberIntro"; + + [IgnoreDataMember] + public string[] Sections => new string[] { "member" }; + + [DataMember(Name = "view")] + public string View => "views/dashboard/members/membersdashboardvideos.html"; + + [IgnoreDataMember] + public IAccessRule[] AccessRules => Array.Empty(); + } +} diff --git a/src/Umbraco.Web/Dashboards/ModelsBuilderDashboard.cs b/src/Umbraco.Web/Dashboards/ModelsBuilderDashboard.cs new file mode 100644 index 0000000000..f25a9f7ea0 --- /dev/null +++ b/src/Umbraco.Web/Dashboards/ModelsBuilderDashboard.cs @@ -0,0 +1,29 @@ +using System; +using System.Runtime.Serialization; +using Umbraco.Core.Composing; +using Umbraco.Core.Dashboards; + +namespace Umbraco.Web.Dashboards +{ + [Weight(40)] + [DataContract] + public class ModelsBuilderDashboard : IDashboardSection + { + [DataMember(Name = "name")] + public string Name => "Models Builder"; + + [DataMember(Name = "alias")] + public string Alias => "settingsModelsBuilder"; + + [IgnoreDataMember] + public string[] Sections => new string[] { "settings" }; + + [DataMember(Name = "view")] + public string View => "/App_Plugins/ModelsBuilder/modelsbuilder.htm"; + + [IgnoreDataMember] + public IAccessRule[] AccessRules => Array.Empty(); + } + + +} diff --git a/src/Umbraco.Web/Dashboards/PublishedStatusDashboard.cs b/src/Umbraco.Web/Dashboards/PublishedStatusDashboard.cs new file mode 100644 index 0000000000..d2fa5b217b --- /dev/null +++ b/src/Umbraco.Web/Dashboards/PublishedStatusDashboard.cs @@ -0,0 +1,29 @@ +using System; +using System.Runtime.Serialization; +using Umbraco.Core.Composing; +using Umbraco.Core.Dashboards; + +namespace Umbraco.Web.Dashboards +{ + [Weight(30)] + [DataContract] + public class PublishedStatusDashboard : IDashboardSection + { + [DataMember(Name = "name")] + public string Name => "Published Status"; + + [DataMember(Name = "alias")] + public string Alias => "settingsPublishedStatus"; + + [IgnoreDataMember] + public string[] Sections => new string[] { "settings" }; + + [DataMember(Name = "view")] + public string View => "views/dashboard/settings/publishedstatus.html"; + + [IgnoreDataMember] + public IAccessRule[] AccessRules => Array.Empty(); + } + + +} diff --git a/src/Umbraco.Web/Dashboards/RedirectUrlDashboard.cs b/src/Umbraco.Web/Dashboards/RedirectUrlDashboard.cs new file mode 100644 index 0000000000..731d259d39 --- /dev/null +++ b/src/Umbraco.Web/Dashboards/RedirectUrlDashboard.cs @@ -0,0 +1,27 @@ +using System; +using System.Runtime.Serialization; +using Umbraco.Core.Composing; +using Umbraco.Core.Dashboards; + +namespace Umbraco.Web.Dashboards +{ + [Weight(20)] + [DataContract] + public class RedirectUrlDashboard : IDashboardSection + { + [DataMember(Name = "name")] + public string Name => "Redirect URL Management"; + + [DataMember(Name = "alias")] + public string Alias => "contentRedirectManager"; + + [IgnoreDataMember] + public string[] Sections => new string[] { "content" }; + + [DataMember(Name = "view")] + public string View => "views/dashboard/content/redirecturls.html"; + + [IgnoreDataMember] + public IAccessRule[] AccessRules => Array.Empty(); + } +} diff --git a/src/Umbraco.Web/Dashboards/SettingsDashboards.cs b/src/Umbraco.Web/Dashboards/SettingsDashboards.cs new file mode 100644 index 0000000000..47c1723075 --- /dev/null +++ b/src/Umbraco.Web/Dashboards/SettingsDashboards.cs @@ -0,0 +1,27 @@ +using System; +using System.Runtime.Serialization; +using Umbraco.Core.Composing; +using Umbraco.Core.Dashboards; + +namespace Umbraco.Web.Dashboards +{ + [Weight(10)] + [DataContract] + public class SettingsDashboard : IDashboardSection + { + [DataMember(Name = "name")] + public string Name => "Welcome"; + + [DataMember(Name = "alias")] + public string Alias => "settingsWelcome"; + + [IgnoreDataMember] + public string[] Sections => new string[] { "settings" }; + + [DataMember(Name = "view")] + public string View => "views/dashboard/settings/settingsdashboardintro.html"; + + [IgnoreDataMember] + public IAccessRule[] AccessRules => Array.Empty(); + } +} diff --git a/src/Umbraco.Web/Editors/DashboardController.cs b/src/Umbraco.Web/Editors/DashboardController.cs index c6e0049865..11d31a86b4 100644 --- a/src/Umbraco.Web/Editors/DashboardController.cs +++ b/src/Umbraco.Web/Editors/DashboardController.cs @@ -16,6 +16,8 @@ using Umbraco.Web.WebApi.Filters; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Services; +using Umbraco.Core.Dashboards; +using Umbraco.Web.Services; namespace Umbraco.Web.Editors { @@ -27,7 +29,7 @@ namespace Umbraco.Web.Editors [WebApi.UmbracoAuthorize] public class DashboardController : UmbracoApiController { - private readonly Dashboards _dashboards; + private readonly IDashboardService _dashboardService; /// /// Initializes a new instance of the with auto dependencies. @@ -38,10 +40,10 @@ namespace Umbraco.Web.Editors /// /// Initializes a new instance of the with all its dependencies. /// - public DashboardController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, Dashboards dashboards) + public DashboardController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, IDashboardService dashboardService) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState) { - _dashboards = dashboards; + _dashboardService = dashboardService; } //we have just one instance of HttpClient shared for the entire application @@ -79,7 +81,7 @@ namespace Umbraco.Web.Editors } catch (HttpRequestException ex) { - Logger.Error(ex.InnerException ?? ex, "Error getting dashboard content from '{Url}'", url); + Logger.Error(ex.InnerException ?? ex, "Error getting dashboard content from {Url}", url); //it's still new JObject() - we return it like this to avoid error codes which triggers UI warnings AppCaches.RuntimeCache.InsertCacheItem(key, () => result, new TimeSpan(0, 5, 0)); @@ -117,7 +119,7 @@ namespace Umbraco.Web.Editors } catch (HttpRequestException ex) { - Logger.Error(ex.InnerException ?? ex, "Error getting dashboard CSS from '{Url}'", url); + Logger.Error(ex.InnerException ?? ex, "Error getting dashboard CSS from {Url}", url); //it's still string.Empty - we return it like this to avoid error codes which triggers UI warnings AppCaches.RuntimeCache.InsertCacheItem(key, () => result, new TimeSpan(0, 5, 0)); @@ -132,9 +134,9 @@ namespace Umbraco.Web.Editors [ValidateAngularAntiForgeryToken] [OutgoingEditorModelEvent] - public IEnumerable> GetDashboard(string section) + public IEnumerable> GetDashboard(string section) { - return _dashboards.GetDashboards(section, Security.CurrentUser); + return _dashboardService.GetDashboards(section, Security.CurrentUser); } } } diff --git a/src/Umbraco.Web/Editors/Dashboards.cs b/src/Umbraco.Web/Editors/Dashboards.cs deleted file mode 100644 index c837cbbf33..0000000000 --- a/src/Umbraco.Web/Editors/Dashboards.cs +++ /dev/null @@ -1,160 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Umbraco.Core; -using Umbraco.Core.Configuration.Dashboard; -using Umbraco.Core.IO; -using Umbraco.Core.Manifest; -using Umbraco.Core.Models.Membership; -using Umbraco.Core.Services; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Services; - -namespace Umbraco.Web.Editors -{ - public class Dashboards - { - private readonly ISectionService _sectionService; - private readonly IDashboardSection _dashboardSection; - private readonly ManifestParser _manifestParser; - - public Dashboards(ISectionService sectionService, IDashboardSection dashboardSection, ManifestParser manifestParser) - { - _sectionService = sectionService ?? throw new ArgumentNullException(nameof(sectionService)); - _dashboardSection = dashboardSection; - _manifestParser = manifestParser; - } - - /// - /// Gets all dashboards, organized by section, for a user. - /// - public IDictionary>> GetDashboards(IUser currentUser) - { - return _sectionService.GetSections().ToDictionary(x => x.Alias, x => GetDashboards(x.Alias, currentUser)); - } - - /// - /// Returns dashboards for a specific section, for a user. - /// - public IEnumerable> GetDashboards(string section, IUser currentUser) - { - var tabId = 1; - var configDashboards = GetDashboardsFromConfig(ref tabId, section, currentUser); - var pluginDashboards = GetDashboardsFromPlugins(ref tabId, section, currentUser); - - // merge dashboards - // both collections contain tab.alias -> controls - var dashboards = configDashboards; - - // until now, it was fine to have duplicate tab.aliases in configDashboard - // so... the rule should be - just merge whatever we get, don't be clever - dashboards.AddRange(pluginDashboards); - - // re-sort by id - dashboards.Sort((tab1, tab2) => tab1.Id > tab2.Id ? 1 : 0); - - // re-assign ids (why?) - var i = 1; - foreach (var tab in dashboards) - { - tab.Id = i++; - tab.IsActive = tab.Id == 1; - } - - return configDashboards; - } - - // note: - // in dashboard.config we have 'sections' which define 'tabs' for 'areas' - // and 'areas' are the true UI sections - and each tab can have more than - // one control - // in a manifest, we directly have 'dashboards' which map to a unique - // control in a tab - - // gets all tabs & controls from the config file - private List> GetDashboardsFromConfig(ref int tabId, string section, IUser currentUser) - { - var tabs = new List>(); - - // disable packages section dashboard - if (section == "packages") return tabs; - - foreach (var dashboardSection in _dashboardSection.Sections.Where(x => x.Areas.InvariantContains(section))) - { - // validate access to this section - if (!DashboardSecurity.AuthorizeAccess(dashboardSection, currentUser, _sectionService)) - continue; - - foreach (var tab in dashboardSection.Tabs) - { - // validate access to this tab - if (!DashboardSecurity.AuthorizeAccess(tab, currentUser, _sectionService)) - continue; - - var dashboardControls = new List(); - - foreach (var control in tab.Controls) - { - // validate access to this control - if (!DashboardSecurity.AuthorizeAccess(control, currentUser, _sectionService)) - continue; - - // create and add control - var dashboardControl = new DashboardControl - { - Caption = control.PanelCaption, - Path = IOHelper.FindFile(control.ControlPath.Trim()) - }; - - if (dashboardControl.Path.InvariantEndsWith(".ascx")) - throw new NotSupportedException("Legacy UserControl (.ascx) dashboards are no longer supported."); - - dashboardControls.Add(dashboardControl); - } - - // create and add tab - tabs.Add(new Tab - { - Id = tabId++, - Alias = tab.Caption.ToSafeAlias(), - Label = tab.Caption, - Properties = dashboardControls - }); - } - } - - return tabs; - } - - private List> GetDashboardsFromPlugins(ref int tabId, string section, IUser currentUser) - { - var tabs = new List>(); - - foreach (var dashboard in _manifestParser.Manifest.Dashboards.Where(x => x.Sections.InvariantContains(section)).OrderBy(x => x.Weight)) - { - // validate access - if (!DashboardSecurity.CheckUserAccessByRules(currentUser, _sectionService, dashboard.AccessRules)) - continue; - - var dashboardControl = new DashboardControl - { - Caption = "", - Path = IOHelper.FindFile(dashboard.View.Trim()) - }; - - if (dashboardControl.Path.InvariantEndsWith(".ascx")) - throw new NotSupportedException("Legacy UserControl (.ascx) dashboards are no longer supported."); - - tabs.Add(new Tab - { - Id = tabId++, - Alias = dashboard.Alias.ToSafeAlias(), - Label = dashboard.Name, - Properties = new[] { dashboardControl } - }); - } - - return tabs; - } - } -} diff --git a/src/Umbraco.Web/Editors/EditorModelEventManager.cs b/src/Umbraco.Web/Editors/EditorModelEventManager.cs index 2225f5c577..dd5282d724 100644 --- a/src/Umbraco.Web/Editors/EditorModelEventManager.cs +++ b/src/Umbraco.Web/Editors/EditorModelEventManager.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Web.Http.Filters; +using Umbraco.Core.Dashboards; using Umbraco.Core.Events; using Umbraco.Web.Models.ContentEditing; @@ -14,9 +15,9 @@ namespace Umbraco.Web.Editors public static event TypedEventHandler> SendingMediaModel; public static event TypedEventHandler> SendingMemberModel; public static event TypedEventHandler> SendingUserModel; - public static event TypedEventHandler>>> SendingDashboardModel; + public static event TypedEventHandler>>> SendingDashboardModel; - private static void OnSendingDashboardModel(HttpActionExecutedContext sender, EditorModelEventArgs>> e) + private static void OnSendingDashboardModel(HttpActionExecutedContext sender, EditorModelEventArgs>> e) { var handler = SendingDashboardModel; handler?.Invoke(sender, e); @@ -65,8 +66,8 @@ namespace Umbraco.Web.Editors if (e.Model is UserDisplay) OnSendingUserModel(sender, new EditorModelEventArgs(e)); - if (e.Model is IEnumerable>) - OnSendingDashboardModel(sender, new EditorModelEventArgs>>(e)); + if (e.Model is IEnumerable) + OnSendingDashboardModel(sender, new EditorModelEventArgs>>(e)); } } } diff --git a/src/Umbraco.Web/Editors/SectionController.cs b/src/Umbraco.Web/Editors/SectionController.cs index 74a06d7149..f6973fcbb9 100644 --- a/src/Umbraco.Web/Editors/SectionController.cs +++ b/src/Umbraco.Web/Editors/SectionController.cs @@ -22,15 +22,15 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] public class SectionController : UmbracoAuthorizedJsonController { - private readonly Dashboards _dashboards; + private readonly IDashboardService _dashboardService; private readonly ISectionService _sectionService; private readonly ITreeService _treeService; public SectionController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, - Dashboards dashboards, ISectionService sectionService, ITreeService treeService) + IDashboardService dashboardService, ISectionService sectionService, ITreeService treeService) : base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState) { - _dashboards = dashboards; + _dashboardService = dashboardService; _sectionService = sectionService; _treeService = treeService; } @@ -48,7 +48,7 @@ namespace Umbraco.Web.Editors ControllerContext = ControllerContext }; - var dashboards = _dashboards.GetDashboards(Security.CurrentUser); + var dashboards = _dashboardService.GetDashboards(Security.CurrentUser); //now we can add metadata for each section so that the UI knows if there's actually anything at all to render for //a dashboard for a given section, then the UI can deal with it accordingly (i.e. redirect to the first tree) diff --git a/src/Umbraco.Web/Models/ContentEditing/DashboardControl.cs b/src/Umbraco.Web/Models/ContentEditing/DashboardControl.cs deleted file mode 100644 index aad6bf2d64..0000000000 --- a/src/Umbraco.Web/Models/ContentEditing/DashboardControl.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; -using System.Text; -using System.Threading.Tasks; - -namespace Umbraco.Web.Models.ContentEditing -{ - [DataContract(Name = "control", Namespace = "")] - public class DashboardControl - { - [DataMember(Name = "path")] - public string Path { get; set; } - - [DataMember(Name = "caption")] - public string Caption { get; set; } - } -} diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 832699b5d7..d165559024 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -6,6 +6,7 @@ using Microsoft.AspNet.SignalR; using Umbraco.Core; using Umbraco.Core.Components; using Umbraco.Core.Composing; +using Umbraco.Core.Dashboards; using Umbraco.Core.Dictionary; using Umbraco.Core.Events; using Umbraco.Core.Models.PublishedContent; @@ -17,6 +18,7 @@ using Umbraco.Web.Actions; using Umbraco.Web.Cache; using Umbraco.Web.Composing.Composers; using Umbraco.Web.ContentApps; +using Umbraco.Web.Dashboards; using Umbraco.Web.Dictionary; using Umbraco.Web.Editors; using Umbraco.Web.Features; @@ -95,14 +97,13 @@ namespace Umbraco.Web.Runtime composition.RegisterUnique(); composition.RegisterUnique(); + composition.RegisterUnique(); + composition.RegisterUnique(factory => ExamineManager.Instance); // configure the container for web composition.ConfigureForWeb(); - - - composition.RegisterUnique(); - + composition .ComposeUmbracoControllers(GetType().Assembly) .SetDefaultRenderMvcController(); // default controller for template views @@ -202,6 +203,25 @@ namespace Umbraco.Web.Runtime .Append() .Append(); + + // register core CMS dashboards as types - will be ordered by weight attribute & merged with package.manifest dashboards + // TODO WB Maybe use typeloader?! + + composition.WithCollectionBuilder() + .Add(composition.TypeLoader.GetTypes()); + + //.Add() + //.Add() + //.Add() + //.Add() + //.Add() + //.Add() + //.Add() + //.Add() + //.Add() + //.Add(); + + // register back office trees foreach (var treeControllerType in umbracoApiControllerTypes .Where(x => typeof(TreeControllerBase).IsAssignableFrom(x))) diff --git a/src/Umbraco.Web/Editors/DashboardSecurity.cs b/src/Umbraco.Web/Services/DashboardService.cs similarity index 62% rename from src/Umbraco.Web/Editors/DashboardSecurity.cs rename to src/Umbraco.Web/Services/DashboardService.cs index fdbf5af7d9..9f70f876a3 100644 --- a/src/Umbraco.Web/Editors/DashboardSecurity.cs +++ b/src/Umbraco.Web/Services/DashboardService.cs @@ -1,65 +1,63 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using Umbraco.Core; -using Umbraco.Core.Configuration.Dashboard; +using Umbraco.Core.Dashboards; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Services; -using Umbraco.Web.Services; +using Umbraco.Web.Dashboards; +using Umbraco.Web.Models.ContentEditing; -namespace Umbraco.Web.Editors +namespace Umbraco.Web.Services { - /// - /// A utility class for determine dashboard security - /// - internal class DashboardSecurity + internal class DashboardService : IDashboardService { - //TODO: Unit test all this!!! :/ + private readonly ISectionService _sectionService; + private readonly DashboardCollection _dashboardCollection; - public static bool AuthorizeAccess(ISection dashboardSection, IUser user, ISectionService sectionService) + public DashboardService(ISectionService sectionService, DashboardCollection dashboardCollection) { - return CheckUserAccessByRules(user, sectionService, dashboardSection.AccessRights.Rules); + _sectionService = sectionService ?? throw new ArgumentNullException(nameof(sectionService)); + _dashboardCollection = dashboardCollection ?? throw new ArgumentNullException(nameof(dashboardCollection)); } - public static bool AuthorizeAccess(IDashboardTab dashboardTab, IUser user, ISectionService sectionService) + + /// + public IEnumerable> GetDashboards(string section, IUser currentUser) { - return CheckUserAccessByRules(user, sectionService, dashboardTab.AccessRights.Rules); - } + var tabs = new List>(); + var tabId = 0; - public static bool AuthorizeAccess(IDashboardControl dashboardControl, IUser user, ISectionService sectionService) - { - return CheckUserAccessByRules(user, sectionService, dashboardControl.AccessRights.Rules); - } - - private static (IAccessRule[], IAccessRule[], IAccessRule[]) GroupRules(IEnumerable rules) - { - IAccessRule[] denyRules = null, grantRules = null, grantBySectionRules = null; - - var groupedRules = rules.GroupBy(x => x.Type); - foreach (var group in groupedRules) + foreach (var dashboard in _dashboardCollection.Where(x => x.Sections.InvariantContains(section))) { - var a = group.ToArray(); - switch (group.Key) + // validate access + if (!CheckUserAccessByRules(currentUser, _sectionService, dashboard.AccessRules)) + continue; + + if (dashboard.View.InvariantEndsWith(".ascx")) + throw new NotSupportedException("Legacy UserControl (.ascx) dashboards are no longer supported."); + + var dashboards = new List(); + dashboards.Add(dashboard); + + tabs.Add(new Tab() { - case AccessRuleType.Deny: - denyRules = a; - break; - case AccessRuleType.Grant: - grantRules = a; - break; - case AccessRuleType.GrantBySection: - grantBySectionRules = a; - break; - default: - throw new Exception("panic"); - } + Id = tabId++, + Label = dashboard.Name, + Alias = dashboard.Alias, + Properties = dashboards + }); } - return (denyRules ?? Array.Empty(), grantRules ?? Array.Empty(), grantBySectionRules ?? Array.Empty()); + return tabs; } - public static bool CheckUserAccessByRules(IUser user, ISectionService sectionService, IEnumerable rules) + /// + public IDictionary>> GetDashboards(IUser currentUser) + { + return _sectionService.GetSections().ToDictionary(x => x.Alias, x => GetDashboards(x.Alias, currentUser)); + } + + private bool CheckUserAccessByRules(IUser user, ISectionService sectionService, IEnumerable rules) { if (user.Id == Constants.Security.SuperUserId) return true; @@ -111,5 +109,32 @@ namespace Umbraco.Web.Editors return hasAccess; } + + private (IAccessRule[], IAccessRule[], IAccessRule[]) GroupRules(IEnumerable rules) + { + IAccessRule[] denyRules = null, grantRules = null, grantBySectionRules = null; + + var groupedRules = rules.GroupBy(x => x.Type); + foreach (var group in groupedRules) + { + var a = group.ToArray(); + switch (group.Key) + { + case AccessRuleType.Deny: + denyRules = a; + break; + case AccessRuleType.Grant: + grantRules = a; + break; + case AccessRuleType.GrantBySection: + grantBySectionRules = a; + break; + default: + throw new Exception("panic"); + } + } + + return (denyRules ?? Array.Empty(), grantRules ?? Array.Empty(), grantBySectionRules ?? Array.Empty()); + } } } diff --git a/src/Umbraco.Web/Services/IDashboardService.cs b/src/Umbraco.Web/Services/IDashboardService.cs new file mode 100644 index 0000000000..a86715c83d --- /dev/null +++ b/src/Umbraco.Web/Services/IDashboardService.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using Umbraco.Core.Dashboards; +using Umbraco.Core.Models.Membership; +using Umbraco.Web.Models.ContentEditing; + +namespace Umbraco.Web.Services +{ + public interface IDashboardService + { + /// + /// Gets dashboard for a specific section/application + /// For a specific backoffice user + /// + /// + /// + /// + IEnumerable> GetDashboards(string section, IUser currentUser); + + /// + /// Gets all dashboards, organized by section, for a user. + /// + /// + /// + IDictionary>> GetDashboards(IUser currentUser); + + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index a6f380b0dd..bd3ff8910b 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -122,6 +122,18 @@ + + + + + + + + + + + + @@ -169,6 +181,8 @@ + + @@ -244,7 +258,6 @@ - @@ -705,7 +718,6 @@ - @@ -826,7 +838,6 @@ -