diff --git a/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs b/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs index 516f26774a..60aa666034 100644 --- a/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs +++ b/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs @@ -16,16 +16,6 @@ namespace Umbraco.Cms.Core.Composing { private readonly Assembly _entryPointAssembly; private readonly ILoggerFactory _loggerFactory; - private static readonly string[] UmbracoCoreAssemblyNames = new[] - { - "Umbraco.Core", - "Umbraco.Infrastructure", - "Umbraco.PublishedCache.NuCache", - "Umbraco.Examine.Lucene", - "Umbraco.Web.Common", - "Umbraco.Web.BackOffice", - "Umbraco.Web.Website", - }; public DefaultUmbracoAssemblyProvider(Assembly entryPointAssembly, ILoggerFactory loggerFactory) { @@ -43,7 +33,7 @@ namespace Umbraco.Cms.Core.Composing { get { - var finder = new FindAssembliesWithReferencesTo(new[] { _entryPointAssembly }, UmbracoCoreAssemblyNames, true, _loggerFactory); + var finder = new FindAssembliesWithReferencesTo(new[] { _entryPointAssembly }, Constants.Composing.UmbracoCoreAssemblyNames, true, _loggerFactory); return finder.Find(); } } diff --git a/src/Umbraco.Core/Composing/ReferenceResolver.cs b/src/Umbraco.Core/Composing/ReferenceResolver.cs index 6ecd425ac1..fdc72a183b 100644 --- a/src/Umbraco.Core/Composing/ReferenceResolver.cs +++ b/src/Umbraco.Core/Composing/ReferenceResolver.cs @@ -82,9 +82,8 @@ namespace Umbraco.Cms.Core.Composing assemblyName.FullName.StartsWith(f, StringComparison.InvariantCultureIgnoreCase))) continue; - // don't include this item if it's Umbraco - // TODO: We should maybe pass an explicit list of these names in? - if (assemblyName.FullName.StartsWith("Umbraco.") || assemblyName.Name.EndsWith(".Views")) + // don't include this item if it's Umbraco Core + if (Constants.Composing.UmbracoCoreAssemblyNames.Any(x=>assemblyName.FullName.StartsWith(x) || assemblyName.Name.EndsWith(".Views"))) continue; var assembly = Assembly.Load(assemblyName); diff --git a/src/Umbraco.Core/Constants-Composing.cs b/src/Umbraco.Core/Constants-Composing.cs index a92f71ee04..747a74b8d8 100644 --- a/src/Umbraco.Core/Constants-Composing.cs +++ b/src/Umbraco.Core/Constants-Composing.cs @@ -9,6 +9,17 @@ /// Defines constants for composition. /// public static class Composing - { } + { + public static readonly string[] UmbracoCoreAssemblyNames = new[] + { + "Umbraco.Core", + "Umbraco.Infrastructure", + "Umbraco.PublishedCache.NuCache", + "Umbraco.Examine.Lucene", + "Umbraco.Web.Common", + "Umbraco.Web.BackOffice", + "Umbraco.Web.Website", + }; + } } } diff --git a/src/Umbraco.Core/Dashboards/ContentDashboard.cs b/src/Umbraco.Core/Dashboards/ContentDashboard.cs index b959851cc7..135fe4304d 100644 --- a/src/Umbraco.Core/Dashboards/ContentDashboard.cs +++ b/src/Umbraco.Core/Dashboards/ContentDashboard.cs @@ -1,4 +1,5 @@ -using Umbraco.Cms.Core.Composing; +using System; +using Umbraco.Cms.Core.Composing; namespace Umbraco.Cms.Core.Dashboards { @@ -7,21 +8,10 @@ namespace Umbraco.Cms.Core.Dashboards { public string Alias => "contentIntro"; - public string[] Sections => new [] { "content" }; + public string[] Sections => new[] { "content" }; public string View => "views/dashboard/default/startupdashboardintro.html"; - public IAccessRule[] AccessRules - { - get - { - var rules = new IAccessRule[] - { - new AccessRule {Type = AccessRuleType.Deny, Value = Constants.Security.TranslatorGroupAlias}, - new AccessRule {Type = AccessRuleType.Grant, Value = Constants.Security.AdminGroupAlias} - }; - return rules; - } - } + public IAccessRule[] AccessRules { get; } = Array.Empty(); } } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index ce524a09a1..cade1041ac 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 @@ -46,6 +46,17 @@ <_Parameter1>DynamicProxyGenAssembly2 + + + + <_Parameter1>Umbraco.Forms.Core + + + <_Parameter1>Umbraco.Forms.Core.Providers + + + <_Parameter1>Umbraco.Forms.Web + diff --git a/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs index 6e732cdc0f..1722fb1d2d 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs @@ -202,8 +202,8 @@ namespace Umbraco.Cms.Core.PropertyEditors _richTextPropertyValueEditor.GetReferences(x.Value))) yield return umbracoEntityReference; - foreach (var umbracoEntityReference in mediaValues.Where(x=>x.Value.HasValues).SelectMany(x => - _mediaPickerPropertyValueEditor.GetReferences(x.Value["udi"]))) + foreach (var umbracoEntityReference in mediaValues.Where(x=>x.Value.HasValues) + .SelectMany(x => _mediaPickerPropertyValueEditor.GetReferences(x.Value["udi"]))) yield return umbracoEntityReference; } } diff --git a/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj b/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj index e5ee719a05..baa69dddb9 100644 --- a/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj +++ b/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj @@ -101,6 +101,17 @@ <_Parameter1>DynamicProxyGenAssembly2 + + + + <_Parameter1>Umbraco.Forms.Core + + + <_Parameter1>Umbraco.Forms.Core.Providers + + + <_Parameter1>Umbraco.Forms.Web + diff --git a/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs b/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs index 42c37684a3..b3de544184 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs @@ -71,8 +71,9 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers var allowedSections = string.Join(",", user.AllowedSections); var language = user.Language; var version = _umbracoVersion.SemanticVersion.ToSemanticString(); + var isAdmin = user.IsAdmin(); - var url = string.Format(baseUrl + "{0}?section={0}&allowed={1}&lang={2}&version={3}", section, allowedSections, language, version); + var url = string.Format(baseUrl + "{0}?section={0}&allowed={1}&lang={2}&version={3}&admin={4}", section, allowedSections, language, version, isAdmin); var key = "umbraco-dynamic-dashboard-" + language + allowedSections.Replace(",", "-") + section; var content = _appCaches.RuntimeCache.GetCacheItem(key); diff --git a/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj b/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj index d49eb6e4f5..967e2043f4 100644 --- a/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj +++ b/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj @@ -1,4 +1,4 @@ - + net5.0 @@ -31,6 +31,11 @@ <_Parameter1>Umbraco.Tests.Integration + + + + <_Parameter1>Umbraco.Forms.Web + diff --git a/src/Umbraco.Web.Common/DependencyInjection/ServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/DependencyInjection/ServiceCollectionExtensions.cs index 5182db4e20..49ed441932 100644 --- a/src/Umbraco.Web.Common/DependencyInjection/ServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/DependencyInjection/ServiceCollectionExtensions.cs @@ -4,7 +4,6 @@ using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Web.Caching; using SixLabors.ImageSharp.Web.Commands; @@ -12,6 +11,7 @@ using SixLabors.ImageSharp.Web.DependencyInjection; using SixLabors.ImageSharp.Web.Processors; using SixLabors.ImageSharp.Web.Providers; using Umbraco.Cms.Core.Configuration.Models; +using Umbraco.Cms.Core.Models.Identity; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Web.Common.Security; @@ -69,8 +69,8 @@ namespace Umbraco.Extensions .AddMemberManager() .AddUserStore() .AddRoleStore() - .AddRoleValidator>() - .AddRoleManager>(); + .AddRoleValidator>() + .AddRoleManager>(); private static MemberIdentityBuilder BuildMembersIdentity(this IServiceCollection services) { @@ -78,7 +78,7 @@ namespace Umbraco.Extensions services.TryAddScoped, UserValidator>(); services.TryAddScoped, PasswordValidator>(); services.TryAddScoped, PasswordHasher>(); - return new MemberIdentityBuilder(typeof(IdentityRole), services); + return new MemberIdentityBuilder(typeof(UmbracoIdentityRole), services); } private static void RemoveIntParamenterIfValueGreatherThen(IDictionary commands, string parameter, int maxValue) diff --git a/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj b/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj index bb2ecbc346..24f20f2f4a 100644 --- a/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj +++ b/src/Umbraco.Web.Common/Umbraco.Web.Common.csproj @@ -40,6 +40,11 @@ <_Parameter1>Umbraco.Tests.UnitTests + + + + <_Parameter1>Umbraco.Forms.Web + diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbfocuslock.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbfocuslock.directive.js index 569f49b88a..f7cd32217e 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbfocuslock.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbfocuslock.directive.js @@ -29,10 +29,6 @@ var defaultFocusedElement = getAutoFocusElement(focusableElements); var firstFocusableElement = focusableElements[0]; var lastFocusableElement = focusableElements[focusableElements.length -1]; - - // We need to add the tabbing-active class in order to highlight the focused button since the default style is - // outline: none; set in the stylesheet specifically - bodyElement.classList.add('tabbing-active'); // If there is no default focused element put focus on the first focusable element in the nodelist if(defaultFocusedElement === null ){ diff --git a/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js index 14643dc9cd..f9ebba00ea 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js @@ -572,13 +572,15 @@ * Method for opening an item in a list view for editing. * * @param {Object} item The item to edit + * @param {Object} scope The scope with options */ function editItem(item, scope) { + if (!item.editPath) { return; } - if (scope.options.useInfiniteEditor) + if (scope && scope.options && scope.options.useInfiniteEditor) { var editorModel = { id: item.id, diff --git a/src/Umbraco.Web.UI.Client/src/less/application/umb-outline.less b/src/Umbraco.Web.UI.Client/src/less/application/umb-outline.less index 939366d5ac..1f1c2c0e72 100644 --- a/src/Umbraco.Web.UI.Client/src/less/application/umb-outline.less +++ b/src/Umbraco.Web.UI.Client/src/less/application/umb-outline.less @@ -15,6 +15,7 @@ right: 0; border-radius: 3px; box-shadow: 0 0 2px 0px @ui-outline, inset 0 0 2px 2px @ui-outline; + pointer-events: none; } } diff --git a/src/Umbraco.Web.UI.Client/src/less/forms.less b/src/Umbraco.Web.UI.Client/src/less/forms.less index 90b2dbe37e..17c62037cc 100644 --- a/src/Umbraco.Web.UI.Client/src/less/forms.less +++ b/src/Umbraco.Web.UI.Client/src/less/forms.less @@ -308,7 +308,14 @@ select[size] { input[type="file"], input[type="radio"], input[type="checkbox"] { - .umb-outline(); + &:focus { + border-color: @inputBorderFocus; + outline: 0; + + .tabbing-active & { + outline: 2px solid @ui-outline; + } + } } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.controller.js index a7021b2867..33d526c3cf 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.controller.js @@ -1,8 +1,8 @@ (function () { "use strict"; - function UserPickerController($scope, usersResource, localizationService, eventsService) { - + function UserPickerController($scope, entityResource, localizationService, eventsService) { + var vm = this; vm.users = []; @@ -102,17 +102,9 @@ vm.loading = true; // Get users - usersResource.getPagedResults(vm.usersOptions).then(function (users) { - - vm.users = users.items; - - vm.usersOptions.pageNumber = users.pageNumber; - vm.usersOptions.pageSize = users.pageSize; - vm.usersOptions.totalItems = users.totalItems; - vm.usersOptions.totalPages = users.totalPages; - + entityResource.getAll("User").then(function (data) { + vm.users = data; preSelect($scope.model.selection, vm.users); - vm.loading = false; }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js index 716ca405c1..94ea4b8604 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js @@ -1,9 +1,9 @@ angular.module("umbraco") .controller("Umbraco.PropertyEditors.Grid.MediaController", - function ($scope, userService, editorService, localizationService) { - - $scope.thumbnailUrl = getThumbnailUrl(); - + function ($scope, userService, editorService, localizationService) { + + $scope.thumbnailUrl = getThumbnailUrl(); + if (!$scope.model.config.startNodeId) { if ($scope.model.config.ignoreUserStartNodes === true) { $scope.model.config.startNodeId = -1; @@ -29,16 +29,16 @@ angular.module("umbraco") onlyImages: true, dataTypeKey: $scope.model.dataTypeKey, submit: model => { - updateControlValue(model.selection[0]); + updateControlValue(model.selection[0]); editorService.close(); }, - close: () => editorService.close() + close: () => editorService.close() }; editorService.mediaPicker(mediaPicker); }; - $scope.editImage = function() { + $scope.editImage = function() { const mediaCropDetailsConfig = { size: 'small', @@ -47,17 +47,17 @@ angular.module("umbraco") updateControlValue(model.target); editorService.close(); }, - close: () => editorService.close() + close: () => editorService.close() }; localizationService.localize('defaultdialogs_editSelectedMedia').then(value => { mediaCropDetailsConfig.title = value; editorService.mediaCropDetails(mediaCropDetailsConfig); - }); + }); } - + /** - * + * */ function getThumbnailUrl() { @@ -94,19 +94,15 @@ angular.module("umbraco") return url; } - + return null; } /** - * - * @param {object} selectedImage + * + * @param {object} selectedImage */ function updateControlValue(selectedImage) { - - const doGetThumbnail = $scope.control.value.focalPoint !== selectedImage.focalPoint - || $scope.control.value.image !== selectedImage.image; - // we could apply selectedImage directly to $scope.control.value, // but this allows excluding fields in future if needed $scope.control.value = { @@ -118,10 +114,6 @@ angular.module("umbraco") caption: selectedImage.caption, altText: selectedImage.altText }; - - - if (doGetThumbnail) { - $scope.thumbnailUrl = getThumbnailUrl(); - } - } + $scope.thumbnailUrl = getThumbnailUrl(); + } }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.controller.js index f2055fea3a..217a9c8421 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.controller.js @@ -1,4 +1,4 @@ -function userPickerController($scope, usersResource , iconHelper, editorService, overlayService){ +function userPickerController($scope, iconHelper, editorService, overlayService, entityResource) { function trim(str, chr) { var rgxtrim = (!chr) ? new RegExp('^\\s+|\\s+$', 'g') : new RegExp('^' + chr + '+|' + chr + '+$', 'g'); @@ -92,17 +92,22 @@ function userPickerController($scope, usersResource , iconHelper, editorService, unsubscribe(); }); - //load user data - var modelIds = $scope.model.value ? $scope.model.value.split(',') : []; - - // entityResource.getByIds doesn't support "User" and we would like to show avatars in umb-user-preview as well. - usersResource.getUsers(modelIds).then(function (data) { - _.each(data, function (item, i) { - // set default icon if it's missing - item.icon = item.icon ? iconHelper.convertFromLegacyIcon(item.icon) : "icon-user"; - $scope.renderModel.push({ name: item.name, id: item.id, udi: item.udi, icon: item.icon, avatars: item.avatars }); - }); - }); + //load user data - split to an array of ints (map) + const modelIds = $scope.model.value ? $scope.model.value.split(',').map(x => +x) : []; + if(modelIds.length !== 0) { + entityResource.getAll("User").then(function (users) { + const filteredUsers = users.filter(user => modelIds.indexOf(user.id) !== -1); + filteredUsers.forEach(item => { + $scope.renderModel.push({ + name: item.name, + id: item.id, + udi: item.udi, + icon: item.icon = item.icon ? iconHelper.convertFromLegacyIcon(item.icon) : "icon-user", + avatars: item.avatars + }); + }); + }); + } } diff --git a/src/Umbraco.Web.Website/Umbraco.Web.Website.csproj b/src/Umbraco.Web.Website/Umbraco.Web.Website.csproj index a7c5e7a277..31a2ef25b2 100644 --- a/src/Umbraco.Web.Website/Umbraco.Web.Website.csproj +++ b/src/Umbraco.Web.Website/Umbraco.Web.Website.csproj @@ -1,4 +1,4 @@ - + net5.0 @@ -34,5 +34,10 @@ <_Parameter1>Umbraco.Tests.Integration + + + + <_Parameter1>Umbraco.Forms.Web +