diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index d21ee5ea02..0e79851c0b 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -17,7 +17,7 @@ Assume positive intent and try to understand before being understood. Treat others as you would like to be treated. -This also goes for treating the HQ with respect. For example: don’t promote products on [our.umbraco.org](https://our.umbraco.org) that directly compete with our commercial offerings which enables us to work for a sustainable Umbraco. +This also goes for treating the HQ with respect. For example: don’t promote products on [our.umbraco.com](https://our.umbraco.com) that directly compete with our commercial offerings which enables us to work for a sustainable Umbraco. ## Open diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index c257600769..6e421da5d7 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -82,7 +82,7 @@ These wonderful volunteers will provide you with a first reply to your PR, revie You can get in touch with [the PR team](#the-pr-team) in multiple ways, we love open conversations and we are a friendly bunch. No question you have is stupid. Any questions you have usually helps out multiple people with the same question. Ask away: - If there's an existing issue on the issue tracker then that's a good place to leave questions and discuss how to start or move forward -- Unsure where to start? Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.org/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely +- Unsure where to start? Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.com/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely - We're also [active in the Gitter chatroom](https://gitter.im/umbraco/Umbraco-CMS) ## Code of Conduct diff --git a/.github/CONTRIBUTING_DETAILED.md b/.github/CONTRIBUTING_DETAILED.md index 020346dc5e..a07539da6a 100644 --- a/.github/CONTRIBUTING_DETAILED.md +++ b/.github/CONTRIBUTING_DETAILED.md @@ -31,7 +31,7 @@ Before creating bug reports, please check [this list](#before-submitting-a-bug-r ##### Before Submitting A Bug Report - * Most importantly, check **if you can reproduce the problem** in the [latest version of Umbraco](https://our.umbraco.org/download/). We might have already fixed your particular problem. + * Most importantly, check **if you can reproduce the problem** in the [latest version of Umbraco](https://our.umbraco.com/download/). We might have already fixed your particular problem. * It also helps tremendously to check if the issue you're experiencing is present in **a clean install** of the Umbraco version you're currently using. Custom code can have side-effects that don't occur in a clean install. * **Use the Google**. Whatever you're experiencing, Google it plus "Umbraco" - usually you can get some pretty good hints from the search results, including open issues and further troubleshooting hints. * If you do find and existing issue has **and the issue is still open**, add a comment to the existing issue if you have additional information. If you have the same problem and no new info to add, just "star" the issue. @@ -65,13 +65,11 @@ Most of the suggestions in the [reporting bugs](#reporting-bugs) section also co Some additional hints that may be helpful: * **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of Umbraco which the suggestion is related to. - * **Explain why this enhancement would be useful to most Umbraco users** and isn't something that can or should be implemented as a [community package](https://our.umbraco.org/projects/). + * **Explain why this enhancement would be useful to most Umbraco users** and isn't something that can or should be implemented as a [community package](https://our.umbraco.com/projects/). ### Your First Code Contribution -Unsure where to begin contributing to Umbraco? You can start by looking through [these `Up for grabs` and issues](http://issues.umbraco.org/issues/U4?q=%28project%3A+%7BU4%7D+Difficulty%3A+%7BVery+Easy%7D+%23Easy+%23Unresolved+Priority%3A+Normal+%23Major+%23Show-stopper+State%3A+-%7BIn+Progress%7D+sort+by%3A+votes+Affected+versions%3A+-6.*+Affected+versions%3A+-4.*%29+OR+%28tag%3A+%7BUp+For+Grabs%7D+%23Unresolved+%29). - -The issue list is sorted by total number of upvotes. While not perfect, number of upvotes is a reasonable proxy for impact a given change will have. +Unsure where to begin contributing to Umbraco? You can start by looking through [these `Up for grabs` and issues](https://issues.umbraco.org/issues?q=&project=U4&tagValue=upforgrabs&release=&issueType=&search=search) or on the [new issue tracker](https://github.com/umbraco/Umbraco-CMS/issues?q=is%3Aopen+is%3Aissue+label%3Acommunity%2Fup-for-grabs). ### Pull Requests @@ -80,7 +78,7 @@ The most successful pull requests usually look a like this: * Fill in the required template * Include screenshots and animated GIFs in your pull request whenever possible. * Unit tests, while optional are awesome, thank you! - * New code is commented with documentation from which [the reference documentation](https://our.umbraco.org/documentation/Reference/) is generated + * New code is commented with documentation from which [the reference documentation](https://our.umbraco.com/documentation/Reference/) is generated Again, these are guidelines, not strict requirements. @@ -116,8 +114,8 @@ There's two big areas that you should know about: To find the general areas of something you're looking to fix or improve, have a look at the following two parts of the API documentation. - * [The AngularJS based backoffice files](https://our.umbraco.org/apidocs/ui/#/api) (to be found in `src\Umbraco.Web.UI.Client\src`) - * [The rest](https://our.umbraco.org/apidocs/csharp/) + * [The AngularJS based backoffice files](https://our.umbraco.com/apidocs/ui/#/api) (to be found in `src\Umbraco.Web.UI.Client\src`) + * [The rest](https://our.umbraco.com/apidocs/csharp/) ### What branch should I target for my contributions? diff --git a/LICENSE.md b/LICENSE.md index c5560c3ce1..fa83dba963 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ # The MIT License (MIT) # -Copyright (c) 2013 Umbraco +Copyright (c) 2013-present Umbraco Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/src/ApiDocs/umbracotemplate/partials/head.tmpl.partial b/src/ApiDocs/umbracotemplate/partials/head.tmpl.partial index 591e1c1885..ccc4d50229 100644 --- a/src/ApiDocs/umbracotemplate/partials/head.tmpl.partial +++ b/src/ApiDocs/umbracotemplate/partials/head.tmpl.partial @@ -8,7 +8,7 @@ {{#_description}}{{/_description}} - + diff --git a/src/ApiDocs/umbracotemplate/styles/main.css b/src/ApiDocs/umbracotemplate/styles/main.css index 7756b2f7d4..d74d51b150 100644 --- a/src/ApiDocs/umbracotemplate/styles/main.css +++ b/src/ApiDocs/umbracotemplate/styles/main.css @@ -63,7 +63,7 @@ a:focus { } .navbar-header .navbar-brand { - background: url(https://our.umbraco.org/assets/images/logo.svg) left center no-repeat; + background: url(https://our.umbraco.com/assets/images/logo.svg) left center no-repeat; background-size: 40px auto; width:50px; } diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index d7f81c1bb1..b5af335791 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -2,7 +2,7 @@ using System.Resources; [assembly: AssemblyCompany("Umbraco")] -[assembly: AssemblyCopyright("Copyright © Umbraco 2017")] +[assembly: AssemblyCopyright("Copyright © Umbraco 2018")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs index 7c274089f7..c00ab795d2 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs @@ -61,7 +61,8 @@ namespace Umbraco.Core.Configuration var config = WebConfigurationManager.OpenWebConfiguration(appPath); var settings = (MailSettingsSectionGroup)config.GetSectionGroup("system.net/mailSettings"); - if (settings == null || settings.Smtp == null) return false; + // note: "noreply@example.com" is/was the sample SMTP from email - we'll regard that as "not configured" + if (settings == null || settings.Smtp == null || "noreply@example.com".Equals(settings.Smtp.From, StringComparison.OrdinalIgnoreCase)) return false; if (settings.Smtp.SpecifiedPickupDirectory != null && string.IsNullOrEmpty(settings.Smtp.SpecifiedPickupDirectory.PickupDirectoryLocation) == false) return true; if (settings.Smtp.Network != null && string.IsNullOrEmpty(settings.Smtp.Network.Host) == false) diff --git a/src/Umbraco.Core/Configuration/UmbracoConfig.cs b/src/Umbraco.Core/Configuration/UmbracoConfig.cs index 6dd5617992..6a1203313e 100644 --- a/src/Umbraco.Core/Configuration/UmbracoConfig.cs +++ b/src/Umbraco.Core/Configuration/UmbracoConfig.cs @@ -193,4 +193,4 @@ namespace Umbraco.Core.Configuration //TODO: Add other configurations here ! } -} +} \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs index 39861ac4e9..d2236bab70 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs @@ -81,12 +81,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings [ConfigurationProperty("loginBackgroundImage")] internal InnerTextConfigurationElement LoginBackgroundImage => GetOptionalTextElement("loginBackgroundImage", string.Empty); - [ConfigurationProperty("StripUdiAttributes")] - internal InnerTextConfigurationElement StripUdiAttributes - { - get { return GetOptionalTextElement("StripUdiAttributes", true); } - } - string IContentSection.NotificationEmailAddress => Notifications.NotificationEmailAddress; @@ -142,7 +136,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings bool IContentSection.EnableInheritedMediaTypes => EnableInheritedMediaTypes; - bool IContentSection.StripUdiAttributes => StripUdiAttributes; string IContentSection.LoginBackgroundImage => LoginBackgroundImage; } diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs index ef9ffeb014..fe2eea5d91 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs @@ -66,7 +66,5 @@ namespace Umbraco.Core.Configuration.UmbracoSettings bool EnableInheritedMediaTypes { get; } string LoginBackgroundImage { get; } - bool StripUdiAttributes { get; } - } -} +} \ No newline at end of file diff --git a/src/Umbraco.Core/Constants-DataTypes.cs b/src/Umbraco.Core/Constants-DataTypes.cs index c9a33ba04d..f2b31be28f 100644 --- a/src/Umbraco.Core/Constants-DataTypes.cs +++ b/src/Umbraco.Core/Constants-DataTypes.cs @@ -13,7 +13,9 @@ public const int Textbox = -88; public const int Boolean = -49; - public const int Datetime = -36; + public const int DateTime = -36; + public const int DropDownSingle = -39; + public const int DropDownMultiple = -42; public const int DefaultContentListView = -95; public const int DefaultMediaListView = -96; diff --git a/src/Umbraco.Core/IO/SystemDirectories.cs b/src/Umbraco.Core/IO/SystemDirectories.cs index c8eedb1614..a0fa732c8c 100644 --- a/src/Umbraco.Core/IO/SystemDirectories.cs +++ b/src/Umbraco.Core/IO/SystemDirectories.cs @@ -6,10 +6,7 @@ namespace Umbraco.Core.IO //all paths has a starting but no trailing / public class SystemDirectories { - //TODO: Why on earth is this even configurable? You cannot change the /Bin folder in ASP.Net - public static string Bin => IOHelper.ReturnPath("umbracoBinDirectory", "~/bin"); - - public static string Base => IOHelper.ReturnPath("umbracoBaseDirectory", "~/base"); + public static string Bin => "~/bin"; public static string Config => IOHelper.ReturnPath("umbracoConfigDirectory", "~/config"); @@ -19,6 +16,7 @@ namespace Umbraco.Core.IO public static string Install => IOHelper.ReturnPath("umbracoInstallPath", "~/install"); + //TODO: Consider removing this public static string Masterpages => IOHelper.ReturnPath("umbracoMasterPagesPath", "~/masterpages"); //NOTE: this is not configurable and shouldn't need to be @@ -40,9 +38,7 @@ namespace Umbraco.Core.IO public static string Umbraco => IOHelper.ReturnPath("umbracoPath", "~/umbraco"); - [Obsolete("This will be removed, there is no more umbraco_client folder")] - public static string UmbracoClient => IOHelper.ReturnPath("umbracoClientPath", "~/umbraco_client"); - + //TODO: Consider removing this public static string UserControls => IOHelper.ReturnPath("umbracoUsercontrolsPath", "~/usercontrols"); public static string WebServices => IOHelper.ReturnPath("umbracoWebservicesPath", Umbraco.EnsureEndsWith("/") + "webservices"); diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs b/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs index cf00e79800..c4ebfb664b 100644 --- a/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs +++ b/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs @@ -114,15 +114,15 @@ namespace Umbraco.Core.Migrations.Install _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -51, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-51", SortOrder = 2, UniqueId = new Guid("2e6d3631-066e-44b8-aec4-96f09099b2b5"), Text = "Numeric", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -49, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-49", SortOrder = 2, UniqueId = new Guid("92897bc6-a5f3-4ffe-ae27-f2e7e33dda49"), Text = "True/false", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -43, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-43", SortOrder = 2, UniqueId = new Guid("fbaf13a8-4036-41f2-93a3-974f678c312a"), Text = "Checkbox list", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -42, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-42", SortOrder = 2, UniqueId = new Guid("0b6a45e7-44ba-430d-9da5-4e46060b9e03"), Text = "Dropdown", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); + _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DropDownMultiple, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DropDownMultiple}", SortOrder = 2, UniqueId = new Guid("0b6a45e7-44ba-430d-9da5-4e46060b9e03"), Text = "Dropdown", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -41, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-41", SortOrder = 2, UniqueId = new Guid("5046194e-4237-453c-a547-15db3a07c4e1"), Text = "Date Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -40, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-40", SortOrder = 2, UniqueId = new Guid("bb5f57c9-ce2b-4bb9-b697-4caca783a805"), Text = "Radiobox", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -39, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-39", SortOrder = 2, UniqueId = new Guid("f38f0ac7-1d27-439c-9f3f-089cd8825a53"), Text = "Dropdown multiple", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -37, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-37", SortOrder = 2, UniqueId = new Guid("0225af17-b302-49cb-9176-b9f35cab9c17"), Text = "Approved Color", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -36, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-36", SortOrder = 2, UniqueId = new Guid("e4d66c0f-b935-4200-81f0-025f7256b89a"), Text = "Date Picker with time", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultContentListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-95", SortOrder = 2, UniqueId = new Guid("C0808DD3-8133-4E4B-8CE8-E2BEA84A96A4"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultMediaListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-96", SortOrder = 2, UniqueId = new Guid("3A0156C4-3B8C-4803-BDC1-6871FAA83FFF"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Media", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); - _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultMembersListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-97", SortOrder = 2, UniqueId = new Guid("AA2C52A0-CE87-4E65-A47C-7DF09358585D"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Members", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); + _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultContentListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DefaultContentListView}", SortOrder = 2, UniqueId = new Guid("C0808DD3-8133-4E4B-8CE8-E2BEA84A96A4"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); + _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultMediaListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DefaultMediaListView}", SortOrder = 2, UniqueId = new Guid("3A0156C4-3B8C-4803-BDC1-6871FAA83FFF"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Media", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); + _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultMembersListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DefaultMembersListView}", SortOrder = 2, UniqueId = new Guid("AA2C52A0-CE87-4E65-A47C-7DF09358585D"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Members", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1031, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1031", SortOrder = 2, UniqueId = new Guid("f38bd2d7-65d0-48e6-95dc-87ce06ec2d3d"), Text = Constants.Conventions.MediaTypes.Folder, NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1032, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1032", SortOrder = 2, UniqueId = new Guid("cc07b313-0843-4aa8-bbda-871c8da728c8"), Text = Constants.Conventions.MediaTypes.Image, NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }); _database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1033, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1033", SortOrder = 2, UniqueId = new Guid("4c52d8ab-54e6-40cd-999c-7a5f24903e4d"), Text = Constants.Conventions.MediaTypes.File, NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now }); @@ -243,12 +243,12 @@ namespace Umbraco.Core.Migrations.Install private void CreateDataTypeData() { - void InsertDataTypeDto(int id, string dbType, string configuration = null) + void InsertDataTypeDto(int id, string editorAlias, string dbType, string configuration = null) { var dataTypeDto = new DataTypeDto { NodeId = id, - EditorAlias = Constants.PropertyEditors.Aliases.NoEdit, + EditorAlias = editorAlias, DbType = dbType }; @@ -271,18 +271,18 @@ namespace Umbraco.Core.Migrations.Install _database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -88, EditorAlias = Constants.PropertyEditors.Aliases.TextBox, DbType = "Nvarchar" }); _database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -89, EditorAlias = Constants.PropertyEditors.Aliases.TextArea, DbType = "Ntext" }); _database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -90, EditorAlias = Constants.PropertyEditors.Aliases.UploadField, DbType = "Nvarchar" }); - InsertDataTypeDto(Constants.DataTypes.LabelString, "Nvarchar", "{\"umbracoDataValueType\":\"STRING\"}"); - InsertDataTypeDto(Constants.DataTypes.LabelInt,"Integer", "{\"umbracoDataValueType\":\"INT\"}"); - InsertDataTypeDto(Constants.DataTypes.LabelBigint, "Nvarchar", "{\"umbracoDataValueType\":\"BIGINT\"}"); - InsertDataTypeDto(Constants.DataTypes.LabelDateTime, "Date", "{\"umbracoDataValueType\":\"DATETIME\"}"); - InsertDataTypeDto(Constants.DataTypes.LabelDecimal, "Decimal", "{\"umbracoDataValueType\":\"DECIMAL\"}"); - InsertDataTypeDto(Constants.DataTypes.LabelTime, "Date", "{\"umbracoDataValueType\":\"TIME\"}"); + InsertDataTypeDto(Constants.DataTypes.LabelString, Constants.PropertyEditors.Aliases.NoEdit, "Nvarchar", "{\"umbracoDataValueType\":\"STRING\"}"); + InsertDataTypeDto(Constants.DataTypes.LabelInt, Constants.PropertyEditors.Aliases.NoEdit, "Integer", "{\"umbracoDataValueType\":\"INT\"}"); + InsertDataTypeDto(Constants.DataTypes.LabelBigint, Constants.PropertyEditors.Aliases.NoEdit, "Nvarchar", "{\"umbracoDataValueType\":\"BIGINT\"}"); + InsertDataTypeDto(Constants.DataTypes.LabelDateTime, Constants.PropertyEditors.Aliases.NoEdit, "Date", "{\"umbracoDataValueType\":\"DATETIME\"}"); + InsertDataTypeDto(Constants.DataTypes.LabelDecimal, Constants.PropertyEditors.Aliases.NoEdit, "Decimal", "{\"umbracoDataValueType\":\"DECIMAL\"}"); + InsertDataTypeDto(Constants.DataTypes.LabelTime, Constants.PropertyEditors.Aliases.NoEdit, "Date", "{\"umbracoDataValueType\":\"TIME\"}"); _database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -36, EditorAlias = Constants.PropertyEditors.Aliases.DateTime, DbType = "Date" }); _database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -37, EditorAlias = Constants.PropertyEditors.Aliases.ColorPicker, DbType = "Nvarchar" }); - _database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -39, EditorAlias = Constants.PropertyEditors.Aliases.DropDownListMultiple, DbType = "Nvarchar" }); + InsertDataTypeDto(Constants.DataTypes.DropDownSingle, Constants.PropertyEditors.Aliases.DropDownListFlexible, "Nvarchar", "{\"multiple\":false}"); _database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -40, EditorAlias = Constants.PropertyEditors.Aliases.RadioButtonList, DbType = "Nvarchar" }); _database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -41, EditorAlias = Constants.PropertyEditors.Aliases.Date, DbType = "Date" }); - _database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -42, EditorAlias = Constants.PropertyEditors.Aliases.DropDownList, DbType = "Integer" }); + InsertDataTypeDto(Constants.DataTypes.DropDownMultiple, Constants.PropertyEditors.Aliases.DropDownListFlexible, "Nvarchar", "{\"multiple\":true}"); _database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -43, EditorAlias = Constants.PropertyEditors.Aliases.CheckBoxList, DbType = "Nvarchar" }); _database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1041, EditorAlias = Constants.PropertyEditors.Aliases.Tags, DbType = "Ntext", Configuration = "{\"group\":\"default\", \"storageType\":\"Json\"}" diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseSchemaCreator.cs b/src/Umbraco.Core/Migrations/Install/DatabaseSchemaCreator.cs index d45126f07f..28a31f23d5 100644 --- a/src/Umbraco.Core/Migrations/Install/DatabaseSchemaCreator.cs +++ b/src/Umbraco.Core/Migrations/Install/DatabaseSchemaCreator.cs @@ -334,16 +334,60 @@ namespace Umbraco.Core.Migrations.Install #region Utilities + /// + /// Returns whether a table with the specified exists in the database. + /// + /// The name of the table. + /// true if the table exists; otherwise false. + /// + /// + /// if (schemaHelper.TableExist("MyTable")) + /// { + /// // do something when the table exists + /// } + /// + /// public bool TableExists(string tableName) { return SqlSyntax.DoesTableExist(_database, tableName); } + /// + /// Returns whether the table for the specified exists in the database. + /// + /// The type representing the DTO/table. + /// true if the table exists; otherwise false. + /// + /// + /// if (schemaHelper.TableExist<MyDto>) + /// { + /// // do something when the table exists + /// } + /// + /// + /// + /// If has been decorated with an , the name from that + /// attribute will be used for the table name. If the attribute is not present, the name + /// will be used instead. + /// public bool TableExists() { var table = DefinitionFactory.GetTableDefinition(typeof(T), SqlSyntax); return table != null && TableExists(table.Name); } - // this is used in tests + /// + /// Creates a new table in the database based on the type of . + /// + /// The type representing the DTO/table. + /// Whether the table should be overwritten if it already exists. + /// + /// If has been decorated with an , the name from that + /// attribute will be used for the table name. If the attribute is not present, the name + /// will be used instead. + /// + /// If a table with the same name already exists, the parameter will determine + /// whether the table is overwritten. If true, the table will be overwritten, whereas this method will + /// not do anything if the parameter is false. + /// internal void CreateTable(bool overwrite = false) where T : new() { @@ -351,6 +395,21 @@ namespace Umbraco.Core.Migrations.Install CreateTable(overwrite, tableType, new DatabaseDataCreator(_database, _logger)); } + /// + /// Creates a new table in the database for the specified . + /// + /// Whether the table should be overwritten if it already exists. + /// The the representing the table. + /// + /// + /// If has been decorated with an , the name from + /// that attribute will be used for the table name. If the attribute is not present, the name + /// will be used instead. + /// + /// If a table with the same name already exists, the parameter will determine + /// whether the table is overwritten. If true, the table will be overwritten, whereas this method will + /// not do anything if the parameter is false. + /// public void CreateTable(bool overwrite, Type modelType, DatabaseDataCreator dataCreation) { var tableDefinition = DefinitionFactory.GetTableDefinition(modelType, SqlSyntax); @@ -364,6 +423,8 @@ namespace Umbraco.Core.Migrations.Install var tableExist = TableExists(tableName); if (overwrite && tableExist) { + _logger.Info($"Table '{tableName}' already exists, but will be recreated"); + DropTable(tableName); tableExist = false; } @@ -417,12 +478,38 @@ namespace Umbraco.Core.Migrations.Install } transaction.Complete(); + + if (overwrite) + { + _logger.Info($"Table '{tableName}' was recreated"); + } + else + { + _logger.Info($"New table '{tableName}' was created"); + } } } - - _logger.Info("Created table '{TableName}'", tableName); + else + { + // The table exists and was not recreated/overwritten. + _logger.Info($"Table '{tableName}' already exists - no changes were made"); + } } + /// + /// Drops the table for the specified . + /// + /// The type representing the DTO/table. + /// + /// + /// schemaHelper.DropTable<MyDto>); + /// + /// + /// + /// If has been decorated with an , the name from that + /// attribute will be used for the table name. If the attribute is not present, the name + /// will be used instead. + /// public void DropTable(string tableName) { var sql = new Sql(string.Format(SqlSyntax.DropTable, SqlSyntax.GetQuotedTableName(tableName))); diff --git a/src/Umbraco.Core/Models/IContentTypeBase.cs b/src/Umbraco.Core/Models/IContentTypeBase.cs index ef5988344e..a1d4aee02f 100644 --- a/src/Umbraco.Core/Models/IContentTypeBase.cs +++ b/src/Umbraco.Core/Models/IContentTypeBase.cs @@ -21,7 +21,12 @@ namespace Umbraco.Core.Models string Description { get; set; } /// - /// Gets or Sets the Icon for the ContentType + /// Gets or sets the icon for the content type. The value is a CSS class name representing + /// the icon (eg. icon-home) along with an optional CSS class name representing the + /// color (eg. icon-blue). Put together, the value for this scenario would be + /// icon-home color-blue. + /// + /// If a class name for the color isn't specified, the icon color will default to black. /// string Icon { get; set; } diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs index e611ded6c8..f1937c1c0c 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentType.cs @@ -94,10 +94,10 @@ namespace Umbraco.Core.Models.PublishedContent { "Comments", (Constants.DataTypes.Textbox, Constants.PropertyEditors.Aliases.TextBox) }, { "IsApproved", (Constants.DataTypes.Boolean, Constants.PropertyEditors.Aliases.Boolean) }, { "IsLockedOut", (Constants.DataTypes.Boolean, Constants.PropertyEditors.Aliases.Boolean) }, - { "LastLockoutDate", (Constants.DataTypes.Datetime, Constants.PropertyEditors.Aliases.DateTime) }, - { "CreateDate", (Constants.DataTypes.Datetime, Constants.PropertyEditors.Aliases.DateTime) }, - { "LastLoginDate", (Constants.DataTypes.Datetime, Constants.PropertyEditors.Aliases.DateTime) }, - { "LastPasswordChangeDate", (Constants.DataTypes.Datetime, Constants.PropertyEditors.Aliases.DateTime) }, + { "LastLockoutDate", (Constants.DataTypes.DateTime, Constants.PropertyEditors.Aliases.DateTime) }, + { "CreateDate", (Constants.DataTypes.DateTime, Constants.PropertyEditors.Aliases.DateTime) }, + { "LastLoginDate", (Constants.DataTypes.DateTime, Constants.PropertyEditors.Aliases.DateTime) }, + { "LastPasswordChangeDate", (Constants.DataTypes.DateTime, Constants.PropertyEditors.Aliases.DateTime) }, }; #region Content type diff --git a/src/Umbraco.Core/Packaging/PackageInstallation.cs b/src/Umbraco.Core/Packaging/PackageInstallation.cs index a6f1dd0f25..556c5203ec 100644 --- a/src/Umbraco.Core/Packaging/PackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageInstallation.cs @@ -576,7 +576,6 @@ namespace Umbraco.Core.Packaging { //this is experimental and undocumented... path = path.Replace("[$UMBRACO]", SystemDirectories.Umbraco); - path = path.Replace("[$UMBRACOCLIENT]", SystemDirectories.UmbracoClient); path = path.Replace("[$CONFIG]", SystemDirectories.Config); path = path.Replace("[$DATA]", SystemDirectories.Data); } diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs index adb3b8c6b3..f3afe99b28 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/DocumentRepository.cs @@ -996,7 +996,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement temp.Content.Template = template; if (temp.Template2Id.HasValue && templates.TryGetValue(temp.Template2Id.Value, out template)) temp.Content.PublishTemplate = template; + + if (properties.ContainsKey(temp.VersionId)) temp.Content.Properties = properties[temp.VersionId]; + else + throw new InvalidOperationException($"No property data found for version: '{temp.VersionId}'."); // reset dirty initial properties (U4-1946) temp.Content.ResetDirtyProperties(false); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs index e6783eaf6d..e80faaa44a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberGroupRepository.cs @@ -22,7 +22,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected override IMemberGroup PerformGet(int id) { var sql = GetBaseQuery(false); - sql.Where(GetBaseWhereClause(), new { Id = id }); + sql.Where(GetBaseWhereClause(), new { id = id }); var dto = Database.Fetch(SqlSyntax.SelectTop(sql, 1)).FirstOrDefault(); @@ -262,7 +262,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement var nonAssignedRoles = roleNames.Except(assignedRoles, StringComparer.CurrentCultureIgnoreCase); foreach (var toAssign in nonAssignedRoles) { - var groupId = rolesForNames.First(x => x.Text == toAssign).NodeId; + var groupId = rolesForNames.First(x => x.Text.InvariantEquals(toAssign)).NodeId; Database.Insert(new Member2MemberGroupDto { Member = mId, MemberGroup = groupId }); } } diff --git a/src/Umbraco.Core/Services/IApplicationTreeService.cs b/src/Umbraco.Core/Services/IApplicationTreeService.cs index 98c3047fea..691a3a0b63 100644 --- a/src/Umbraco.Core/Services/IApplicationTreeService.cs +++ b/src/Umbraco.Core/Services/IApplicationTreeService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Umbraco.Core.Models; namespace Umbraco.Core.Services @@ -41,10 +42,7 @@ namespace Umbraco.Core.Services /// /// Returns a ApplicationTree Array IEnumerable GetAll(); - - - IEnumerable GetAllTypes(); - + /// /// Gets the application tree for the applcation with the specified alias /// @@ -59,6 +57,14 @@ namespace Umbraco.Core.Services /// /// Returns a ApplicationTree Array IEnumerable GetApplicationTrees(string applicationAlias, bool onlyInitialized); + + /// + /// Gets the grouped application trees for the application with the specified alias + /// + /// + /// + /// + IDictionary> GetGroupedApplicationTrees(string applicationAlias, bool onlyInitialized); } /// @@ -117,7 +123,7 @@ namespace Umbraco.Core.Services throw new System.NotImplementedException(); } - public IEnumerable GetAllTypes() + public IDictionary> GetGroupedApplicationTrees(string applicationAlias, bool onlyInitialized) { throw new System.NotImplementedException(); } diff --git a/src/Umbraco.Core/Services/Implement/ContentService.cs b/src/Umbraco.Core/Services/Implement/ContentService.cs index ebdbe8d83e..2cd9051e72 100644 --- a/src/Umbraco.Core/Services/Implement/ContentService.cs +++ b/src/Umbraco.Core/Services/Implement/ContentService.cs @@ -1887,6 +1887,9 @@ namespace Umbraco.Core.Services.Implement Audit(AuditType.SendToPublish, content.WriterId, content.Id); } + // fixme here, on only on success? + scope.Complete(); + return saveResult.Success; } } @@ -1991,7 +1994,7 @@ namespace Umbraco.Core.Services.Implement if (raiseEvents && published.Any()) scope.Events.Dispatch(Published, this, new PublishEventArgs(published, false, false), "Published"); - Audit(AuditType.Sort, userId, 0); + Audit(AuditType.Sort, "Sorting content performed by user", userId, 0); return true; } diff --git a/src/Umbraco.Core/Services/Implement/NotificationService.cs b/src/Umbraco.Core/Services/Implement/NotificationService.cs index 3afb7c3777..cc76374715 100644 --- a/src/Umbraco.Core/Services/Implement/NotificationService.cs +++ b/src/Umbraco.Core/Services/Implement/NotificationService.cs @@ -72,7 +72,7 @@ namespace Umbraco.Core.Services.Implement // users being (dis)approved = not an issue, filtered in memory not in SQL // users being modified or created = not an issue, ordering by ID, as long as we don't *insert* low IDs // users being deleted = not an issue for GetNextUsers - var id = 0; + var id = Constants.Security.SuperUserId; var nodeIds = content.Path.Split(',').Select(int.Parse).ToArray(); const int pagesz = 400; // load batches of 400 users do diff --git a/src/Umbraco.Tests/IO/IoHelperTests.cs b/src/Umbraco.Tests/IO/IoHelperTests.cs index 07436eff1a..b2ef5e4d31 100644 --- a/src/Umbraco.Tests/IO/IoHelperTests.cs +++ b/src/Umbraco.Tests/IO/IoHelperTests.cs @@ -43,8 +43,7 @@ namespace Umbraco.Tests.IO Assert.AreEqual(IOHelper.MapPath(SystemDirectories.Preview, true), IOHelper.MapPath(SystemDirectories.Preview, false)); Assert.AreEqual(IOHelper.MapPath(SystemDirectories.Root, true), IOHelper.MapPath(SystemDirectories.Root, false)); Assert.AreEqual(IOHelper.MapPath(SystemDirectories.Scripts, true), IOHelper.MapPath(SystemDirectories.Scripts, false)); - Assert.AreEqual(IOHelper.MapPath(SystemDirectories.Umbraco, true), IOHelper.MapPath(SystemDirectories.Umbraco, false)); - Assert.AreEqual(IOHelper.MapPath(SystemDirectories.UmbracoClient, true), IOHelper.MapPath(SystemDirectories.UmbracoClient, false)); + Assert.AreEqual(IOHelper.MapPath(SystemDirectories.Umbraco, true), IOHelper.MapPath(SystemDirectories.Umbraco, false)); Assert.AreEqual(IOHelper.MapPath(SystemDirectories.UserControls, true), IOHelper.MapPath(SystemDirectories.UserControls, false)); Assert.AreEqual(IOHelper.MapPath(SystemDirectories.WebServices, true), IOHelper.MapPath(SystemDirectories.WebServices, false)); } diff --git a/src/Umbraco.Tests/Services/MemberServiceTests.cs b/src/Umbraco.Tests/Services/MemberServiceTests.cs index 968b27a4f9..078336262f 100644 --- a/src/Umbraco.Tests/Services/MemberServiceTests.cs +++ b/src/Umbraco.Tests/Services/MemberServiceTests.cs @@ -292,6 +292,29 @@ namespace Umbraco.Tests.Services Assert.AreEqual(2, membersInRole.Count()); } + [Test] + public void Associate_Members_To_Roles_With_Member_Id_Casing() + { + ServiceContext.MemberService.AddRole("MyTestRole1"); + + IMemberType memberType = MockedContentTypes.CreateSimpleMemberType(); + ServiceContext.MemberTypeService.Save(memberType); + var member1 = MockedMember.CreateSimpleMember(memberType, "test1", "test1@test.com", "pass", "test1"); + ServiceContext.MemberService.Save(member1); + var member2 = MockedMember.CreateSimpleMember(memberType, "test2", "test2@test.com", "pass", "test2"); + ServiceContext.MemberService.Save(member2); + + // temp make sure they exist + Assert.IsNotNull(ServiceContext.MemberService.GetById(member1.Id)); + Assert.IsNotNull(ServiceContext.MemberService.GetById(member2.Id)); + + ServiceContext.MemberService.AssignRoles(new[] { member1.Id, member2.Id }, new[] { "mytestrole1" }); + + var membersInRole = ServiceContext.MemberService.GetMembersInRole("MyTestRole1"); + + Assert.AreEqual(2, membersInRole.Count()); + } + [Test] public void Associate_Members_To_Roles_With_Member_Username() { diff --git a/src/Umbraco.Tests/UI/LegacyDialogTests.cs b/src/Umbraco.Tests/UI/LegacyDialogTests.cs index ba7c4f0e66..99391104ab 100644 --- a/src/Umbraco.Tests/UI/LegacyDialogTests.cs +++ b/src/Umbraco.Tests/UI/LegacyDialogTests.cs @@ -23,8 +23,6 @@ namespace Umbraco.Tests.UI } } - [TestCase(typeof(MemberGroupTasks), Constants.Applications.Members)] - [TestCase(typeof(dictionaryTasks), Constants.Applications.Settings)] [TestCase(typeof(macroTasks), Constants.Applications.Packages)] [TestCase(typeof(CreatedPackageTasks), Constants.Applications.Packages)] public void Check_Assigned_Apps_For_Tasks(Type taskType, string app) diff --git a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs index f05e9525c2..defdec5660 100644 --- a/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs +++ b/src/Umbraco.Tests/Web/TemplateUtilitiesTests.cs @@ -1,8 +1,8 @@ using System; using System.Globalization; +using System.Linq; using System.Web; using LightInject; -using HtmlAgilityPack; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -12,6 +12,7 @@ using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Tests.Testing.Objects.Accessors; @@ -66,14 +67,6 @@ namespace Umbraco.Tests.Web [TestCase("hello href=\"{localLink:umb://document-type/9931BDE0AAC34BABB838909A7B47570E}\" world ", "hello href=\"/my-test-url\" world ")] //this one has an invalid char so won't match [TestCase("hello href=\"{localLink:umb^://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"{localLink:umb^://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ")] - // with a-tag with data-udi attribute, that needs to be stripped - [TestCase("hello world ", "hello world ")] - // with a-tag with data-udi attribute spelled wrong, so don't need stripping - [TestCase("hello world ", "hello world ")] - // with a img-tag with data-udi id, that needs to be strippde - [TestCase("hello world ", "hello world ")] - // with a img-tag with data-udi id spelled wrong, so don't need stripping - [TestCase("hello world ", "hello world ")] public void ParseLocalLinks(string input, string result) { var serviceCtxMock = new TestObjects(null).GetServiceContextMock(); @@ -114,7 +107,7 @@ namespace Umbraco.Tests.Web //setup a quick mock of the WebRouting section Mock.Of(section => section.WebRouting == Mock.Of(routingSection => routingSection.UrlProviderMode == "AutoLegacy")), //pass in the custom url provider - new[] { testUrlProvider.Object }, + new[]{ testUrlProvider.Object }, globalSettings, new TestVariationContextAccessor(), true)) @@ -124,27 +117,5 @@ namespace Umbraco.Tests.Web Assert.AreEqual(result, output); } } - - [Test] - public void StripDataUdiAttributesUsingSrtringOnLinks() - { - var input = "hello world "; - var expected = "hello world "; - - var result = TemplateUtilities.StripUdiDataAttributes(input); - - Assert.AreEqual(expected, result); - } - - [Test] - public void StripDataUdiAttributesUsingStringOnImages() - { - var input = "hello world "; - var expected = "hello world "; - - var result = TemplateUtilities.StripUdiDataAttributes(input); - - Assert.AreEqual(expected, result); - } } -} +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js b/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js index 5fad4b944e..bd7cf964d0 100644 --- a/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js +++ b/src/Umbraco.Web.UI.Client/lib/umbraco/LegacyUmbClientMgr.js @@ -146,7 +146,8 @@ Umbraco.Sys.registerNamespace("Umbraco.Application"); sourceUrl: currentMenuNode.childNodesUrl, updateDefinition: function() { throw "'updateDefinition' method is not supported in Umbraco 7, consider upgrading to the new v7 APIs"; - } + }, + expanded: currentMenuNode.expanded === true }; //defined getters that will throw a not implemented/supported exception Object.defineProperty(legacyNode, "menu", { diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index deda717214..9233b24d53 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -1266,7 +1266,7 @@ "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "integrity": "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=", "dev": true }, "array-union": { @@ -1440,7 +1440,7 @@ "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", "dev": true, "requires": { "cache-base": "^1.0.1", @@ -1464,7 +1464,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -1473,7 +1473,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -1482,7 +1482,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -1680,7 +1680,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -1696,7 +1696,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -1822,7 +1822,7 @@ "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "integrity": "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=", "dev": true, "requires": { "arr-flatten": "^1.1.0", @@ -2014,7 +2014,7 @@ "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", "dev": true, "requires": { "collection-visit": "^1.0.0", @@ -2225,7 +2225,7 @@ "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", "dev": true, "requires": { "arr-union": "^3.1.0", @@ -2717,7 +2717,7 @@ "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=", "dev": true }, "convert-source-map": { @@ -3228,7 +3228,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -3244,7 +3244,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -3549,7 +3549,7 @@ "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", "dev": true, "requires": { "is-descriptor": "^1.0.2", @@ -3559,7 +3559,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -3568,7 +3568,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -3577,7 +3577,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -3942,7 +3942,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -3958,7 +3958,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -4051,7 +4051,7 @@ "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", "dev": true, "requires": { "once": "^1.4.0" @@ -4065,7 +4065,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -4081,7 +4081,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -4263,7 +4263,7 @@ "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=", "dev": true, "optional": true, "requires": { @@ -4972,7 +4972,7 @@ "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", "dev": true, "requires": { "array-unique": "^0.3.2", @@ -5006,7 +5006,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -5015,7 +5015,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -5024,7 +5024,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -5356,9 +5356,9 @@ } }, "font-awesome": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.2.0.tgz", - "integrity": "sha1-RzOKGgF9pr75XOLhsOF2go/Yreo=" + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", + "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=" }, "for-in": { "version": "1.0.2", @@ -6289,7 +6289,7 @@ "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", "dev": true, "requires": { "global-prefix": "^1.0.1", @@ -6439,7 +6439,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -6617,7 +6617,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -6633,7 +6633,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -6950,7 +6950,7 @@ }, "lodash": { "version": "2.4.1", - "resolved": "http://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz", "integrity": "sha1-W3cjA03aTSYuWkb7LFjXzCL3FCA=", "dev": true }, @@ -8044,7 +8044,7 @@ "is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=", "dev": true, "requires": { "is-relative": "^1.0.0", @@ -8148,7 +8148,7 @@ "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", @@ -8159,7 +8159,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=", "dev": true } } @@ -8382,7 +8382,7 @@ "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=", "dev": true, "requires": { "is-unc-path": "^1.0.0" @@ -8439,7 +8439,7 @@ "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=", "dev": true, "requires": { "unc-path-regex": "^0.1.2" @@ -8466,7 +8466,7 @@ "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=", "dev": true }, "is-zip": { @@ -8975,7 +8975,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -8991,7 +8991,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -9084,7 +9084,7 @@ "livereload-js": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.3.0.tgz", - "integrity": "sha512-j1R0/FeGa64Y+NmqfZhyoVRzcFlOZ8sNlKzHjh4VvLULFACZhn68XrX5DFg2FhMvSMJmROuFxRSa560ECWKBMg==", + "integrity": "sha1-w6si6Kr1vzUF2A0JjLrWdyZUjJo=", "dev": true }, "load-json-file": { @@ -9322,7 +9322,7 @@ "lodash.merge": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", - "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==", + "integrity": "sha1-rcJdnLmbk5HFliTzefu6YNcRHVQ=", "dev": true }, "lodash.partialright": { @@ -9741,7 +9741,7 @@ "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "integrity": "sha1-KbM/MSqo9UfEpeSQ9Wr87JkTOtY=", "dev": true, "requires": { "kind-of": "^6.0.2" @@ -9900,7 +9900,7 @@ "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -9963,7 +9963,7 @@ "mixin-deep": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", "dev": true, "requires": { "for-in": "^1.0.2", @@ -9973,7 +9973,7 @@ "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { "is-plain-object": "^2.0.4" @@ -14099,7 +14099,7 @@ "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", "dev": true, "optional": true, "requires": { @@ -14312,7 +14312,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -14328,7 +14328,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -14535,7 +14535,7 @@ "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", "dev": true, "requires": { "extend-shallow": "^3.0.2", @@ -14771,7 +14771,7 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=", "dev": true }, "right-align": { @@ -15079,7 +15079,7 @@ "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -15184,7 +15184,7 @@ "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", "dev": true, "requires": { "base": "^0.11.1", @@ -15220,7 +15220,7 @@ "snapdragon-node": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", "dev": true, "requires": { "define-property": "^1.0.0", @@ -15240,7 +15240,7 @@ "is-accessor-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -15249,7 +15249,7 @@ "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -15258,7 +15258,7 @@ "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -15271,7 +15271,7 @@ "snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", "dev": true, "requires": { "kind-of": "^3.2.0" @@ -15470,7 +15470,7 @@ "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", "dev": true, "requires": { "extend-shallow": "^3.0.0" @@ -15596,7 +15596,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -15612,7 +15612,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -15977,7 +15977,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -16294,7 +16294,7 @@ "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", "dev": true, "requires": { "define-property": "^2.0.2", @@ -16394,7 +16394,7 @@ "type-is": { "version": "1.6.16", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "integrity": "sha1-+JzjQVQcZysl7nrjxz3uOyvlAZQ=", "dev": true, "requires": { "media-typer": "0.3.0", @@ -16742,7 +16742,7 @@ "vendors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz", - "integrity": "sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ==", + "integrity": "sha1-f8te759WI7FWvOqJ7DfWNnbyGAE=", "dev": true }, "verror": { @@ -16799,7 +16799,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -16815,7 +16815,7 @@ "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -17016,7 +17016,7 @@ "websocket-extensions": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "integrity": "sha1-XS/yKXcAPsaHpLhwc9+7rBRszyk=", "dev": true }, "when": { diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index e5948367da..69c046624f 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -24,7 +24,7 @@ "codemirror": "5.3.0", "diff": "3.4.0", "flatpickr": "4.5.2", - "font-awesome": "4.2.0", + "font-awesome": "4.7.0", "jquery": "2.2.4", "jquery-migrate": "1.4.0", "jquery-ui-dist": "1.12.1", diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstep.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstep.directive.js index 08e0a44c0b..2dc0ebdf93 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstep.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstep.directive.js @@ -1,4 +1,17 @@ -(function() { +/** +@ngdoc directive +@name umbraco.directives.directive:umbTourStep +@restrict E +@scope + +@description +Added in Umbraco 7.8. The tour step component is a component that can be used in custom views for tour steps. + +@param {callback} onClose The callback which should be performened when the close button of the tour step is clicked +@param {boolean=} hideClose A boolean indicating if the close button needs to be shown + +**/ +(function () { 'use strict'; function TourStepDirective() { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepcontent.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepcontent.directive.js index 52ed358b61..909f87eac5 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepcontent.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepcontent.directive.js @@ -1,4 +1,17 @@ -(function() { +/** +@ngdoc directive +@name umbraco.directives.directive:umbTourStepContent +@restrict E +@scope + +@description +Added in Umbraco 7.8. The tour step content component is a component that can be used in custom views for tour steps. +It's meant to be used in the umb-tour-step directive. +All markup in the body of the directive will be shown after the content attribute + +@param {string} content The content that needs to be shown +**/ +(function () { 'use strict'; function TourStepContentDirective() { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepcounter.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepcounter.directive.js index 7e04ef5d00..2477953580 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepcounter.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepcounter.directive.js @@ -1,4 +1,18 @@ -(function() { +/** +@ngdoc directive +@name umbraco.directives.directive:umbTourStepCounter +@restrict E +@scope + +@description +Added in Umbraco 7.8. The tour step counter component is a component that can be used in custom views for tour steps. +It's meant to be used in the umb-tour-step-footer directive. It will show the progress you have made in a tour eg. step 2/12 + + +@param {int} currentStep The current step the tour is on +@param {int} totalSteps The current step the tour is on +**/ +(function () { 'use strict'; function TourStepCounterDirective() { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepfooter.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepfooter.directive.js index fedb527972..7cfb498394 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepfooter.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepfooter.directive.js @@ -1,4 +1,16 @@ -(function() { +/** +@ngdoc directive +@name umbraco.directives.directive:umbTourStepFooter +@restrict E +@scope + +@description +Added in Umbraco 7.8. The tour step footer component is a component that can be used in custom views for tour steps. It's meant to be used in the umb-tour-step directive. +All markup in the body of the directive will be shown as the footer of the tour step + + +**/ +(function () { 'use strict'; function TourStepFooterDirective() { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepheader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepheader.directive.js index 9d32ad87a4..ec6768928f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepheader.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstepheader.directive.js @@ -1,4 +1,16 @@ -(function() { +/** +@ngdoc directive +@name umbraco.directives.directive:umbTourStepHeader +@restrict E +@scope + +@description +Added in Umbraco 7.8. The tour step header component is a component that can be used in custom views for tour steps. It's meant to be used in the umb-tour-step directive. + + +@param {string} title The title that needs to be shown +**/ +(function () { 'use strict'; function TourStepHeaderDirective() { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index 6670a41ac4..cd04f0bb52 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -46,7 +46,7 @@ $scope.ancestors = anc; }); $scope.$watch('culture', - function(value, oldValue) { + function (value, oldValue) { entityResource.getAncestors(content.id, "document", value) .then(function (anc) { $scope.ancestors = anc; @@ -157,7 +157,7 @@ // only create the save/publish/preview buttons if the // content app is "Conent" - if(app && app.alias !== "umbContent" && app.alias !== "umbInfo") { + if (app && app.alias !== "umbContent" && app.alias !== "umbInfo") { $scope.defaultButton = null; $scope.subButtons = null; $scope.page.showSaveButton = false; @@ -166,7 +166,7 @@ } // create the save button - if(_.contains($scope.content.allowedActions, "A")) { + if (_.contains($scope.content.allowedActions, "A")) { $scope.page.showSaveButton = true; // add ellipsis to the save button if it opens the variant overlay $scope.page.saveButtonEllipsis = content.variants && content.variants.length > 1 ? "true" : "false"; @@ -236,7 +236,7 @@ } } - function checkValidility(){ + function checkValidility() { //Get all controls from the 'contentForm' var allControls = $scope.contentForm.$getControls(); @@ -245,7 +245,7 @@ //Exclude known formControls 'contentHeaderForm' and 'tabbedContentForm' //Check property - $name === "contentHeaderForm" - allControls = _.filter(allControls, function(obj){ + allControls = _.filter(allControls, function (obj) { return obj.$name !== 'contentHeaderForm' && obj.$name !== 'tabbedContentForm' && obj.hasOwnProperty('$submitted'); }); @@ -263,26 +263,26 @@ } //Controls is the - function recurseFormControls(controls, array){ + function recurseFormControls(controls, array) { //Loop over the controls for (var i = 0; i < controls.length; i++) { var controlItem = controls[i]; //Check if the controlItem has a property '' - if(controlItem.hasOwnProperty('$submitted')){ + if (controlItem.hasOwnProperty('$submitted')) { //This item is a form - so lets get the child controls of it & recurse again var childFormControls = controlItem.$getControls(); recurseFormControls(childFormControls, array); } else { //We can assume its a field on a form - if(controlItem.hasOwnProperty('$error')){ + if (controlItem.hasOwnProperty('$error')) { //Set the validlity of the error/s to be valid //String of keys of error invalid messages var errorKeys = []; - for(var key in controlItem.$error){ + for (var key in controlItem.$error) { errorKeys.push(key); controlItem.$setValidity(key, true); } @@ -298,7 +298,7 @@ return array; } - function resetNestedFieldValiation(array){ + function resetNestedFieldValiation(array) { for (var i = 0; i < array.length; i++) { var item = array[i]; //Item is an object containing two props @@ -306,7 +306,7 @@ var fieldControl = item.control; var fieldErrorKeys = item.errorKeys; - for(var i = 0; i < fieldErrorKeys.length; i++) { + for (var i = 0; i < fieldErrorKeys.length; i++) { fieldControl.$setValidity(fieldErrorKeys[i], false); } } @@ -314,7 +314,7 @@ // This is a helper method to reduce the amount of code repitition for actions: Save, Publish, SendToPublish function performSave(args) { - + //Used to check validility of nested form - coming from Content Apps mostly //Set them all to be invalid @@ -421,7 +421,7 @@ }); } - $scope.unpublish = function() { + $scope.unpublish = function () { clearNotifications($scope.content); if (formHelper.submitForm({ scope: $scope, action: "unpublish", skipValidation: true })) { var dialog = { @@ -433,9 +433,9 @@ submit: function (model) { model.submitButtonState = "busy"; - - var selectedVariants = _.filter(model.variants, function(variant) { return variant.save; }); - var culturesForUnpublishing = _.map(selectedVariants, function(variant) { return variant.language.culture; }); + + var selectedVariants = _.filter(model.variants, function (variant) { return variant.save; }); + var culturesForUnpublishing = _.map(selectedVariants, function (variant) { return variant.language.culture; }); contentResource.unpublish($scope.content.id, culturesForUnpublishing) .then(function (data) { @@ -449,8 +449,8 @@ }, function (err) { $scope.page.buttonGroupState = 'error'; }); - - + + }, close: function () { overlayService.close(); @@ -459,7 +459,7 @@ overlayService.open(dialog); } }; - + $scope.sendToPublish = function () { clearNotifications($scope.content); if (showSaveOrPublishDialog()) { @@ -476,7 +476,24 @@ model.submitButtonState = "busy"; clearNotifications($scope.content); //we need to return this promise so that the dialog can handle the result and wire up the validation response - console.log("saving need to happen here"); + return performSave({ + saveMethod: contentResource.sendToPublish, + action: "sendToPublish", + showNotifications: false + }).then(function (data) { + //show all notifications manually here since we disabled showing them automatically in the save method + formHelper.showNotifications(data); + clearNotifications($scope.content); + overlayService.close(); + return $q.when(data); + }, function (err) { + clearDirtyState($scope.content.variants); + model.submitButtonState = "error"; + //re-map the dialog model since we've re-bound the properties + dialog.variants = $scope.content.variants; + //don't reject, we've handled the error + return $q.when(err); + }); }, close: function () { overlayService.close(); @@ -488,10 +505,10 @@ } else { $scope.page.buttonGroupState = "busy"; - return performSave({ - saveMethod: contentResource.sendToPublish, - action: "sendToPublish" - }).then(function(){ + return performSave({ + saveMethod: contentResource.sendToPublish, + action: "sendToPublish" + }).then(function () { $scope.page.buttonGroupState = "success"; }, function () { $scope.page.buttonGroupState = "error"; @@ -547,10 +564,10 @@ //ensure the publish flag is set $scope.content.variants[0].publish = true; $scope.page.buttonGroupState = "busy"; - return performSave({ - saveMethod: contentResource.publish, - action: "publish" - }).then(function(){ + return performSave({ + saveMethod: contentResource.publish, + action: "publish" + }).then(function () { $scope.page.buttonGroupState = "success"; }, function () { $scope.page.buttonGroupState = "error"; @@ -605,13 +622,13 @@ else { $scope.page.saveButtonState = "busy"; return performSave({ - saveMethod: $scope.saveMethod(), - action: "save" - }).then(function(){ - $scope.page.saveButtonState = "success"; - }, function () { - $scope.page.saveButtonState = "error"; - }); + saveMethod: $scope.saveMethod(), + action: "save" + }).then(function () { + $scope.page.saveButtonState = "success"; + }, function () { + $scope.page.saveButtonState = "error"; + }); } }; @@ -781,7 +798,7 @@ * Call back when a content app changes * @param {any} app */ - $scope.appChanged = function(app) { + $scope.appChanged = function (app) { createButtons($scope.content, app); }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js index 015255c577..651edf5bfd 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js @@ -22,14 +22,6 @@ }, link: function(scope) { - function onInit() { - angular.forEach(scope.content.tabs, function (group) { - group.open = true; - }); - } - - onInit(); - }, scope: { content: "=" diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagegravity.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagegravity.directive.js index d56a4d2439..a70b8ca33e 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagegravity.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/imaging/umbimagegravity.directive.js @@ -97,10 +97,32 @@ //listen for the image DOM element loading htmlImage.on("load", function () { $timeout(function () { + + vm.isCroppable = true; + vm.hasDimensions = true; + + if (vm.src) { + if (vm.src.endsWith(".svg")) { + vm.isCroppable = false; + vm.hasDimensions = false; + } + else { + // From: https://stackoverflow.com/a/51789597/5018 + var type = vm.src.substring(vm.src.indexOf("/") + 1, vm.src.indexOf(";base64")); + if (type.startsWith("svg")) { + vm.isCroppable = false; + vm.hasDimensions = false; + } + } + } + setDimensions(); vm.loaded = true; if (vm.onImageLoaded) { - vm.onImageLoaded(); + vm.onImageLoaded({ + "isCroppable": vm.isCroppable, + "hasDimensions": vm.hasDimensions + }); } }, 100); }); @@ -147,19 +169,7 @@ /** Sets the width/height/left/top dimentions based on the image size and the "center" value */ function setDimensions() { - if (vm.src.endsWith(".svg")) { - // svg files don't automatically get a size by - // loading them set a default size for now - vm.dimensions.width = 200; - vm.dimensions.height = 200; - vm.dimensions.left = vm.center.left * vm.dimensions.width - 10; - vm.dimensions.top = vm.center.top * vm.dimensions.height - 10; - // can't crop an svg file, don't show the focal point - if (htmlOverlay) { - htmlOverlay.remove(); - } - } - else if (htmlImage && vm.center) { + if (vm.isCroppable && htmlImage && vm.center) { vm.dimensions.width = htmlImage.width(); vm.dimensions.height = htmlImage.height(); vm.dimensions.left = vm.center.left * vm.dimensions.width - 10; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbGenerateAlias.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbGenerateAlias.directive.js index 4bc6f08eb9..47d1431e13 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbGenerateAlias.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbGenerateAlias.directive.js @@ -48,7 +48,7 @@ the directive will use {@link umbraco.directives.directive:umbLockedField umbLoc **/ angular.module("umbraco.directives") - .directive('umbGenerateAlias', function ($timeout, entityResource) { + .directive('umbGenerateAlias', function ($timeout, entityResource, localizationService) { return { restrict: 'E', templateUrl: 'views/components/umb-generate-alias.html', @@ -67,7 +67,21 @@ angular.module("umbraco.directives") var updateAlias = false; scope.locked = true; - scope.placeholderText = "Enter alias..."; + + scope.labels = { + idle: "Enter alias...", + busy: "Generating alias..." + }; + + scope.placeholderText = scope.labels.idle; + + localizationService.localize('placeholders_enterAlias').then(function (value) { + scope.labels.idle = scope.placeholderText = value; + }); + + localizationService.localize('placeholders_generatingAlias').then(function (value) { + scope.labels.busy = value; + }); function generateAlias(value) { @@ -78,7 +92,7 @@ angular.module("umbraco.directives") if( value !== undefined && value !== "" && value !== null) { scope.alias = ""; - scope.placeholderText = "Generating Alias..."; + scope.placeholderText = scope.labels.busy; generateAliasTimeout = $timeout(function () { updateAlias = true; @@ -92,7 +106,7 @@ angular.module("umbraco.directives") } else { updateAlias = true; scope.alias = ""; - scope.placeholderText = "Enter alias..."; + scope.placeholderText = scope.labels.idle; } } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js index b14f8418c5..308ffbf00f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js @@ -125,13 +125,19 @@ Use this directive to generate a thumbnail grid of media items. i--; } - if (scope.includeSubFolders !== 'true') { - if (item.parentId !== parseInt(scope.currentFolderId)) { - scope.items.splice(i, 1); - i--; + + // If subfolder search is not enabled remove the media items that's not needed + // Make sure that includeSubFolder is not undefined since the directive is used + // in contexts where it should not be used. Currently only used when we trigger + // a media picker + if(scope.includeSubFolders !== undefined){ + if (scope.includeSubFolders !== 'true') { + if (item.parentId !== parseInt(scope.currentFolderId)) { + scope.items.splice(i, 1); + i--; + } } } - } @@ -152,7 +158,7 @@ Use this directive to generate a thumbnail grid of media items. } if (!item.isFolder) { - + // handle entity if(item.image) { item.thumbnail = mediaHelper.resolveFileFromEntity(item, true); @@ -161,7 +167,7 @@ Use this directive to generate a thumbnail grid of media items. } else { item.thumbnail = mediaHelper.resolveFile(item, true); item.image = mediaHelper.resolveFile(item, false); - + var fileProp = _.find(item.properties, function (v) { return (v.alias === "umbracoFile"); }); diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js index 28aae834b3..8b1faab448 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/services/localization.mocks.js @@ -36,7 +36,6 @@ angular.module('umbraco.mocks'). "actions_sendtopublish": "Send To Publish", "actions_sendToTranslate": "Send To Translation", "actions_sort": "Sort", - "actions_toPublish": "Send to publication", "actions_translate": "Translate", "actions_update": "Update", "actions_exportContourForm": "Export form", diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js index 71cbe3b8d7..64c2b127e9 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js @@ -756,11 +756,11 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { * @returns {Promise} resourcePromise object containing the saved content item. * */ - sendToPublish: function (content, isNew, files) { + sendToPublish: function (content, isNew, files, showNotifications) { var endpoint = umbRequestHelper.getApiUrl( "contentApiBaseUrl", "PostSave"); - return saveContentItem(content, "sendPublish" + (isNew ? "New" : ""), files, endpoint); + return saveContentItem(content, "sendPublish" + (isNew ? "New" : ""), files, endpoint, showNotifications); }, /** diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js index 5d2ac1e8b9..9cf96f8e7a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js @@ -109,11 +109,23 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) { return umbRequestHelper.resourcePromise( $http.post(umbRequestHelper.getApiUrl("mediaApiBaseUrl", "PostMove"), - { - parentId: args.parentId, - id: args.id + { + parentId: args.parentId, + id: args.id }, {responseType: 'text'}), - 'Failed to move media'); + { + error: function(data){ + var errorMsg = 'Failed to move media'; + + if(data.parentId === data.id){ + errorMsg = 'Media can\'t be moved into itself'; + } + + return { + errorMsg: errorMsg + }; + } + }); }, 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 cb416e3974..15c738638b 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 @@ -646,10 +646,10 @@ function navigationService($rootScope, $route, $routeParams, $log, $location, $q */ hideDialog: function (showMenu) { - setMode("default"); - - if(showMenu){ + if (showMenu) { this.showMenu({ skipDefault: true, node: appState.getMenuState("currentNode") }); + } else { + setMode("default"); } }, /** diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js index 1619ca0623..1f99659389 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js @@ -126,12 +126,21 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ /** The default error callback used if one is not supplied in the opts */ function defaultError(data, status, headers, config) { - return { + + var err = { //NOTE: the default error message here should never be used based on the above docs! errorMsg: (angular.isString(opts) ? opts : 'An error occurred!'), data: data, status: status }; + + // if "opts" is a promise, we set "err.errorMsg" to be that promise + if (typeof(opts) == "object" && typeof(opts.then) == "function") { + err.errorMsg = opts; + } + + return err; + } //create the callbacs based on whats been passed in. diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index ac8279e3ab..3100433a4a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -66,6 +66,7 @@ // Belle styles @import "buttons.less"; @import "forms.less"; +@import "legacydialog.less"; @import "modals.less"; @import "panel.less"; @import "sections.less"; @@ -159,6 +160,7 @@ @import "components/umb-mini-editor.less"; @import "components/users/umb-user-cards.less"; +@import "components/users/umb-user-details.less"; @import "components/users/umb-user-group-picker-list.less"; @import "components/users/umb-user-group-preview.less"; @import "components/users/umb-user-preview.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/buttons.less b/src/Umbraco.Web.UI.Client/src/less/buttons.less index b1e9671de3..0b21864127 100644 --- a/src/Umbraco.Web.UI.Client/src/less/buttons.less +++ b/src/Umbraco.Web.UI.Client/src/less/buttons.less @@ -63,9 +63,6 @@ .btn-group>.btn+.dropdown-toggle { box-shadow: none; -webkit-box-shadow:none; -} - -.btn-group .btn.dropdown-toggle { border-left-width: 1px; border-left-style: solid; border-color: rgba(0,0,0,0.09); diff --git a/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less b/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less index 78c1616bc6..cbb38a23b1 100644 --- a/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less +++ b/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less @@ -81,9 +81,9 @@ a, a:hover{ .wait { display: block; - height: 280px; + height: 100%; width: 100%; - background: center center url(../img/loader.gif) no-repeat; + background:#fff center center url(../img/loader.gif) no-repeat; } /****************************/ diff --git a/src/Umbraco.Web.UI.Client/src/less/components/application/umb-drawer.less b/src/Umbraco.Web.UI.Client/src/less/components/application/umb-drawer.less index cc024ca5bb..2c7f07ef26 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/application/umb-drawer.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/application/umb-drawer.less @@ -159,6 +159,7 @@ margin-bottom: 1px; border-radius: 0; border-bottom: 1px solid @gray-9; + padding: 10px; } .umb-help-list-item:last-child { @@ -193,6 +194,7 @@ .umb-help-list-item__title { font-size: 14px; display: block; + margin-left: 26px; } .umb-help-list-item__description { @@ -205,6 +207,7 @@ margin-right: 8px; color: @gray-4; font-size: 18px; + float: left; } .umb-help-list-item__open-icon { @@ -219,4 +222,4 @@ [data-element*="tour-"].umb-help-list-item:hover .umb-help-list-item__title { text-decoration:none; -} \ No newline at end of file +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less index 73f059b4ee..150963cbb2 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less @@ -10,6 +10,10 @@ } } +.umb-toggle:focus .umb-toggle__toggle{ + box-shadow: 0 1px 3px fade(@black, 12%), 0 1px 2px fade(@black, 24%); +} + .umb-toggle__handler { position: absolute; top: 0; @@ -30,6 +34,7 @@ background: @gray-8; border-radius: 90px; position: relative; + transition: box-shadow .3s; } .umb-toggle--checked .umb-toggle__toggle { @@ -43,7 +48,6 @@ /* Labels */ .umb-toggle__label { - font-size: 12px; color: @gray-2; } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/card.less b/src/Umbraco.Web.UI.Client/src/less/components/card.less index e8b8325183..a302ba71b8 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/card.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/card.less @@ -101,11 +101,13 @@ } .umb-card-grid li.-four-in-row { - flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; } .umb-card-grid li.-three-in-row { flex: 0 0 33.33%; + max-width:33.33%; } .umb-card-grid .umb-card-grid-item { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-color-swatches.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-color-swatches.less index a987c5daa3..c6fdf8a7bf 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-color-swatches.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-color-swatches.less @@ -3,8 +3,8 @@ flex-flow: row wrap; .umb-color-box { - border: none; - color: white; + border: 1px solid @gray-8; + color: @white; cursor: pointer; padding: 1px; text-align: center; @@ -19,7 +19,7 @@ justify-content: center; &:hover, &:focus { - box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); + box-shadow: 0 1px 3px fade(@black, 12%), 0 1px 2px fade(@black, 24%); } &.umb-color-box--m { @@ -50,7 +50,7 @@ padding-top: 10px; .umb-color-box__label { - background: #fff; + background: @white; font-size: 14px; display: flex; flex-flow: column wrap; @@ -63,7 +63,8 @@ margin-right: -1px; text-indent: 0; text-align: left; - border: 1px solid @gray-8; + border-top: 1px solid @gray-8; + border-bottom: 1px solid @gray-8; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; overflow: hidden; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-multiple-textbox.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-multiple-textbox.less index 21f59a3e2d..52cc7a9aaf 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-multiple-textbox.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-multiple-textbox.less @@ -1,4 +1,17 @@ -.umb-multiple-textbox .textbox-wrapper { +.umb-multiple-textbox{ + &__confirm{ + position: relative; + + &-action{ + margin: 0; + padding: 2px; + background: transparent; + border: 0 none; + } + } +} + +.umb-multiple-textbox .textbox-wrapper { align-items: center; margin-bottom: 15px; } @@ -7,7 +20,7 @@ margin-bottom: 0; } -.umb-multiple-textbox .textbox-wrapper i { +.umb-multiple-textbox .textbox-wrapper i:not(.icon-delete, .icon-check) { margin-right: 5px; } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less index 514a73407c..5a11403bb3 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less @@ -1,5 +1,6 @@ .umb-nested-content { text-align: center; + position: relative; } .umb-nested-content--not-supported { @@ -208,11 +209,25 @@ width: 99%; } -.usky-grid.umb-nested-content__node-type-picker .cell-tools-menu { - position: relative; - transform: translate(-50%, -25%); -} +.usky-grid.umb-nested-content__node-type-picker { + .cell-tools-menu { + position: relative; + transform: translate(-50%, -25%); + } + .elements li { + &:hover { + i { + color: @white !important; + } + } + + i { + // make sure the item icons shown are in the correct color according to their doc type icon instead of the grid editor item color + color: unset; + } + } +} // this resolves the layout issue introduced in nested content in 7.12 with the addition of the input for link anchors // the attribute selector ensures the change only applies to the linkpicker overlay diff --git a/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-details.less b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-details.less new file mode 100644 index 0000000000..9ddad03b48 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-details.less @@ -0,0 +1,114 @@ +.umb-user-details-avatar { + margin-bottom: 20px; + padding-bottom: 20px; + border-bottom: 1px solid #d8d7d9; +} + +div.umb-user-details-actions > div { + margin-bottom: 20px; +} + +.umb-user-details-actions .umb-button { + margin-bottom: 20px; +} + +.umb-user-details-view-title { + font-size: 20px; + font-weight: bold; + color: @black; + margin-bottom: 30px; +} + +.umb-user-details-view-wrapper { + padding: 20px 60px; +} + +@media (max-width: 768px) { + + .umb-user-details-view-wrapper { + padding: 0; + } +} + +.umb-user-details-section { + margin-bottom: 40px; +} +.umb-user-details-details { + display: flex; +} + +a.umb-user-details-details__back-link { + font-weight: bold; + color: @black; +} + +.umb-user-details-details__back-link:hover { + color: @gray-4; + text-decoration: none; +} + + +@sidebarwidth: 350px; // Width of sidebar. Ugly hack because of old version of Less + +.umb-user-details-details__main-content { + flex: 1 1 auto; + margin-right: 30px; + width: calc(~'100%' - ~'@{sidebarwidth}' - ~'30px'); // Make sure that the main content area doesn't gets affected by inline styling +} + +.umb-user-details-details__main-content .umb-node-preview-add { + max-width: 100%; +} + + +.umb-user-details-details__sidebar { + flex: 0 0 @sidebarwidth; +} + +@media (max-width: 768px) { + + .umb-user-details-details { + flex-direction: column; + } + + .umb-user-details-details__main-content { + flex: 1 1 auto; + width: 100%; + margin-bottom: 30px; + margin-right: 0; + } + + .umb-user-details-details__sidebar { + flex: 1 1 auto; + width: 100%; + } +} + +.umb-user-details-details__section-title { + font-size: 17px; + font-weight: bold; + color: @black; + margin-top: 0; + margin-bottom: 15px; +} + +.umb-user-details-details__section-description { + font-size: 12px; + line-height: 1.6em; + margin-bottom: 15px; +} + +.umb-user-details-details__information-item { + margin-bottom: 10px; + font-size: 13px; +} + +.umb-user-details-details__information-item-label { + color: @black; + font-weight: bold; +} + +.umb-user-details-details__information-item-content { + word-break: break-word; +} + diff --git a/src/Umbraco.Web.UI.Client/src/less/forms.less b/src/Umbraco.Web.UI.Client/src/less/forms.less index 6940987290..e3350b4956 100644 --- a/src/Umbraco.Web.UI.Client/src/less/forms.less +++ b/src/Umbraco.Web.UI.Client/src/less/forms.less @@ -580,7 +580,7 @@ div.help { text-align: center; text-shadow: 0 1px 0 @white; background-color: @gray-10; - border: 1px solid @gray-8; + border: 1px solid @purple-l3; } .add-on, .btn, diff --git a/src/Umbraco.Web.UI.Client/src/less/hacks.less b/src/Umbraco.Web.UI.Client/src/less/hacks.less index 22e2eb4566..cd32c64782 100644 --- a/src/Umbraco.Web.UI.Client/src/less/hacks.less +++ b/src/Umbraco.Web.UI.Client/src/less/hacks.less @@ -202,7 +202,7 @@ pre { //font-size: @baseFontSize - 1; // 14px to 13px color: @gray-2; line-height: @baseLineHeight; - white-space: pre-line; // 1 + white-space: pre-wrap; // 1 overflow-x: auto; // 1 background-color: @gray-10; border: 1px solid @gray-8; @@ -222,4 +222,4 @@ pre { background-color: transparent; border: 0; } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web.UI.Client/src/less/legacydialog.less b/src/Umbraco.Web.UI.Client/src/less/legacydialog.less new file mode 100644 index 0000000000..ca920d22c2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/legacydialog.less @@ -0,0 +1,58 @@ + +.umb-dialog .propertyItemheader { + width: 140px !Important; +} + +.umb-dialog .diffDropdown { + width: 400px; +} + +.umb-dialog .diffPanel { + height: 400px; +} + + +.umb-dialog .diff { + margin-top: 10px; + height: 100%; + overflow: auto; + border-top: 1px solid #ccc; + border-top: 1px solid #ccc; + padding: 5px; +} + +.umb-dialog .diff table { + width: 95%; + max-width: 95%; + margin: 0 3px; +} + +.umb-dialog .diff table th { + padding: 5px; + width: 25%; + border-bottom: 1px solid #ccc; +} + +.umb-dialog .diff table td { + border-bottom: 1px solid #ccc; + padding: 3px; +} + +.umb-dialog .diff del { + background: rgb(255, 230, 230) none repeat scroll 0%; + -moz-background-clip: -moz-initial; + -moz-background-origin: -moz-initial; + -moz-background-inline-policy: -moz-initial; +} + +.umb-dialog .diff ins { + background: rgb(230, 255, 230) none repeat scroll 0%; + -moz-background-clip: -moz-initial; + -moz-background-origin: -moz-initial; + -moz-background-inline-policy: -moz-initial; +} + +.umb-dialog .diff .diffnotice { + text-align: center; + margin-bottom: 10px; +} diff --git a/src/Umbraco.Web.UI.Client/src/less/panel.less b/src/Umbraco.Web.UI.Client/src/less/panel.less index def6d114ff..912e7d90e2 100644 --- a/src/Umbraco.Web.UI.Client/src/less/panel.less +++ b/src/Umbraco.Web.UI.Client/src/less/panel.less @@ -52,6 +52,16 @@ -webkit-flex: 1; -ms-flex: 1; flex: 1; + + &__toggle{ + margin: 10px 0; + + label{ + margin-right: 10px; + position: relative; + top: -2px; + } + } } .upload-button { diff --git a/src/Umbraco.Web.UI.Client/src/less/property-editors.less b/src/Umbraco.Web.UI.Client/src/less/property-editors.less index 198885e6be..27a51bc80c 100644 --- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less +++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less @@ -120,6 +120,13 @@ div.umb-codeeditor .umb-btn-toolbar { // // RTE // -------------------------------------------------- +.umb-rte { + position: relative; + + .-loading { + position: absolute; + } +} .mce-tinymce{border: 1px solid @gray-8 !important; border-radius: 0px !important;} .mce-panel{background: @gray-10 !important; border-color: @gray-8 !important;} .mce-btn-group, .mce-btn{border: none !important; background: none !important;} @@ -142,11 +149,14 @@ div.umb-codeeditor .umb-btn-toolbar { /* pre-value editor */ .control-group.color-picker-preval { .thumbnail { - width: 36px; + width: 34px; + height: 34px; min-width: auto; border: none; cursor: move; border-radius: 3px; + margin-top: auto; + margin-bottom: auto; } .handle { @@ -158,19 +168,19 @@ div.umb-codeeditor .umb-btn-toolbar { div.color-picker-prediv { display: inline-flex; align-items: center; - max-width: 85%; + max-width: 100%; + flex: 1; pre { display: inline-flex; font-family: monospace; - margin-right: 10px; - margin-left: 10px; + margin-left: 15px; + margin-right: 15px; white-space: nowrap; overflow: hidden; margin-bottom: 0; vertical-align: middle; - padding-top: 7px; - padding-bottom: 7px; + padding: 6px 10px; background: #f7f7f7; flex: 0 0 auto; } @@ -199,11 +209,11 @@ div.umb-codeeditor .umb-btn-toolbar { label { border: 1px solid #fff; - padding: 7px 10px; + padding: 6px 10px; font-family: monospace; border: 1px solid #dfdfe1; background: #f7f7f7; - margin: 0 15px 0 0; + margin: 0 15px 0 3px; border-radius: 3px; } } @@ -310,7 +320,7 @@ div.umb-codeeditor .umb-btn-toolbar { .umb-mediapicker .umb-sortable-thumbnails li { flex-direction: column; - margin: 0 5px 5px 0; + margin: 0 0 5px 5px; padding: 5px; } @@ -579,6 +589,16 @@ div.umb-codeeditor .umb-btn-toolbar { } } + .imagecropper .umb-cropper__container .button-drawer { + display: flex; + justify-content: flex-end; + padding: 10px; + + button { + margin-left: 4px; + } + } + .umb-close-cropper { position: absolute; top: 3px; @@ -843,7 +863,20 @@ div.umb-codeeditor .umb-btn-toolbar { // // Nested boolean (e.g. list view bulk action permissions) -// ---------------------=====----------------------------- +// ------------------------------------------------------- .umb-nested-boolean label {margin-bottom: 8px; float: left; width: 320px;} .umb-nested-boolean label span {float: left; width: 80%;} .umb-nested-boolean label input[type='checkbox'] {margin-right: 10px; float: left;} + +// +// Custom styles of property editors in property preview in document type editor +// ----------------------------------------------------------------------------- +.umb-group-builder__property-preview { + .umb-property-editor { + .slider { + .tooltip { + display: none; + } + } + } +} diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js index c965d16c0d..ac529fc215 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js @@ -207,7 +207,7 @@ } } - $scope.allowPasswordReset = Umbraco.Sys.ServerVariables.umbracoSettings.allowPasswordReset; + $scope.allowPasswordReset = Umbraco.Sys.ServerVariables.umbracoSettings.canSendRequiredEmail && Umbraco.Sys.ServerVariables.umbracoSettings.allowPasswordReset; $scope.showLogin = function () { $scope.errorMsg = ""; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js index 9b563be2df..40f5035d11 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js @@ -151,7 +151,7 @@ angular.module("umbraco") if (folder.id > 0) { entityResource.getAncestors(folder.id, "media") - .then(function(anc) { + .then(function(anc) { $scope.path = _.filter(anc, function(f) { return f.path.indexOf($scope.startNodeId) !== -1; @@ -236,7 +236,10 @@ angular.module("umbraco") $scope.onUploadComplete = function(files) { $scope.gotoFolder($scope.currentFolder).then(function() { if (files.length === 1 && $scope.model.selectedImages.length === 0) { - selectImage($scope.images[$scope.images.length - 1]); + var image = $scope.images[$scope.images.length - 1]; + $scope.target = image; + $scope.target.url = mediaHelper.resolveFile(image); + selectImage(image); } }); }; @@ -305,6 +308,23 @@ angular.module("umbraco") debounceSearchMedia(); }; + /** + * Toggle the $scope.model.allowAsRoot value to either true or false + */ + $scope.toggle = function(){ + + // Make sure to activate the changeSearch function everytime the toggle is clicked + $scope.changeSearch(); + + // Toggle the showChilds option + if($scope.showChilds){ + $scope.showChilds = false; + return; + } + + $scope.showChilds = true; + } + $scope.changePagination = function(pageNumber) { $scope.loading = true; $scope.searchOptions.pageNumber = pageNumber; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html index 5da564d41f..7a9ccd9b89 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html @@ -30,12 +30,15 @@ ng-change="changeSearch()" type="text" no-dirty-check /> -
- + +
+ + + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-toggle.html b/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-toggle.html index fc62485521..bc5c114bb6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-toggle.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-toggle.html @@ -1,4 +1,4 @@ -
-
{{error.errorMsg}}
-

{{error.data.message}}

+
+
{{error.errorMsg}}
+
{{error.data.message}}
+
-
{{currentNode.name}} was moved underneath {{target.name}}
+
+ {{currentNode.name}} was moved underneath {{target.name}} +
diff --git a/src/Umbraco.Web.UI.Client/src/views/datatypes/rename.html b/src/Umbraco.Web.UI.Client/src/views/datatypes/rename.html index 6840e58565..ec93009a4c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/datatypes/rename.html +++ b/src/Umbraco.Web.UI.Client/src/views/datatypes/rename.html @@ -7,8 +7,10 @@ val-form-manager>
-
{{error.errorMsg}}
-

{{error.data.message}}

+
+
{{error.errorMsg}}
+
{{error.data.message}}
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/copy.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/copy.html index af3b954c83..6543d7a280 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/copy.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/copy.html @@ -12,13 +12,16 @@
-
{{error.errorMsg}}
-

{{error.data.message}}

+
+
{{error.errorMsg}}
+
{{error.data.message}}
+
-
- {{currentNode.name}} was copied underneath {{target.name}}
+
+ {{currentNode.name}} was copied underneath {{target.name}} +
diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.controller.js index 9fae0a6304..5fa70263b9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.controller.js @@ -26,8 +26,8 @@ function DocumentTypesCreateController($scope, $location, navigationService, con $scope.showCreateDocTypeCollection = function () { $scope.model.creatingDoctypeCollection = true; - $scope.model.collectionCreateTemplate = true; - $scope.model.collectionItemCreateTemplate = true; + $scope.model.collectionCreateTemplate = !$scope.model.disableTemplates; + $scope.model.collectionItemCreateTemplate = !$scope.model.disableTemplates; }; $scope.createContainer = function () { diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.html index 917e9147a4..d19b1329d2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.html @@ -16,8 +16,8 @@ - - Document type> + + Document type> @@ -45,8 +45,10 @@ val-form-manager>
-
{{error.errorMsg}}
-

{{error.data.message}}

+
+
{{error.errorMsg}}
+
{{error.data.message}}
+
@@ -69,20 +71,26 @@ val-form-manager>
-
{{error.errorMsg}}
-

{{error.data.message}}

+
+
{{error.errorMsg}}
+
{{error.data.message}}
+
- - + + + + - - + + + + diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js index 7a1a825e46..10c563a289 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js @@ -9,7 +9,7 @@ (function () { "use strict"; - function DocumentTypesEditController($scope, $routeParams, $injector, contentTypeResource, dataTypeResource, editorState, contentEditingHelper, formHelper, navigationService, iconHelper, contentTypeHelper, notificationsService, $filter, $q, localizationService, overlayHelper, eventsService) { + function DocumentTypesEditController($scope, $routeParams, $injector, contentTypeResource, dataTypeResource, editorState, contentEditingHelper, formHelper, navigationService, iconHelper, contentTypeHelper, notificationsService, $filter, $q, localizationService, overlayHelper, eventsService, angularHelper) { var vm = this; var evts = []; @@ -478,6 +478,15 @@ eventsService.unsubscribe(evts[e]); } }); + + // #3368 - changes on the other "buttons" do not register on the current form, so we manually have to flag the form as dirty + $scope.$watch("vm.contentType.allowedContentTypes.length + vm.contentType.allowAsRoot + vm.contentType.allowedTemplates.length + vm.contentType.isContainer", function (newVal, oldVal) { + if (oldVal === undefined) { + // still initializing, ignore + return; + } + angularHelper.getCurrentForm($scope).$setDirty(); + }); } angular.module("umbraco").controller("Umbraco.Editors.DocumentTypes.EditController", DocumentTypesEditController); diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/move.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/move.html index 379a64fc14..a75c6346c7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/move.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/move.html @@ -12,13 +12,16 @@
-
{{error.errorMsg}}
-

{{error.data.message}}

+
+
{{error.errorMsg}}
+
{{error.data.message}}
+
-
- {{currentNode.name}} was moved underneath {{target.name}}
+
+ {{currentNode.name}} was moved underneath {{target.name}} +
diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/rename.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/rename.html index f739cadb71..c52b3be6d6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/rename.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/rename.html @@ -6,8 +6,10 @@ val-form-manager>
-
{{error.errorMsg}}
-

{{error.data.message}}

+
+
{{error.errorMsg}}
+
{{error.data.message}}
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/media/apps/content/content.controller.js b/src/Umbraco.Web.UI.Client/src/views/media/apps/content/content.controller.js index 6dcf1211c2..365cb03a5d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/apps/content/content.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/media/apps/content/content.controller.js @@ -5,14 +5,6 @@ var vm = this; - function onInit() { - angular.forEach($scope.content.tabs, function(group){ - group.open = true; - }); - } - - onInit(); - } angular.module("umbraco").controller("Umbraco.Editors.Media.Apps.ContentController", MediaAppContentController); diff --git a/src/Umbraco.Web.UI.Client/src/views/media/apps/content/content.html b/src/Umbraco.Web.UI.Client/src/views/media/apps/content/content.html index 358dcef27d..f8bbf5ed54 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/apps/content/content.html +++ b/src/Umbraco.Web.UI.Client/src/views/media/apps/content/content.html @@ -1,5 +1,5 @@
-
+
{{ group.label }}
diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/copy.html b/src/Umbraco.Web.UI.Client/src/views/mediatypes/copy.html index 8104fcc979..97b21d6645 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/copy.html +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/copy.html @@ -12,13 +12,16 @@
-
{{error.errorMsg}}
-

{{error.data.message}}

+
+
{{error.errorMsg}}
+
{{error.data.message}}
+
-
- {{currentNode.name}} was copied underneath {{target.name}}
+
+ {{currentNode.name}} was copied underneath {{target.name}} +
diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/move.html b/src/Umbraco.Web.UI.Client/src/views/mediatypes/move.html index 5d96375b44..d6a8fa4e70 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/move.html +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/move.html @@ -12,12 +12,16 @@
-
{{error.errorMsg}}
-

{{error.data.message}}

+
+
{{error.errorMsg}}
+
{{error.data.message}}
+
-
{{currentNode.name}} was moved underneath {{target.name}}
+
+ {{currentNode.name}} was moved underneath {{target.name}} +
diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/rename.html b/src/Umbraco.Web.UI.Client/src/views/mediatypes/rename.html index 5f027cf607..0bc4aa5123 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/rename.html +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/rename.html @@ -6,8 +6,10 @@ val-form-manager>
-
{{error.errorMsg}}
-

{{error.data.message}}

+
+
{{error.errorMsg}}
+
{{error.data.message}}
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/member/edit.html b/src/Umbraco.Web.UI.Client/src/views/member/edit.html index fb9d99a9eb..310559b4d4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/member/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/member/edit.html @@ -18,7 +18,7 @@ -
+
{{ group.label }}
diff --git a/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js index 78daeceab4..a3c74c56d1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js @@ -77,10 +77,10 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS } else { //so, we usually refernce all editors with the Int ID, but with members we have - //a different pattern, adding a route-redirect here to handle this: - //isNumber doesnt work here since its seen as a string - - //TODO: Why is this here - I don't understand why this would ever be an integer? This will not work when we support non-umbraco membership providers. + //a different pattern, adding a route-redirect here to handle this just in case. + //(isNumber doesnt work here since its seen as a string) + //The reason this might be an INT is due to the routing used for the member list view + //but this is now configured to use the key, so this is just a fail safe if ($routeParams.id && $routeParams.id.length < 9) { diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.html b/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.html index b7fcf00bba..36ab0e71c1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.html @@ -61,8 +61,10 @@ val-form-manager>
-
{{vm.createFolderError.errorMsg}}
-

{{vm.createFolderError.data.message}}

+
+
{{vm.createFolderError.errorMsg}}
+
{{vm.createFolderError.data.message}}
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviews/create.html b/src/Umbraco.Web.UI.Client/src/views/partialviews/create.html index 4ca34379e6..59c0b0b344 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviews/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/partialviews/create.html @@ -51,8 +51,10 @@ val-form-manager>
-
{{vm.createFolderError.errorMsg}}
-

{{vm.createFolderError.data.message}}

+
+
{{vm.createFolderError.errorMsg}}
+
{{vm.createFolderError.data.message}}
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js index 4c8c5f845a..a6ef34f43b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js @@ -1,4 +1,4 @@ -function booleanEditorController($scope, $rootScope, assetsService) { +function booleanEditorController($scope) { function setupViewModel() { $scope.renderModel = { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html index 443b677790..0f90239b0e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html @@ -1,6 +1,10 @@
+ on-click="toggle()" + show-labels="{{model.config.labelOn ? 'true': 'false'}}" + label-position="right" + label-on="{{model.config.labelOn}}" + label-off="{{model.config.labelOn}}">
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js index 14c37d2ee4..17be7718d6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js @@ -11,7 +11,8 @@ function ColorPickerController($scope) { //map back to the model $scope.model.config = config; - + + //TODO: This isn't used function convertArrayToDictionaryArray(model) { //now we need to format the items in the dictionary because we always want to have an array var newItems = []; @@ -22,7 +23,7 @@ function ColorPickerController($scope) { return newItems; } - + //TODO: This isn't used function convertObjectToDictionaryArray(model) { //now we need to format the items in the dictionary because we always want to have an array var newItems = []; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html index e209d0cb60..c86e7f44f7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html @@ -1,5 +1,6 @@ 
+
You haven't defined any colors
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.prevalues.html index a70ecabf35..1056b45f9d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.prevalues.html @@ -3,18 +3,22 @@
- +
-
+
-
-
#{{item.value}}
{{item.label}}
+
+
+
#{{item.value}}
+ + +
Remove diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/multicolorpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/multicolorpicker.controller.js index 7ae728a85a..287a0f48fc 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/multicolorpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/multicolorpicker.controller.js @@ -5,8 +5,9 @@ var defaultLabel = null; $scope.newColor = defaultColor; - $scope.newLavel = defaultLabel; + $scope.newLabel = defaultLabel; $scope.hasError = false; + $scope.focusOnNew = false; $scope.labels = {}; @@ -104,7 +105,6 @@ }; $scope.add = function (evt) { - evt.preventDefault(); if ($scope.newColor) { @@ -117,7 +117,9 @@ value: $scope.newColor, label: newLabel }); + $scope.newLabel = ""; $scope.hasError = false; + $scope.focusOnNew = true; return; } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js index 0fb0e75d09..9bed59b0d7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js @@ -35,6 +35,22 @@ function dateTimePickerController($scope, notificationsService, assetsService, a } }; + //here we declare a special method which will be called whenever the value has changed from the server + //this is instead of doing a watch on the model.value = faster + $scope.model.onValueChanged = function (newVal, oldVal) { + if (newVal != oldVal) { + //check for c# System.DateTime.MinValue being passed as the clear indicator + var minDate = moment('0001-01-01'); + var newDate = moment(newVal); + + if (newDate.isAfter(minDate)) { + applyDate({ date: moment(newVal) }); + } else { + $scope.clearDate(); + } + } + }; + //handles the date changing via the date picker function applyDate(e) { angularHelper.safeApply($scope, function() { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js index 38e32b7451..7d7405bedb 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js @@ -285,9 +285,11 @@ angular.module("umbraco") event: event, show: true, submit: function(model) { + if (model.selectedItem) { $scope.addControl(model.selectedItem, area, index); $scope.editorOverlay.show = false; $scope.editorOverlay = null; + } } }; }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/idwithguid/idwithguid.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/idwithguid/idwithguid.controller.js new file mode 100644 index 0000000000..1402226f78 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/idwithguid/idwithguid.controller.js @@ -0,0 +1,25 @@ +/** + * @ngdoc controller + * @name Umbraco.Editors.IdWithGuidValueController + * @function + * + * @description + * The controller for the idwithguid property editor, which formats the ID as normal + * with the GUID in smaller text below, as used across the backoffice. +*/ +function IdWithGuidValueController($rootScope, $scope, $filter) { + + function formatDisplayValue() { + if ($scope.model.value.length > 1) { + $scope.displayid = $scope.model.value[0]; + $scope.displayguid = $scope.model.value[1]; + } else { + $scope.displayid = $scope.model.value; + } + } + + //format the display value on init: + formatDisplayValue(); +} + +angular.module('umbraco').controller("Umbraco.PropertyEditors.IdWithGuidValueController", IdWithGuidValueController); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/idwithguid/idwithguid.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/idwithguid/idwithguid.html new file mode 100644 index 0000000000..02179b7c71 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/idwithguid/idwithguid.html @@ -0,0 +1,4 @@ +
+
{{ displayid }}
+ {{ displayguid }} +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js index 04bfe98284..e4a7bd5267 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js @@ -1,15 +1,18 @@ angular.module('umbraco') .controller("Umbraco.PropertyEditors.ImageCropperController", - function ($rootScope, $routeParams, $scope, $log, mediaHelper, cropperHelper, $timeout, editorState, umbRequestHelper, fileManager, angularHelper) { + function ($scope, fileManager) { var config = angular.copy($scope.model.config); $scope.filesSelected = onFileSelected; $scope.filesChanged = onFilesChanged; $scope.fileUploaderInit = onFileUploaderInit; + $scope.imageLoaded = imageLoaded; $scope.crop = crop; $scope.done = done; $scope.clear = clear; + $scope.reset = reset; + $scope.close = close; $scope.focalPointChanged = focalPointChanged; //declare a special method which will be called whenever the value has changed from the server $scope.model.onValueChanged = onValueChanged; @@ -65,6 +68,11 @@ angular.module('umbraco') $scope.imageCropperForm.$setDirty(); } + function imageLoaded (isCroppable, hasDimensions) { + $scope.isCroppable = isCroppable; + $scope.hasDimensions = hasDimensions; + }; + /** * Called when the file collection changes * @param {any} value @@ -122,7 +130,8 @@ angular.module('umbraco') * @param {any} crop */ function crop(crop) { - $scope.currentCrop = crop; + // clone the crop so we can discard the changes + $scope.currentCrop = angular.copy(crop); $scope.currentPoint = null; //set form to dirty to track changes @@ -131,13 +140,28 @@ angular.module('umbraco') /** done cropping */ function done() { - $scope.currentCrop = null; - $scope.currentPoint = null; + if (!$scope.currentCrop) { + return; + } + // find the original crop by crop alias and update its coordinates + var editedCrop = _.find($scope.model.value.crops, crop => crop.alias === $scope.currentCrop.alias); + editedCrop.coordinates = $scope.currentCrop.coordinates; + $scope.close(); //set form to dirty to track changes $scope.imageCropperForm.$setDirty(); }; + function reset() { + $scope.currentCrop.coordinates = undefined; + $scope.done(); + } + + function close() { + $scope.currentCrop = undefined; + $scope.currentPoint = undefined; + } + /** * crop a specific crop * @param {any} crop @@ -171,7 +195,7 @@ angular.module('umbraco') }) .run(function (mediaHelper, umbRequestHelper) { if (mediaHelper && mediaHelper.registerFileResolver) { - + //NOTE: The 'entity' can be either a normal media entity or an "entity" returned from the entityResource // they contain different data structures so if we need to query against it we need to be aware of this. mediaHelper.registerFileResolver("Umbraco.ImageCropper", function (property, entity, thumbnail) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html index 5e920cee01..4f46f4c5ae 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html @@ -2,7 +2,6 @@ ng-controller="Umbraco.PropertyEditors.ImageCropperController"> -
- -
- - Reset - +
+ + + +
+
+ on-value-changed="focalPointChanged(left, top)" + on-image-loaded="imageLoaded(isCroppable, hasDimensions)"> Remove file
- + -
    +
    • - - - + +
      + + + + +
      +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html index 7aa2a14b26..c45e118891 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html @@ -1,5 +1,5 @@
-
Loading...
+
Loading...
- - -
+
+ + + +
-
-
+
+
Last login:
-
+
{{ model.user.formattedLastLogin }} {{ model.user.name | umbWordLimit:1 }} has not logged in yet
-
-
+
+
Failed login attempts:
-
+
{{ model.user.failedPasswordAttempts }}
-
-
+
+
Last lockout date:
-
+
{{ model.user.name | umbWordLimit:1 }} hasn't been locked out @@ -363,11 +364,11 @@
-
-
+
+
Password is last changed:
-
+
The password hasn't been changed @@ -375,24 +376,36 @@
-
-
+
+
User is created:
-
+
{{ model.user.formattedCreateDate }}
-
-
+
+
User is last updated:
-
+
{{ model.user.formattedUpdateDate }}
+
+
+ Id: +
+
+ {{ model.user.id }} +
+
+ {{ model.user.key }} +
+
+ diff --git a/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml index 38b178fcfa..fcd375da45 100644 --- a/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Views/Preview/Index.cshtml @@ -32,7 +32,7 @@ @Html.Partial(Model.PreviewExtendedHeaderView) } -
+
diff --git a/src/Umbraco.Web.UI/Umbraco/config/create/UI.Release.xml b/src/Umbraco.Web.UI/Umbraco/config/create/UI.Release.xml index 52abf37133..0ebdb5cd48 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/create/UI.Release.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/create/UI.Release.xml @@ -15,50 +15,6 @@ - -
membergroup
- /create/simple.ascx - - - -
- -
membergroup
- /create/simple.ascx - - - -
- -
Stylesheet
- /create/simple.ascx - - - -
- -
Stylesheet
- /create/simple.ascx - - - - -
- -
Stylesheet editor egenskab
- /create/simple.ascx - - - - -
- -
Stylesheet editor egenskab
- /create/simple.ascx - - - -
Package
/create/simple.ascx diff --git a/src/Umbraco.Web.UI/Umbraco/config/create/UI.xml b/src/Umbraco.Web.UI/Umbraco/config/create/UI.xml index 82adc71525..d6be62ff88 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/create/UI.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/create/UI.xml @@ -15,50 +15,6 @@
- -
membergroup
- /create/simple.ascx - - - -
- -
membergroup
- /create/simple.ascx - - - -
- -
Stylesheet
- /create/simple.ascx - - - -
- -
Stylesheet
- /create/simple.ascx - - - - -
- -
Stylesheet editor egenskab
- /create/simple.ascx - - - - -
- -
Stylesheet editor egenskab
- /create/simple.ascx - - - -
Package
/create/simple.ascx diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml index e5dfe70db7..e624e22b75 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/da.xml @@ -145,6 +145,7 @@ Brugeren har tilbagerullet indholdet til en tidligere tilstand Brugeren har sendt indholdet til udgivelse Brugeren har sendt indholdet til oversættelse + Brugeren har sorteret de underliggende sider Kopieret Udgivet Flyttet @@ -154,6 +155,7 @@ Indhold tilbagerullet Sendt til udgivelse Sendt til oversættelse + Sorteret For at skifte det valgte indholds dokumenttype, skal du først vælge en ny dokumenttype, som er gyldig på denne placering. @@ -254,7 +256,7 @@ Klik for at uploade eller klik her for at vælge filer - Du kan trække filer herind for at uploade + Du kan trække filer herind for at uploade. Kan ikke uploade denne fil, den har ikke en godkendt filtype Maks filstørrelse er Medie rod @@ -421,6 +423,8 @@ Indtast din e-mail Indtast en besked... Dit brugernavn er typisk din e-mailadresse + Indtast alias... + Genererer alias... Tilladte typer @@ -530,6 +534,7 @@ Skjul Historik Ikon + Id Importer Indre margen Indsæt @@ -918,6 +923,8 @@ Mange hilsner fra Umbraco robotten Nulstil + Acceptér + Fortryd Nuværende version diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index 28376bf593..e852be1a4e 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -150,6 +150,7 @@ Content rolled back Content sent for publishing Content cultures %0% sent for publishing + Sort child items performed by user Copy Publish Publish @@ -161,6 +162,7 @@ Rollback Send To Publish Send To Publish + Sort To change the document type for the selected content, first select from the list of valid types for this location. @@ -286,7 +288,7 @@ Document Type without a template New folder New data type - New javascript file + New JavaScript file New empty partial view New partial view macro New partial view from snippet @@ -444,6 +446,8 @@ Enter a message... Your username is usually your email #value or ?key=value + Enter alias... + Generating alias... Allowed child node types @@ -561,6 +565,7 @@ Hide History Icon + Id Import Info Inner margin @@ -612,7 +617,7 @@ Permissions Scheduled Publishing Search - Sorry, we can not find what you are looking for + Sorry, we cannot find what you are looking for No items have been added Server Settings @@ -1106,7 +1111,7 @@ To manage your website, simply open the Umbraco back office and start adding con Role based protection - using Umbraco's member groups.]]> + If you wish to control access to the page using role-based authentication, using Umbraco's member groups. You need to create a membergroup before you can use role-based authentication Error Page Used when people are logged on, but do not have access @@ -1170,11 +1175,13 @@ To manage your website, simply open the Umbraco back office and start adding con Enter the link - Reset + Reset crop Define crop Give the crop an alias and its default width and height Save crop Add new crop + Done + Undo edits Current version @@ -1263,6 +1270,7 @@ To manage your website, simply open the Umbraco back office and start adding con Sent For Approval Changes have been sent for approval Media saved + Member group saved Media saved without any errors Member saved Stylesheet Property Saved diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index f466ff699a..54d86eee5c 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -155,6 +155,7 @@ Content rolled back Content sent for publishing Content cultures %0% sent for publishing + Sort child items performed by user Copy Publish Publish @@ -166,6 +167,7 @@ Rollback Send To Publish Send To Publish + Sort To change the document type for the selected content, first select from the list of valid types for this location. @@ -294,6 +296,7 @@ Create a new member All Members + Member groups have no additional properties for editing. Where do you want to create the new %0% @@ -305,7 +308,7 @@ Document Type without a template New folder New data type - New javascript file + New JavaScript file New empty partial view New partial view macro New partial view from snippet @@ -463,6 +466,8 @@ Enter a message... Your username is usually your email #value or ?key=value + Enter alias... + Generating alias... Allowed child node types @@ -580,6 +585,7 @@ Hide History Icon + Id Import Info Inner margin @@ -631,7 +637,7 @@ Permissions Scheduled Publishing Search - Sorry, we can not find what you are looking for + Sorry, we cannot find what you are looking for No items have been added Server Settings @@ -1125,7 +1131,7 @@ To manage your website, simply open the Umbraco back office and start adding con Role based protection - using Umbraco's member groups.]]> + If you wish to control access to the page using role-based authentication, using Umbraco's member groups. You need to create a membergroup before you can use role-based authentication Error Page Used when people are logged on, but do not have access @@ -1188,11 +1194,13 @@ To manage your website, simply open the Umbraco back office and start adding con Enter the link - Reset + Reset crop Define crop Give the crop an alias and its default width and height Save crop Add new crop + Done + Undo edits Current version @@ -1281,6 +1289,7 @@ To manage your website, simply open the Umbraco back office and start adding con Media saved Media saved without any errors Member saved + Member group saved Stylesheet Property Saved Stylesheet saved Template saved diff --git a/src/Umbraco.Web.UI/Umbraco/dialogs/protectPage.aspx b/src/Umbraco.Web.UI/Umbraco/dialogs/protectPage.aspx index 7e76240d14..5bcf97310f 100644 --- a/src/Umbraco.Web.UI/Umbraco/dialogs/protectPage.aspx +++ b/src/Umbraco.Web.UI/Umbraco/dialogs/protectPage.aspx @@ -74,15 +74,19 @@ - - + +
+ +
+ +
-
+
@@ -116,74 +120,72 @@ + +
+ - - -
- - - - -
- -
- - - -
- - -

Member name already exists, click Change to use a different name or Update to continue

-
-
- - - -

<%= Services.TextService.Localize("publicAccess/paSelectRoles")%>

-
- - - -
- - - - - - - <%=Services.TextService.Localize("paLoginPageHelp")%> - -
- +
+ + + +
- - - - - - - <%=Services.TextService.Localize("paErrorPageHelp")%> - -
- +
+ + +
- - - + +

Member name already exists, click Change to use a different name or Update to continue

+
+ + + + +

<%= Services.TextService.Localize("publicAccess/paSelectRoles")%>

+
+ + + +
+ + + + + + <%=Services.TextService.Localize("paLoginPageHelp")%> + +
+ +
+ + +
+ + + <%=Services.TextService.Localize("paErrorPageHelp")%> + +
+ +
+ +
+ +
+
- diff --git a/src/Umbraco.Web.UI/config/EmbeddedMedia.Release.config b/src/Umbraco.Web.UI/config/EmbeddedMedia.Release.config index 32a165399c..442493e3d6 100644 --- a/src/Umbraco.Web.UI/config/EmbeddedMedia.Release.config +++ b/src/Umbraco.Web.UI/config/EmbeddedMedia.Release.config @@ -124,7 +124,7 @@ - + diff --git a/src/Umbraco.Web.UI/config/EmbeddedMedia.config b/src/Umbraco.Web.UI/config/EmbeddedMedia.config index ac8c5cc901..c466b14f1c 100644 --- a/src/Umbraco.Web.UI/config/EmbeddedMedia.config +++ b/src/Umbraco.Web.UI/config/EmbeddedMedia.config @@ -124,7 +124,7 @@ - + diff --git a/src/Umbraco.Web.UI/web.Template.config b/src/Umbraco.Web.UI/web.Template.config index 844855f10f..50319370e9 100644 --- a/src/Umbraco.Web.UI/web.Template.config +++ b/src/Umbraco.Web.UI/web.Template.config @@ -82,9 +82,14 @@ + diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index b0cdcb72b9..98114f0664 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -57,7 +57,7 @@ namespace Umbraco.Web.Editors var keepOnlyKeys = new Dictionary { {"umbracoUrls", new[] {"authenticationApiBaseUrl", "serverVarsJs", "externalLoginsUrl", "currentUserApiBaseUrl"}}, - {"umbracoSettings", new[] {"allowPasswordReset", "imageFileTypes", "maxFileSize", "loginBackgroundImage"}}, + {"umbracoSettings", new[] {"allowPasswordReset", "imageFileTypes", "maxFileSize", "loginBackgroundImage", "canSendRequiredEmail"}}, {"application", new[] {"applicationPath", "cacheBuster"}}, {"isDebuggingEnabled", new string[] { }}, {"features", new [] {"disabledFeatures"}} @@ -224,6 +224,10 @@ namespace Umbraco.Web.Editors "memberTypeApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( controller => controller.GetAllTypes()) }, + { + "memberGroupApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( + controller => controller.GetAllGroups()) + }, { "updateCheckApiBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( controller => controller.GetCheck()) @@ -326,6 +330,7 @@ namespace Umbraco.Web.Editors {"allowPasswordReset", UmbracoConfig.For.UmbracoSettings().Security.AllowPasswordReset}, {"loginBackgroundImage", UmbracoConfig.For.UmbracoSettings().Content.LoginBackgroundImage}, {"showUserInvite", EmailSender.CanSendRequiredEmail}, + {"canSendRequiredEmail", EmailSender.CanSendRequiredEmail}, } }, { diff --git a/src/Umbraco.Web/Editors/Binders/BlueprintItemBinder.cs b/src/Umbraco.Web/Editors/Binders/BlueprintItemBinder.cs new file mode 100644 index 0000000000..eb4d482b14 --- /dev/null +++ b/src/Umbraco.Web/Editors/Binders/BlueprintItemBinder.cs @@ -0,0 +1,24 @@ +using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Core.Services; +using Umbraco.Web.Models.ContentEditing; + +namespace Umbraco.Web.Editors.Binders +{ + internal class BlueprintItemBinder : ContentItemBinder + { + public BlueprintItemBinder() + { + } + + public BlueprintItemBinder(ILogger logger, ServiceContext services, IUmbracoContextAccessor umbracoContextAccessor) + : base(logger, services, umbracoContextAccessor) + { + } + + protected override IContent GetExisting(ContentItemSave model) + { + return Services.ContentService.GetBlueprintById(model.Id); + } + } +} diff --git a/src/Umbraco.Web/Editors/Binders/ContentItemBinder.cs b/src/Umbraco.Web/Editors/Binders/ContentItemBinder.cs index a3cb1d229a..fd8951993b 100644 --- a/src/Umbraco.Web/Editors/Binders/ContentItemBinder.cs +++ b/src/Umbraco.Web/Editors/Binders/ContentItemBinder.cs @@ -1,23 +1,15 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Net; -using System.Net.Http; -using System.Web.Http; using System.Web.Http.Controllers; using System.Web.Http.ModelBinding; using AutoMapper; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Models.Editors; using Umbraco.Core.Services; using Umbraco.Web.Composing; -using Umbraco.Web.Editors.Filters; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.Mapping; -using Umbraco.Web.WebApi; -using Umbraco.Web.WebApi.Filters; namespace Umbraco.Web.Editors.Binders { @@ -26,7 +18,6 @@ namespace Umbraco.Web.Editors.Binders ///
internal class ContentItemBinder : IModelBinder { - private readonly ServiceContext _services; private readonly ContentModelBinderHelper _modelBinderHelper; public ContentItemBinder() : this(Current.Logger, Current.Services, Current.UmbracoContextAccessor) @@ -35,10 +26,12 @@ namespace Umbraco.Web.Editors.Binders public ContentItemBinder(ILogger logger, ServiceContext services, IUmbracoContextAccessor umbracoContextAccessor) { - _services = services; + Services = services; _modelBinderHelper = new ContentModelBinderHelper(); } + protected ServiceContext Services { get; } + /// /// Creates the model from the request and binds it to the context /// @@ -78,14 +71,14 @@ namespace Umbraco.Web.Editors.Binders return true; } - private IContent GetExisting(ContentItemSave model) + protected virtual IContent GetExisting(ContentItemSave model) { - return _services.ContentService.GetById(model.Id); + return Services.ContentService.GetById(model.Id); } private IContent CreateNew(ContentItemSave model) { - var contentType = _services.ContentTypeService.Get(model.ContentTypeAlias); + var contentType = Services.ContentTypeService.Get(model.ContentTypeAlias); if (contentType == null) { throw new InvalidOperationException("No content type found with alias " + model.ContentTypeAlias); diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index cce9a2d2ed..6e095e8393 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -555,7 +555,7 @@ namespace Umbraco.Web.Editors /// [FileUploadCleanupFilter] [ContentSaveValidation] - public ContentItemDisplay PostSaveBlueprint([ModelBinder(typeof(ContentItemBinder))] ContentItemSave contentItem) + public ContentItemDisplay PostSaveBlueprint([ModelBinder(typeof(BlueprintItemBinder))] ContentItemSave contentItem) { var contentItemDisplay = PostSaveInternal(contentItem, content => @@ -1068,7 +1068,7 @@ namespace Umbraco.Web.Editors var contentService = Services.ContentService; // Save content with new sort order and update content xml in db accordingly - if (contentService.Sort(sorted.IdSortOrder) == false) + if (contentService.Sort(sorted.IdSortOrder, Security.CurrentUser.Id) == false) { Logger.Warn("Content sorting failed, this was probably caused by an event being cancelled"); return Request.CreateValidationErrorResponse("Content sorting failed, this was probably caused by an event being cancelled"); diff --git a/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/DatabaseSchemaValidationHealthCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/DatabaseSchemaValidationHealthCheck.cs deleted file mode 100644 index d3c60d4b59..0000000000 --- a/src/Umbraco.Web/HealthCheck/Checks/DataIntegrity/DatabaseSchemaValidationHealthCheck.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Collections.Generic; -using Umbraco.Core.Logging; -using Umbraco.Core.Migrations.Install; -using Umbraco.Core.Services; - -namespace Umbraco.Web.HealthCheck.Checks.DataIntegrity -{ - /// - /// U4-9544 Health check to detect if the database has any missing indexes or constraints - /// - [HealthCheck( - "0873D589-2064-4EA3-A152-C43417FE00A4", - "Database Schema Validation", - Description = "This checks the Umbraco database by doing a comparison of current indexes and schema items with the current state of the database and returns any problems it found. Useful to detect if the database hasn't been upgraded correctly.", - Group = "Data Integrity")] - public class DatabaseSchemaValidationHealthCheck : HealthCheck - { - private readonly DatabaseBuilder _databaseBuilder; - private readonly ILocalizedTextService _textService; - private readonly ILogger _logger; - - public DatabaseSchemaValidationHealthCheck(DatabaseBuilder databaseBuilder, ILocalizedTextService textService, ILogger logger) - { - _databaseBuilder = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder)); - _textService = textService ?? throw new ArgumentNullException(nameof(textService)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } - - public override HealthCheckStatus ExecuteAction(HealthCheckAction action) - { - return CheckDatabase(); - } - - public override IEnumerable GetStatus() - { - //return the statuses - return new[] { CheckDatabase() }; - } - - private HealthCheckStatus CheckDatabase() - { - var results = _databaseBuilder.ValidateDatabaseSchema(); - - _logger.Warn(_textService.Localize("databaseSchemaValidationCheckDatabaseLogMessage")); - - foreach(var error in results.Errors) - { - _logger.Warn("{Error} : {ErrorDetail}", error.Item1, error.Item2); - } - - if(results.Errors.Count > 0) - { - return new HealthCheckStatus(_textService.Localize("healthcheck/databaseSchemaValidationCheckDatabaseErrors", new[] { results.Errors.Count.ToString() })) - { - ResultType = StatusResultType.Error, - View = "Umbraco.Dashboard.DatabaseSchemaValidationController" - }; - } - - return new HealthCheckStatus(_textService.Localize("healthcheck/databaseSchemaValidationCheckDatabaseOk")) - { - ResultType = StatusResultType.Success - }; - } - } -} diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentDomainsAndCulture.cs b/src/Umbraco.Web/Models/ContentEditing/ContentDomainsAndCulture.cs index 9f0750cb7c..45c6313d91 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentDomainsAndCulture.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentDomainsAndCulture.cs @@ -1,11 +1,15 @@ using System.Collections.Generic; +using System.Runtime.Serialization; namespace Umbraco.Web.Models.ContentEditing { + [DataContract(Name = "ContentDomainsAndCulture")] public class ContentDomainsAndCulture { + [DataMember(Name = "domains")] public IEnumerable Domains { get; set; } + [DataMember(Name = "language")] public string Language { get; internal set; } } } diff --git a/src/Umbraco.Web/Models/ContentEditing/DomainDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/DomainDisplay.cs index a6f7e499e4..ea3ea509c9 100644 --- a/src/Umbraco.Web/Models/ContentEditing/DomainDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/DomainDisplay.cs @@ -1,16 +1,26 @@ -namespace Umbraco.Web.Models.ContentEditing +using System.Runtime.Serialization; + +namespace Umbraco.Web.Models.ContentEditing { + [DataContract(Name = "DomainDisplay")] public class DomainDisplay - { + { public DomainDisplay(string name, int lang) { Name = name; Lang = lang; } + [DataMember(Name = "name")] public string Name { get; } + + [DataMember(Name = "lang")] public int Lang { get; } + + [DataMember(Name = "duplicate")] public bool Duplicate { get; set; } + + [DataMember(Name = "other")] public string Other { get; set; } } } diff --git a/src/Umbraco.Web/Models/ContentEditing/DomainSave.cs b/src/Umbraco.Web/Models/ContentEditing/DomainSave.cs index 3ad19cfd60..6853762af3 100644 --- a/src/Umbraco.Web/Models/ContentEditing/DomainSave.cs +++ b/src/Umbraco.Web/Models/ContentEditing/DomainSave.cs @@ -1,10 +1,20 @@ -namespace Umbraco.Web.Models.ContentEditing +using System.Runtime.Serialization; + +namespace Umbraco.Web.Models.ContentEditing { + [DataContract(Name = "DomainSave")] public class DomainSave { + [DataMember(Name = "valid")] public bool Valid { get; set; } + + [DataMember(Name = "nodeId")] public int NodeId { get; set; } + + [DataMember(Name = "language")] public int Language { get; set; } + + [DataMember(Name = "domains")] public DomainDisplay[] Domains { get; set; } } } diff --git a/src/Umbraco.Web/Models/ContentEditing/Tab.cs b/src/Umbraco.Web/Models/ContentEditing/Tab.cs index c83f293f08..758317606c 100644 --- a/src/Umbraco.Web/Models/ContentEditing/Tab.cs +++ b/src/Umbraco.Web/Models/ContentEditing/Tab.cs @@ -21,6 +21,12 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "alias")] public string Alias { get; set; } + /// + /// The expanded state of the tab + /// + [DataMember(Name = "open")] + public bool Expanded { get; set; } = true; + [DataMember(Name = "properties")] public IEnumerable Properties { get; set; } } diff --git a/src/Umbraco.Web/Models/ImageCropMode.cs b/src/Umbraco.Web/Models/ImageCropMode.cs index e36f079c02..03fe6676cb 100644 --- a/src/Umbraco.Web/Models/ImageCropMode.cs +++ b/src/Umbraco.Web/Models/ImageCropMode.cs @@ -2,11 +2,34 @@ namespace Umbraco.Web.Models { public enum ImageCropMode { + /// + /// Resizes the image to the given dimensions. If the set dimensions do not match the aspect ratio of the original image then the output is cropped to match the new aspect ratio. + /// Crop, + + /// + /// Resizes the image to the given dimensions. If the set dimensions do not match the aspect ratio of the original image then the output is resized to the maximum possible value in each direction while aintaining the original aspect ratio. + /// Max, + + /// + /// Resizes the image to the given dimensions. If the set dimensions do not match the aspect ratio of the original image then the output is stretched to match the new aspect ratio. + /// Stretch, + + /// + /// Passing a single dimension will automatically preserve the aspect ratio of the original image. If the requested aspect ratio is different then the image will be padded to fit. + /// Pad, + + /// + /// When upscaling an image the image pixels themselves are not resized, rather the image is padded to fit the given dimensions. + /// BoxPad, + + /// + /// Resizes the image until the shortest side reaches the set given dimension. This will maintain the aspect ratio of the original image. Upscaling is disabled in this mode and the original image will be returned if attempted. + /// Min } } diff --git a/src/Umbraco.Web/Models/Mapping/ContentPropertyMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/ContentPropertyMapperProfile.cs index b249760053..0b086afb2d 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentPropertyMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentPropertyMapperProfile.cs @@ -24,7 +24,8 @@ namespace Umbraco.Web.Models.Mapping .ForMember(tab => tab.Label, expression => expression.MapFrom(@group => @group.Name)) .ForMember(tab => tab.IsActive, expression => expression.UseValue(true)) .ForMember(tab => tab.Properties, expression => expression.Ignore()) - .ForMember(tab => tab.Alias, expression => expression.Ignore()); + .ForMember(tab => tab.Alias, expression => expression.Ignore()) + .ForMember(tab => tab.Expanded, expression => expression.Ignore()); //FROM Property TO ContentPropertyBasic CreateMap().ConvertUsing(contentPropertyBasicConverter); diff --git a/src/Umbraco.Web/Models/Mapping/MemberMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/MemberMapperProfile.cs index 0cfa3cf154..a524aa158c 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberMapperProfile.cs @@ -34,7 +34,7 @@ namespace Umbraco.Web.Models.Mapping //FROM MembershipUser TO IMember - used when using a non-umbraco membership provider CreateMap() .ConstructUsing(src => MemberService.CreateGenericMembershipProviderMember(src.UserName, src.Email, src.UserName, "")) - //we're giving this entity an ID of 0 - we cannot really map it but it needs an id so the system knows it's not a new entity + //we're giving this entity an ID of int.MaxValue - TODO: SD: I can't remember why this mapping is here? .ForMember(dest => dest.Id, opt => opt.MapFrom(src => int.MaxValue)) .ForMember(dest => dest.Comments, opt => opt.MapFrom(src => src.Comment)) .ForMember(dest => dest.CreateDate, opt => opt.MapFrom(src => src.CreationDate)) @@ -84,6 +84,8 @@ namespace Umbraco.Web.Models.Mapping //FROM IMember TO MemberBasic CreateMap() + //we're giving this entity an ID of int.MaxValue - this is kind of a hack to force angular to use the Key instead of the Id in list views + .ForMember(dest => dest.Id, opt => opt.MapFrom(src => int.MaxValue)) .ForMember(dest => dest.Udi, opt => opt.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key))) .ForMember(dest => dest.Owner, opt => opt.ResolveUsing(src => memberOwnerResolver.Resolve(src))) .ForMember(dest => dest.Icon, opt => opt.MapFrom(src => src.ContentType.Icon)) @@ -99,7 +101,7 @@ namespace Umbraco.Web.Models.Mapping //FROM MembershipUser TO MemberBasic CreateMap() - //we're giving this entity an ID of 0 - we cannot really map it but it needs an id so the system knows it's not a new entity + //we're giving this entity an ID of int.MaxValue - TODO: SD: I can't remember why this mapping is here? .ForMember(dest => dest.Id, opt => opt.MapFrom(src => int.MaxValue)) .ForMember(dest => dest.Udi, opt => opt.Ignore()) .ForMember(dest => dest.CreateDate, opt => opt.MapFrom(src => src.CreationDate)) @@ -142,8 +144,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dest => dest.Icon, opt => opt.Ignore()) .ForMember(dest => dest.Trashed, opt => opt.Ignore()) .ForMember(dest => dest.ParentId, opt => opt.Ignore()) - .ForMember(dest => dest.Alias, opt => opt.Ignore()) - .ForMember(dest => dest.Path, opt => opt.Ignore()); + .ForMember(dest => dest.Alias, opt => opt.Ignore()); } } } diff --git a/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesResolver.cs b/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesResolver.cs index 9f6747ea95..0e4b902196 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberTabsAndPropertiesResolver.cs @@ -71,7 +71,7 @@ namespace Umbraco.Web.Models.Mapping } else { - var umbracoProvider = (IUmbracoMemberTypeMembershipProvider) provider; + var umbracoProvider = (IUmbracoMemberTypeMembershipProvider)provider; //This is kind of a hack because a developer is supposed to be allowed to set their property editor - would have been much easier // if we just had all of the membeship provider fields on the member table :( @@ -112,11 +112,18 @@ namespace Umbraco.Web.Models.Mapping protected override IEnumerable GetCustomGenericProperties(IContentBase content) { - var member = (IMember) content; + var member = (IMember)content; var membersProvider = Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider(); var genericProperties = new List { + new ContentPropertyDisplay + { + Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}id", + Label = _localizedTextService.Localize("general/id"), + Value = new List {member.Id.ToString(), member.Key.ToString()}, + View = "idwithguid" + }, new ContentPropertyDisplay { Alias = $"{Constants.PropertyEditors.InternalGenericPropertiesPrefix}doctype", diff --git a/src/Umbraco.Web/Models/Trees/TreeNodeExtensions.cs b/src/Umbraco.Web/Models/Trees/TreeNodeExtensions.cs index 9f8ca9b84d..819d74f8e7 100644 --- a/src/Umbraco.Web/Models/Trees/TreeNodeExtensions.cs +++ b/src/Umbraco.Web/Models/Trees/TreeNodeExtensions.cs @@ -15,7 +15,7 @@ } /// - /// Sets the node style to show that it is currently protected publicly + /// Sets the node style to show that it is a container type /// /// public static void SetContainerStyle(this TreeNode treeNode) diff --git a/src/Umbraco.Web/PropertyEditors/ColorPickerConfigurationEditor.cs b/src/Umbraco.Web/PropertyEditors/ColorPickerConfigurationEditor.cs index cbd4e69a9e..a4d894c551 100644 --- a/src/Umbraco.Web/PropertyEditors/ColorPickerConfigurationEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ColorPickerConfigurationEditor.cs @@ -105,7 +105,11 @@ namespace Umbraco.Web.PropertyEditors // handle useLabel if (editorValues.TryGetValue("useLabel", out var useLabelObj)) - output.UseLabel = useLabelObj.TryConvertTo(); + { + var convertBool = useLabelObj.TryConvertTo(); + if (convertBool.Success) + output.UseLabel = convertBool.Result; + } // auto-assigning our ids, get next id from existing values var nextId = 1; @@ -125,13 +129,8 @@ namespace Umbraco.Web.PropertyEditors var id = item.Property("id")?.Value?.Value() ?? 0; if (id >= nextId) nextId = id + 1; - // if using a label, replace color by json blob - // (a pity we have to serialize here!) - if (output.UseLabel) - { - var label = item.Property("label")?.Value?.Value(); - value = JsonConvert.SerializeObject(new { value, label }); - } + var label = item.Property("label")?.Value?.Value(); + value = JsonConvert.SerializeObject(new { value, label }); output.Items.Add(new ValueListConfiguration.ValueListItem { Id = id, Value = value }); } diff --git a/src/Umbraco.Web/PropertyEditors/DropDownFlexibleConfigurationEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownFlexibleConfigurationEditor.cs index 5821823576..dbdedebd0a 100644 --- a/src/Umbraco.Web/PropertyEditors/DropDownFlexibleConfigurationEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DropDownFlexibleConfigurationEditor.cs @@ -27,7 +27,13 @@ namespace Umbraco.Web.PropertyEditors // handle multiple if (editorValues.TryGetValue("multiple", out var multipleObj)) - output.Multiple = multipleObj.TryConvertTo(); + { + var convertBool = multipleObj.TryConvertTo(); + if (convertBool.Success) + { + output.Multiple = convertBool.Result; + } + } // auto-assigning our ids, get next id from existing values var nextId = 1; @@ -56,7 +62,10 @@ namespace Umbraco.Web.PropertyEditors public override Dictionary ToConfigurationEditor(DropDownFlexibleConfiguration configuration) { - var items = configuration?.Items.ToDictionary(x => x.Id.ToString(), x => x.Value) ?? new object(); + // map to what the editor expects + var i = 1; + var items = configuration?.Items.ToDictionary(x => x.Id.ToString(), x => new { value = x.Value, sortOrder = i++ }) ?? new object(); + var multiple = configuration?.Multiple ?? false; return new Dictionary diff --git a/src/Umbraco.Web/PropertyEditors/EmailAddressPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/EmailAddressPropertyEditor.cs index 89c3dbf0e0..d55d3327e1 100644 --- a/src/Umbraco.Web/PropertyEditors/EmailAddressPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/EmailAddressPropertyEditor.cs @@ -5,7 +5,7 @@ using Umbraco.Core.PropertyEditors.Validators; namespace Umbraco.Web.PropertyEditors { - [DataEditor(Constants.PropertyEditors.Aliases.EmailAddress, "Email address", "email", Icon="icon-message")] + [DataEditor(Constants.PropertyEditors.Aliases.EmailAddress, EditorType.PropertyValue | EditorType.MacroParameter, "Email address", "email", Icon="icon-message")] public class EmailAddressPropertyEditor : DataEditor { /// diff --git a/src/Umbraco.Web/PropertyEditors/TrueFalseConfiguration.cs b/src/Umbraco.Web/PropertyEditors/TrueFalseConfiguration.cs index 2dfbf9b0b6..6d962c42f1 100644 --- a/src/Umbraco.Web/PropertyEditors/TrueFalseConfiguration.cs +++ b/src/Umbraco.Web/PropertyEditors/TrueFalseConfiguration.cs @@ -9,5 +9,8 @@ namespace Umbraco.Web.PropertyEditors { [ConfigurationField("default", "Default Value", "boolean")] public string Default { get; set; } // fixme - well, true or false?! + + [ConfigurationField("labelOn", "Write a label text", "textstring")] + public string Label { get; set; } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web/PropertyEditors/TrueFalsePropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/TrueFalsePropertyEditor.cs index be2bbb66c1..ccd3bee744 100644 --- a/src/Umbraco.Web/PropertyEditors/TrueFalsePropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/TrueFalsePropertyEditor.cs @@ -19,5 +19,6 @@ namespace Umbraco.Web.PropertyEditors /// protected override IConfigurationEditor CreateConfigurationEditor() => new TrueFalseConfigurationEditor(); + } } diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs index 4266edecf1..3c143a6066 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/XmlPublishedContent.cs @@ -34,6 +34,8 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache private readonly ICacheProvider _cacheProvider; // at snapshot/request level (see PublishedContentCache) private readonly PublishedContentTypeCache _contentTypeCache; + private readonly object _initializeLock = new object(); + private bool _nodeInitialized; private bool _parentInitialized; private bool _childrenInitialized; @@ -66,15 +68,14 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); - if (_childrenInitialized == false) InitializeChildren(); + EnsureNodeInitialized(andChildren: true); return _children; } } public override IPublishedProperty GetProperty(string alias) { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); IPublishedProperty property; return _properties.TryGetValue(alias, out property) ? property : null; } @@ -85,8 +86,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); - if (_parentInitialized == false) InitializeParent(); + EnsureNodeInitialized(andParent: true); return _parent; } } @@ -95,7 +95,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _id; } } @@ -104,7 +104,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _key; } } @@ -113,7 +113,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _template; } } @@ -122,7 +122,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _sortOrder; } } @@ -131,7 +131,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _name; } } @@ -144,7 +144,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _writerName; } } @@ -153,7 +153,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _creatorName; } } @@ -162,7 +162,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _writerId; } } @@ -171,7 +171,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _creatorId; } } @@ -180,7 +180,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _path; } } @@ -189,7 +189,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _createDate; } } @@ -198,7 +198,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _updateDate; } } @@ -207,7 +207,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _urlName; } } @@ -216,7 +216,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _level; } } @@ -225,7 +225,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _isDraft; } } @@ -234,7 +234,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _properties.Values; } } @@ -243,7 +243,7 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache { get { - if (_nodeInitialized == false) InitializeNode(); + EnsureNodeInitialized(); return _contentType; } } @@ -256,10 +256,27 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache if (parent.Attributes?.GetNamedItem("isDoc") != null) _parent = Get(parent, _isPreviewing, _cacheProvider, _contentTypeCache); - // warn: this is not thread-safe... _parentInitialized = true; } + private void EnsureNodeInitialized(bool andChildren = false, bool andParent = false) + { + // In *theory* XmlPublishedContent are a per-request thing, and so should not + // end up being involved into multi-threaded situations - however, it's been + // reported that some users ended up seeing 100% CPU due to infinite loops in + // the properties dictionary in InitializeNode, which would indicate that the + // dictionary *is* indeed involved in some multi-threaded operation. No idea + // what users are doing that cause this, but let's be friendly and use a true + // lock around initialization. + + lock (_initializeLock) + { + if (_nodeInitialized == false) InitializeNode(); + if (andChildren && _childrenInitialized == false) InitializeChildren(); + if (andParent && _parentInitialized == false) InitializeParent(); + } + } + private void InitializeNode() { InitializeNode(this, _xmlNode, _isPreviewing, @@ -268,10 +285,10 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache out _createDate, out _updateDate, out _level, out _isDraft, out _contentType, out _properties, _contentTypeCache.Get); - // warn: this is not thread-safe... _nodeInitialized = true; } + // internal for some benchmarks internal static void InitializeNode(XmlPublishedContent node, XmlNode xmlNode, bool isPreviewing, out int id, out Guid key, out int template, out int sortOrder, out string name, out string writerName, out string urlName, out string creatorName, out int creatorId, out int writerId, out string docTypeAlias, out int docTypeId, out string path, @@ -398,7 +415,6 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache .OrderBy(x => x.SortOrder) .ToList(); - // warn: this is not thread-safe _childrenInitialized = true; } diff --git a/src/Umbraco.Web/Routing/ContentFinderByUrlAlias.cs b/src/Umbraco.Web/Routing/ContentFinderByUrlAlias.cs index bbf3ee1283..4979a59d45 100644 --- a/src/Umbraco.Web/Routing/ContentFinderByUrlAlias.cs +++ b/src/Umbraco.Web/Routing/ContentFinderByUrlAlias.cs @@ -93,7 +93,7 @@ namespace Umbraco.Web.Routing } if (string.IsNullOrWhiteSpace(v)) return false; v = "," + v.Replace(" ", "") + ","; - return v.Contains(a1) || v.Contains(a2); + return v.InvariantContains(a1) || v.InvariantContains(a2); } // fixme - even with Linq, what happens below has to be horribly slow diff --git a/src/Umbraco.Web/Services/ApplicationTreeService.cs b/src/Umbraco.Web/Services/ApplicationTreeService.cs index 08a17187e7..f13c0547b6 100644 --- a/src/Umbraco.Web/Services/ApplicationTreeService.cs +++ b/src/Umbraco.Web/Services/ApplicationTreeService.cs @@ -21,15 +21,16 @@ namespace Umbraco.Web.Services private readonly ILogger _logger; private readonly CacheHelper _cache; private Lazy> _allAvailableTrees; - private IEnumerable _treeTypes; internal const string TreeConfigFileName = "trees.config"; private static string _treeConfig; private static readonly object Locker = new object(); + private readonly Lazy>> _groupedTrees; public ApplicationTreeService(ILogger logger, CacheHelper cache) { _logger = logger; _cache = cache; + _groupedTrees = new Lazy>>(InitGroupedTrees); } /// @@ -252,11 +253,6 @@ namespace Umbraco.Web.Services return GetAppTrees().OrderBy(x => x.SortOrder); } - public IEnumerable GetAllTypes() - { - return _treeTypes ?? (_treeTypes = GetAll().Select(x => x.GetRuntimeType())); - } - /// /// Gets the application tree for the applcation with the specified alias /// @@ -287,6 +283,46 @@ namespace Umbraco.Web.Services return list.OrderBy(x => x.SortOrder).ToArray(); } + public IDictionary> GetGroupedApplicationTrees(string applicationAlias, bool onlyInitialized) + { + var result = new Dictionary>(); + var foundTrees = GetApplicationTrees(applicationAlias, onlyInitialized); + foreach(var treeGroup in _groupedTrees.Value) + { + List resultGroup = null; + foreach(var tree in foundTrees) + { + foreach(var treeAliasInGroup in treeGroup) + { + if (tree.Alias == treeAliasInGroup) + { + if (resultGroup == null) resultGroup = new List(); + resultGroup.Add(tree); + } + } + } + if (resultGroup != null) + result[treeGroup.Key ?? string.Empty] = resultGroup; //key cannot be null so make empty string + } + return result; + } + + /// + /// Creates a group of all tree groups and their tree aliases + /// + /// + /// + /// Used to initialize the field + /// + private IReadOnlyCollection> InitGroupedTrees() + { + var result = GetAll() + .Select(x => (treeAlias: x.Alias, treeGroup: x.GetRuntimeType().GetCustomAttribute(false)?.TreeGroup)) + .GroupBy(x => x.treeGroup, x => x.treeAlias) + .ToList(); + return result; + } + /// /// Loads in the xml structure from disk if one is found, otherwise loads in an empty xml structure, calls the /// callback with the xml document and saves the structure back to disk if saveAfterCallback is true. diff --git a/src/Umbraco.Web/Templates/TemplateUtilities.cs b/src/Umbraco.Web/Templates/TemplateUtilities.cs index 9c13429b44..91548e44f1 100644 --- a/src/Umbraco.Web/Templates/TemplateUtilities.cs +++ b/src/Umbraco.Web/Templates/TemplateUtilities.cs @@ -1,6 +1,4 @@ -using HtmlAgilityPack; -using System; -using System.Runtime.CompilerServices; +using System; using System.Text.RegularExpressions; using Umbraco.Core; using Umbraco.Core.Configuration; @@ -38,11 +36,6 @@ namespace Umbraco.Web.Templates { if (urlProvider == null) throw new ArgumentNullException("urlProvider"); - if(string.IsNullOrEmpty(text)) - { - return text; - } - // Parse internal links var tags = LocalLinkPattern.Matches(text); foreach (Match tag in tags) @@ -71,11 +64,6 @@ namespace Umbraco.Web.Templates } } - if (UmbracoConfig.For.UmbracoSettings().Content.StripUdiAttributes) - { - text = StripUdiDataAttributes(text); - } - return text; } @@ -87,9 +75,6 @@ namespace Umbraco.Web.Templates private static readonly Regex ResolveUrlPattern = new Regex("(=[\"\']?)(\\W?\\~(?:.(?![\"\']?\\s+(?:\\S+)=|[>\"\']))+.)[\"\']?", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - private static readonly Regex UdiDataAttributePattern = new Regex("data-udi=\"[^\\\"]*\"", - RegexOptions.IgnoreCase | RegexOptions.Compiled); - /// /// The RegEx matches any HTML attribute values that start with a tilde (~), those that match are passed to ResolveUrl to replace the tilde with the application path. /// @@ -133,21 +118,5 @@ namespace Umbraco.Web.Templates { return text.CleanForXss(ignoreFromClean); } - - /// - /// Strips data-udi attributes from rich text - /// - /// A html string - /// A string stripped from the data-uid attributes - public static string StripUdiDataAttributes(string input) - { - if (string.IsNullOrEmpty(input)) - { - return string.Empty; - } - - - return UdiDataAttributePattern.Replace(input, string.Empty); - } } } diff --git a/src/Umbraco.Web/Trees/ApplicationTreeController.cs b/src/Umbraco.Web/Trees/ApplicationTreeController.cs index fd669a1b07..273a7afb37 100644 --- a/src/Umbraco.Web/Trees/ApplicationTreeController.cs +++ b/src/Umbraco.Web/Trees/ApplicationTreeController.cs @@ -21,20 +21,7 @@ namespace Umbraco.Web.Trees [AngularJsonOnlyConfiguration] [PluginController("UmbracoTrees")] public class ApplicationTreeController : UmbracoAuthorizedApiController - { - /// - /// Fetches all registered trees and groups them together if they have a [CoreTree] - /// Attribute with a 'TreeGroup' property set - /// This allows the settings section trees to be grouped by Settings, Templating & Other - /// - private static readonly Lazy>> CoreTrees - = new Lazy>>(() => - Current.Services.ApplicationTreeService.GetAllTypes() - .Select(x => (TreeType: x, TreeGroup: x.GetCustomAttribute(false)?.TreeGroup)) - .GroupBy(x => x.TreeGroup) - .ToList()); - - + { /// /// Returns the tree nodes for an application /// @@ -51,13 +38,14 @@ namespace Umbraco.Web.Trees if (string.IsNullOrEmpty(application)) throw new HttpResponseException(HttpStatusCode.NotFound); //find all tree definitions that have the current application alias - var appTrees = Services.ApplicationTreeService.GetApplicationTrees(application, onlyInitialized).ToArray(); + var groupedTrees = Services.ApplicationTreeService.GetGroupedApplicationTrees(application, onlyInitialized); + var allTrees = groupedTrees.Values.SelectMany(x => x).ToList(); - if (string.IsNullOrEmpty(tree) == false || appTrees.Length <= 1) + if (string.IsNullOrEmpty(tree) == false || allTrees.Count <= 1) { - var apptree = string.IsNullOrEmpty(tree) == false - ? appTrees.SingleOrDefault(x => x.Alias == tree) - : appTrees.SingleOrDefault(); + var apptree = !tree.IsNullOrWhiteSpace() + ? allTrees.FirstOrDefault(x => x.Alias == tree) + : allTrees.FirstOrDefault(); if (apptree == null) throw new HttpResponseException(HttpStatusCode.NotFound); @@ -74,22 +62,22 @@ namespace Umbraco.Web.Trees } } - var collection = new TreeNodeCollection(); - foreach (var apptree in appTrees) - { - //return the root nodes for each tree in the app - var rootNode = await GetRootForMultipleAppTree(apptree, queryStrings); - //This could be null if the tree decides not to return it's root (i.e. the member type tree does this when not in umbraco membership mode) - if (rootNode != null) - { - collection.Add(rootNode); - } - } - //Don't apply fancy grouping logic futher down, if we only have one group of items - var hasGroups = CoreTrees.Value.Count > 0; + var hasGroups = groupedTrees.Count > 1; if (!hasGroups) { + var collection = new TreeNodeCollection(); + foreach (var apptree in allTrees) + { + //return the root nodes for each tree in the app + var rootNode = await GetRootForMultipleAppTree(apptree, queryStrings); + //This could be null if the tree decides not to return it's root (i.e. the member type tree does this when not in umbraco membership mode) + if (rootNode != null) + { + collection.Add(rootNode); + } + } + var multiTree = TreeRootNode.CreateMultiTreeRoot(collection); multiTree.Name = Services.TextService.Localize("sections/" + application); @@ -99,32 +87,23 @@ namespace Umbraco.Web.Trees var rootNodeGroups = new List(); //Group trees by [CoreTree] attribute with a TreeGroup property - foreach (var treeSectionGroup in CoreTrees.Value) + foreach (var treeSectionGroup in groupedTrees) { var treeGroupName = treeSectionGroup.Key; var groupNodeCollection = new TreeNodeCollection(); - foreach (var treeItem in treeSectionGroup) + foreach (var appTree in treeSectionGroup.Value) { - //Item1 tuple - is the type from all tree types - var treeItemType = treeItem.Item1; - - var findAppTree = appTrees.FirstOrDefault(x => x.GetRuntimeType() == treeItemType); - if (findAppTree != null) + var rootNode = await GetRootForMultipleAppTree(appTree, queryStrings); + if (rootNode != null) { - //Now we need to get the 'TreeNode' which is in 'collection' - var treeItemNode = collection.FirstOrDefault(x => x.AdditionalData["treeAlias"].ToString() == findAppTree.Alias); - - if (treeItemNode != null) - { - //Add to a new list/collection - groupNodeCollection.Add(treeItemNode); - } + //Add to a new list/collection + groupNodeCollection.Add(rootNode); } } //If treeGroupName == null then its third party - if (treeGroupName == null) + if (treeGroupName.IsNullOrWhiteSpace()) { //This is used for the localisation key //treeHeaders/thirdPartyGroup diff --git a/src/Umbraco.Web/Trees/ContentTreeController.cs b/src/Umbraco.Web/Trees/ContentTreeController.cs index d04bb1c83b..4a0589cce4 100644 --- a/src/Umbraco.Web/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTreeController.cs @@ -92,6 +92,7 @@ namespace Umbraco.Web.Trees } } + node.AdditionalData.Add("variesByCulture", documentEntity.Variations.VariesByCulture()); node.AdditionalData.Add("contentType", documentEntity.ContentTypeAlias); } diff --git a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs index d1a3cddd52..a2179be75f 100644 --- a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs @@ -116,21 +116,11 @@ namespace Umbraco.Web.Trees if (enableInheritedDocumentTypes) { menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias))); - - //no move action if this is a child doc type - if (parent == null) - { - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionMove.Instance.Alias)), true); - } } - else + //no move action if this is a child doc type + if (parent == null) { - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionMove.Instance.Alias))); - //no move action if this is a child doc type - if (parent == null) - { - menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionMove.Instance.Alias)), true); - } + menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionMove.Instance.Alias)), true); } menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionCopy.Instance.Alias))); menu.Items.Add(Services.TextService.Localize(string.Format("actions/{0}", ActionExport.Instance.Alias)), true); diff --git a/src/Umbraco.Web/Trees/MacrosTreeController.cs b/src/Umbraco.Web/Trees/MacrosTreeController.cs index 5d0a4f6315..6a612ba8fb 100644 --- a/src/Umbraco.Web/Trees/MacrosTreeController.cs +++ b/src/Umbraco.Web/Trees/MacrosTreeController.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Net.Http.Formatting; using Umbraco.Core; using Umbraco.Core.Models; diff --git a/src/Umbraco.Web/UI/Controls/ProgressBar.cs b/src/Umbraco.Web/UI/Controls/ProgressBar.cs index 0c97e96644..a40509cfb8 100644 --- a/src/Umbraco.Web/UI/Controls/ProgressBar.cs +++ b/src/Umbraco.Web/UI/Controls/ProgressBar.cs @@ -9,7 +9,7 @@ namespace Umbraco.Web.UI.Controls protected override void Render(System.Web.UI.HtmlTextWriter writer) { // fixme - image is gone! - base.ImageUrl = SystemDirectories.UmbracoClient + "/images/progressBar.gif"; + base.ImageUrl = "/images/progressBar.gif"; base.AlternateText = Title; base.Render(writer); diff --git a/src/Umbraco.Web/UI/JavaScript/UmbracoClientDependencyLoader.cs b/src/Umbraco.Web/UI/JavaScript/UmbracoClientDependencyLoader.cs index 7b8397d047..dc3a2efbc7 100644 --- a/src/Umbraco.Web/UI/JavaScript/UmbracoClientDependencyLoader.cs +++ b/src/Umbraco.Web/UI/JavaScript/UmbracoClientDependencyLoader.cs @@ -17,7 +17,6 @@ namespace Umbraco.Web.UI.JavaScript public UmbracoClientDependencyLoader() : base() { - this.AddPath("UmbracoClient", IOHelper.ResolveUrl(SystemDirectories.UmbracoClient)); this.AddPath("UmbracoRoot", IOHelper.ResolveUrl(SystemDirectories.Umbraco)); this.ProviderName = LoaderControlProvider.DefaultName; diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 6b4273e829..656bbd29c5 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -180,6 +180,7 @@ + @@ -201,7 +202,6 @@ - @@ -1248,9 +1248,7 @@ - - FeedProxy.aspx ASPXCodeBehind diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index 91cd388317..aa30fff0ec 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -916,7 +916,7 @@ namespace Umbraco.Web } /// - /// Will take the first non-null value in the collection and return the value of it. + /// Joins any number of int/string/objects into one string /// public string Concatenate(params object[] args) { diff --git a/src/Umbraco.Web/_Legacy/Controls/Splitter.cs b/src/Umbraco.Web/_Legacy/Controls/Splitter.cs index 6e418bbf01..df6ade91bc 100644 --- a/src/Umbraco.Web/_Legacy/Controls/Splitter.cs +++ b/src/Umbraco.Web/_Legacy/Controls/Splitter.cs @@ -10,7 +10,7 @@ namespace Umbraco.Web._Legacy.Controls this.Height = System.Web.UI.WebControls.Unit.Pixel(21); this.Style.Add("border", "0px"); this.Attributes.Add("class", "editorIconSplit"); - this.ImageUrl = SystemDirectories.UmbracoClient + "/menuicon/images/split.gif"; + this.ImageUrl = "/menuicon/images/split.gif"; } } } diff --git a/src/Umbraco.Web/_Legacy/Packager/Installer.cs b/src/Umbraco.Web/_Legacy/Packager/Installer.cs index ae6b3e0a11..020e34d4ce 100644 --- a/src/Umbraco.Web/_Legacy/Packager/Installer.cs +++ b/src/Umbraco.Web/_Legacy/Packager/Installer.cs @@ -717,7 +717,6 @@ namespace umbraco.cms.businesslogic.packager { //this is experimental and undocumented... path = path.Replace("[$UMBRACO]", SystemDirectories.Umbraco); - path = path.Replace("[$UMBRACOCLIENT]", SystemDirectories.UmbracoClient); path = path.Replace("[$CONFIG]", SystemDirectories.Config); path = path.Replace("[$DATA]", SystemDirectories.Data); } diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/dualSelectBox.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/dualSelectBox.cs index 121e290830..6e109b3327 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/controls/dualSelectBox.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/controls/dualSelectBox.cs @@ -45,6 +45,15 @@ namespace umbraco.controls } } + public new int Height + { + set + { + _possibleValues.Height = new Unit(value); + _selectedValues.Height = new Unit(value); + } + } + protected override void CreateChildControls() { _possibleValues.ID = "posVals"; diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/MemberGroupTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/MemberGroupTasks.cs deleted file mode 100644 index 2a603544bf..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/MemberGroupTasks.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Linq; -using System.Web.Security; -using Umbraco.Core; -using Umbraco.Web; -using Umbraco.Web.Composing; -using Umbraco.Web._Legacy.UI; - -namespace umbraco -{ - public class MemberGroupTasks : LegacyDialogTask - { - public override bool PerformSave() - { - Roles.CreateRole(Alias); - _returnUrl = $"members/EditMemberGroup.aspx?id={System.Web.HttpContext.Current.Server.UrlEncode(Alias)}"; - return true; - } - - public override bool PerformDelete() - { - var roleDeleted = false; - - // only built-in roles can be deleted - if (Roles.Provider.Name == Constants.Conventions.Member.UmbracoRoleProviderName) - { - var group = Current.Services.MemberGroupService.GetByName(Alias); - if (group != null) - { - Current.Services.MemberGroupService.Delete(group); - } - } - - // Need to delete the member group from any content item that has it assigned in public access settings - var publicAccessService = Current.Services.PublicAccessService; - var allPublicAccessRules = publicAccessService.GetAll(); - - // Find only rules which have the current role name (alias) assigned to them - var rulesWithDeletedRoles = allPublicAccessRules.Where(x => x.Rules.Any(r => r.RuleValue == Alias)); - - var contentService = Current.Services.ContentService; - foreach (var publicAccessEntry in rulesWithDeletedRoles) - { - var contentItem = contentService.GetById(publicAccessEntry.ProtectedNodeId); - var rulesToDelete = publicAccessEntry.Rules.ToList(); - foreach (var rule in rulesToDelete) - publicAccessService.RemoveRule(contentItem, rule.RuleType, rule.RuleValue); - } - - return roleDeleted; - } - - private string _returnUrl = ""; - - public override string ReturnUrl => _returnUrl; - - public override string AssignedApp => Constants.Applications.Members.ToString(); - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/dictionaryTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/dictionaryTasks.cs deleted file mode 100644 index 17bfde7fb3..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/dictionaryTasks.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using Umbraco.Core.Logging; -using Umbraco.Web.UI; -using Umbraco.Core; -using Umbraco.Web; -using Umbraco.Web.Composing; -using Umbraco.Web._Legacy.UI; - -namespace umbraco -{ - public class dictionaryTasks : LegacyDialogTask - { - public override bool PerformSave() - { - //check to see if key is already there - if (Current.Services.LocalizationService.DictionaryItemExists(Alias)) - return false; - - // Create new dictionary item if name no already exist - if (ParentID > 0) - { - var di = Current.Services.LocalizationService.GetDictionaryItemById(ParentID); - if (di == null) throw new NullReferenceException("No dictionary item found by id " + ParentID); - var item = Current.Services.LocalizationService.CreateDictionaryItemWithIdentity(Alias, di.Key); - _returnUrl = string.Format("settings/editDictionaryItem.aspx?id={0}", item.Id); - } - else - { - var item = Current.Services.LocalizationService.CreateDictionaryItemWithIdentity(Alias, null); - _returnUrl = string.Format("settings/editDictionaryItem.aspx?id={0}", item.Id); - } - return true; - } - - public override bool PerformDelete() - { - Current.Logger.Debug(TypeID + " " + ParentID + " deleting " + Alias); - var di = Current.Services.LocalizationService.GetDictionaryItemById(ParentID); - if (di == null) return true; - - Current.Services.LocalizationService.Delete(di); - return true; - } - - private string _returnUrl = ""; - - public override string ReturnUrl - { - get { return _returnUrl; } - } - - public override string AssignedApp - { - get { return Constants.Applications.Settings.ToString(); } - } - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dashboard/FeedProxy.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dashboard/FeedProxy.aspx.cs index cfa60b79a4..58d219e0c6 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dashboard/FeedProxy.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dashboard/FeedProxy.aspx.cs @@ -33,7 +33,7 @@ namespace dashboardUtilities return; var feedProxyXml = XmlHelper.OpenAsXmlDocument(IOHelper.MapPath(SystemFiles.FeedProxyConfig)); - if (feedProxyXml?.SelectSingleNode($"//allow[@host = '{requestUri.Host}']") != null && requestUri.Port == 80) + if (feedProxyXml?.SelectSingleNode($"//allow[@host = '{requestUri.Host}']") != null && (requestUri.Port == 80 || requestUri.Port == 443)) { if (_httpClient == null) _httpClient = new HttpClient(); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/protectPage.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/protectPage.aspx.cs index 4da6aab67f..e3fc136bad 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/protectPage.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/protectPage.aspx.cs @@ -43,7 +43,7 @@ namespace umbraco.presentation.umbraco.dialogs protected void selectMode(object sender, EventArgs e) { p_mode.Visible = false; - p_buttons.Visible = true; + p_setup.Visible = true; if (rb_simple.Checked) { @@ -271,14 +271,15 @@ namespace umbraco.presentation.umbraco.dialogs bt_protect.CommandName = "advanced"; } - p_buttons.Visible = true; p_mode.Visible = false; + p_setup.Visible = true; } } // Load up membergrouops _memberGroups.ID = "Membergroups"; _memberGroups.Width = 175; + _memberGroups.Height = 165; var selectedGroups = ""; // get roles from the membership provider @@ -307,7 +308,7 @@ namespace umbraco.presentation.umbraco.dialogs groupsSelector.Controls.Add(_memberGroups); - bt_protect.Text = Services.TextService.Localize("update"); + bt_protect.Text = Services.TextService.Localize("buttons", "select"); bt_buttonRemoveProtection.Text = Services.TextService.Localize("paRemoveProtection"); // Put user code to initialize the page here @@ -416,38 +417,35 @@ namespace umbraco.presentation.umbraco.dialogs var content = Services.ContentService.GetById(pageId); var text = content == null ? "" : content.Name; - feedback.Text = Services.TextService.Localize("publicAccess/paIsProtected", new[] { text }) + "

" + Services.TextService.Localize("closeThisWindow") + ""; + feedback_text.Text = Services.TextService.Localize("publicAccess/paIsProtected", new[] { text }); - p_buttons.Visible = false; - pane_advanced.Visible = false; - pane_simple.Visible = false; + p_setup.Visible = false; + p_feedback.Visible = true; //reloads the current node in the tree ClientTools.SyncTree(content.Path, true); //reloads the current node's children in the tree ClientTools.ReloadActionNode(false, true); - feedback.type = global::Umbraco.Web._Legacy.Controls.Feedback.feedbacktype.success; } protected void buttonRemoveProtection_Click(object sender, System.EventArgs e) { int pageId = int.Parse(Request.GetItemAsString("nodeId")); - p_buttons.Visible = false; - pane_advanced.Visible = false; - pane_simple.Visible = false; + p_setup.Visible = false; RemoveProtection(pageId); var content = Services.ContentService.GetById(pageId); var text = content == null ? "" : content.Name; - feedback.Text = Services.TextService.Localize("publicAccess/paIsRemoved", new[] { text }) + "

" + Services.TextService.Localize("closeThisWindow") + ""; + feedback_text.Text = Services.TextService.Localize("publicAccess/paIsRemoved", new[] { text }); + p_feedback.Visible = true; + //reloads the current node in the tree ClientTools.SyncTree(content.Path, true); //reloads the current node's children in the tree ClientTools.ReloadActionNode(false, true); - feedback.type = global::Umbraco.Web._Legacy.Controls.Feedback.feedbacktype.success; } protected CustomValidator SimpleLoginNameValidator; @@ -463,13 +461,13 @@ namespace umbraco.presentation.umbraco.dialogs protected global::System.Web.UI.HtmlControls.HtmlInputHidden tempFile; ///

- /// feedback control. + /// p_feedback control. /// /// /// Auto-generated field. /// To modify move field declaration from designer file to code-behind file. /// - protected global::Umbraco.Web._Legacy.Controls.Feedback feedback; + protected global::System.Web.UI.WebControls.Panel p_feedback; /// /// p_mode control. @@ -480,6 +478,15 @@ namespace umbraco.presentation.umbraco.dialogs /// protected global::System.Web.UI.WebControls.Panel p_mode; + /// + /// p_setup control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Panel p_setup; + /// /// pane_chooseMode control. /// @@ -615,15 +622,6 @@ namespace umbraco.presentation.umbraco.dialogs /// protected global::System.Web.UI.WebControls.PlaceHolder groupsSelector; - /// - /// p_buttons control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Panel p_buttons; - /// /// pane_pages control. /// @@ -732,6 +730,15 @@ namespace umbraco.presentation.umbraco.dialogs /// protected global::System.Web.UI.WebControls.PlaceHolder js; + /// + /// feedback_text control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal feedback_text; + } }