diff --git a/src/Umbraco.Core/Constants-Sql.cs b/src/Umbraco.Core/Constants-Sql.cs new file mode 100644 index 0000000000..b57861c92a --- /dev/null +++ b/src/Umbraco.Core/Constants-Sql.cs @@ -0,0 +1,18 @@ +namespace Umbraco.Cms.Core +{ + public static partial class Constants + { + public static class Sql + { + /// + /// The maximum amount of parameters that can be used in a query. + /// + /// + /// The actual limit is 2100 + /// (https://docs.microsoft.com/en-us/sql/sql-server/maximum-capacity-specifications-for-sql-server), + /// but we want to ensure there's room for additional parameters if this value is used to create groups/batches. + /// + public const int MaxParameterCount = 2000; + } + } +} diff --git a/src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs b/src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs index 2380657180..e4d101ff06 100644 --- a/src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs +++ b/src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs @@ -251,7 +251,7 @@ namespace Umbraco.Cms.Core.Models.Mapping // the entity service due to too many Sql parameters. var list = new List(); - foreach (var idGroup in allContentPermissions.Keys.InGroupsOf(2000)) + foreach (var idGroup in allContentPermissions.Keys.InGroupsOf(Constants.Sql.MaxParameterCount)) list.AddRange(_entityService.GetAll(UmbracoObjectTypes.Document, idGroup.ToArray())); contentEntities = list.ToArray(); } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 734ed2261d..8ed2205f59 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -1,61 +1,61 @@ - - netstandard2.0 - Umbraco.Cms.Core - Umbraco CMS - Umbraco.Cms.Core - Umbraco CMS Core - Contains the core assembly needed to run Umbraco Cms. This package only contains the assembly, and can be used for package development. Use the template in the Umbraco.Templates package to setup Umbraco - Umbraco CMS - + + netstandard2.0 + Umbraco.Cms.Core + Umbraco CMS + Umbraco.Cms.Core + Umbraco CMS Core + Contains the core assembly needed to run Umbraco Cms. This package only contains the assembly, and can be used for package development. Use the template in the Umbraco.Templates package to setup Umbraco + Umbraco CMS + - - bin\Release\Umbraco.Core.xml - + + bin\Release\Umbraco.Core.xml + - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - all - - + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + all + + - - - <_Parameter1>Umbraco.Tests - - - <_Parameter1>Umbraco.Tests.Common - - - <_Parameter1>Umbraco.Tests.UnitTests - - - <_Parameter1>Umbraco.Tests.Benchmarks - - - <_Parameter1>Umbraco.Tests.Integration - - - <_Parameter1>DynamicProxyGenAssembly2 - - + + + <_Parameter1>Umbraco.Tests + + + <_Parameter1>Umbraco.Tests.Common + + + <_Parameter1>Umbraco.Tests.UnitTests + + + <_Parameter1>Umbraco.Tests.Benchmarks + + + <_Parameter1>Umbraco.Tests.Integration + + + <_Parameter1>DynamicProxyGenAssembly2 + + - - - + + + diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/AuditEntryRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/AuditEntryRepository.cs index 16c411c772..c439c1a80d 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/AuditEntryRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/AuditEntryRepository.cs @@ -53,7 +53,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement var entries = new List(); - foreach (var group in ids.InGroupsOf(2000)) + foreach (var group in ids.InGroupsOf(Constants.Sql.MaxParameterCount)) { var sql = Sql() .Select() diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs index 239f0a89ed..fd4d1c33b9 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentRepositoryBase.cs @@ -657,7 +657,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement // in the table? // get all PropertyDataDto for all definitions / versions - var allPropertyDataDtos = Database.FetchByGroups(versions, 2000, batch => + var allPropertyDataDtos = Database.FetchByGroups(versions, Constants.Sql.MaxParameterCount, batch => SqlContext.Sql() .Select() .From() @@ -666,7 +666,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement // get PropertyDataDto distinct PropertyTypeDto var allPropertyTypeIds = allPropertyDataDtos.Select(x => x.PropertyTypeId).Distinct().ToList(); - var allPropertyTypeDtos = Database.FetchByGroups(allPropertyTypeIds, 2000, batch => + var allPropertyTypeDtos = Database.FetchByGroups(allPropertyTypeIds, Constants.Sql.MaxParameterCount, batch => SqlContext.Sql() .Select(r => r.Select(x => x.DataTypeDto)) .From() diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs index d93c2c8322..d7be081fe1 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs @@ -795,7 +795,7 @@ AND umbracoNode.id <> @id", // note: important to use SqlNullableEquals for nullable types, cannot directly compare language identifiers var whereInArgsCount = propertyTypeIds.Count + (contentTypeIds?.Count ?? 0); - if (whereInArgsCount > 2000) + if (whereInArgsCount > Constants.Sql.MaxParameterCount) throw new NotSupportedException("Too many property/content types."); // delete existing relations (for target language) @@ -933,7 +933,7 @@ AND umbracoNode.id <> @id", // note: important to use SqlNullableEquals for nullable types, cannot directly compare language identifiers // var whereInArgsCount = propertyTypeIds.Count + (contentTypeIds?.Count ?? 0); - if (whereInArgsCount > 2000) + if (whereInArgsCount > Constants.Sql.MaxParameterCount) throw new NotSupportedException("Too many property/content types."); //first clear out any existing property data that might already exists under the target language @@ -1032,7 +1032,7 @@ AND umbracoNode.id <> @id", //based on the current variance of each item to see if it's 'edited' value should be true/false. var whereInArgsCount = propertyTypeIds.Count + (contentTypeIds?.Count ?? 0); - if (whereInArgsCount > 2000) + if (whereInArgsCount > Constants.Sql.MaxParameterCount) throw new NotSupportedException("Too many property/content types."); var propertySql = Sql() @@ -1121,14 +1121,20 @@ AND umbracoNode.id <> @id", } } - //lookup all matching rows in umbracoDocumentCultureVariation - var docCultureVariationsToUpdate = editedLanguageVersions.InGroupsOf(2000) - .SelectMany(_ => Database.Fetch( - Sql().Select().From() - .WhereIn(x => x.LanguageId, editedLanguageVersions.Keys.Select(x => x.langId).ToList()) - .WhereIn(x => x.NodeId, editedLanguageVersions.Keys.Select(x => x.nodeId)))) - //convert to dictionary with the same key type - .ToDictionary(x => (x.NodeId, (int?)x.LanguageId), x => x); + // lookup all matching rows in umbracoDocumentCultureVariation + // fetch in batches to account for maximum parameter count (distinct languages can't exceed 2000) + var languageIds = editedLanguageVersions.Keys.Select(x => x.langId).Distinct().ToArray(); + var nodeIds = editedLanguageVersions.Keys.Select(x => x.nodeId).Distinct(); + var docCultureVariationsToUpdate = nodeIds.InGroupsOf(Constants.Sql.MaxParameterCount - languageIds.Length) + .SelectMany(group => + { + var sql = Sql().Select().From() + .WhereIn(x => x.LanguageId, languageIds) + .WhereIn(x => x.NodeId, group); + + return Database.Fetch(sql); + }) + .ToDictionary(x => (x.NodeId, (int?)x.LanguageId), x => x); //convert to dictionary with the same key type var toUpdate = new List(); foreach (var ev in editedLanguageVersions) diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DictionaryRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DictionaryRepository.cs index 0ec31d843f..bc9892b1ee 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DictionaryRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DictionaryRepository.cs @@ -263,13 +263,12 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement Func>> getItemsFromParents = guids => { - //needs to be in groups of 2000 because we are doing an IN clause and there's a max parameter count that can be used. - return guids.InGroupsOf(2000) - .Select(@group => + return guids.InGroupsOf(Constants.Sql.MaxParameterCount) + .Select(group => { var sqlClause = GetBaseQuery(false) .Where(x => x.Parent != null) - .Where($"{SqlSyntax.GetQuotedColumnName("parent")} IN (@parentIds)", new { parentIds = @group }); + .WhereIn(x => x.Parent, group); var translator = new SqlTranslator(sqlClause, Query()); var sql = translator.Translate(); diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs index 4c9b19f1a9..75d66cf09d 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/DocumentRepository.cs @@ -1390,7 +1390,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement { var result = new Dictionary(); - var scheduleDtos = Database.FetchByGroups(contentIds, 2000, batch => Sql() + var scheduleDtos = Database.FetchByGroups(contentIds, Constants.Sql.MaxParameterCount, batch => Sql() .Select() .From() .WhereIn(x => x.NodeId, batch)); @@ -1440,7 +1440,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement if (versions.Count == 0) return new Dictionary>(); - var dtos = Database.FetchByGroups(versions, 2000, batch + var dtos = Database.FetchByGroups(versions, Constants.Sql.MaxParameterCount, batch => Sql() .Select() .From() @@ -1469,7 +1469,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement { var ids = temps.Select(x => x.Id); - var dtos = Database.FetchByGroups(ids, 2000, batch => + var dtos = Database.FetchByGroups(ids, Constants.Sql.MaxParameterCount, batch => Sql() .Select() .From() diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityContainerRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityContainerRepository.cs index bc1b1b1881..ac69d02587 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityContainerRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityContainerRepository.cs @@ -62,7 +62,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement { if (ids.Any()) { - return Database.FetchByGroups(ids, 2000, batch => + return Database.FetchByGroups(ids, Constants.Sql.MaxParameterCount, batch => GetBaseQuery(false) .Where(x => x.NodeObjectType == NodeObjectTypeId) .WhereIn(x => x.NodeId, batch)) diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs index 4eb4f108ce..f1b9c77d0a 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs @@ -279,7 +279,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement if (v == null) return entitiesList; // fetch all variant info dtos - var dtos = Database.FetchByGroups(v.Select(x => x.Id), 2000, GetVariantInfos); + var dtos = Database.FetchByGroups(v.Select(x => x.Id), Constants.Sql.MaxParameterCount, GetVariantInfos); // group by node id (each group contains all languages) var xdtos = dtos.GroupBy(x => x.NodeId).ToDictionary(x => x.Key, x => x); diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepositoryBase.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepositoryBase.cs index 25927213e5..1589c9d52e 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepositoryBase.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepositoryBase.cs @@ -209,16 +209,15 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement // can't query more than 2000 ids at a time... but if someone is really querying 2000+ entities, // the additional overhead of fetching them in groups is minimal compared to the lookup time of each group - const int maxParams = 2000; - if (ids.Length <= maxParams) + if (ids.Length <= Constants.Sql.MaxParameterCount) { return CachePolicy.GetAll(ids, PerformGetAll); } var entities = new List(); - foreach (var groupOfIds in ids.InGroupsOf(maxParams)) + foreach (var group in ids.InGroupsOf(Constants.Sql.MaxParameterCount)) { - entities.AddRange(CachePolicy.GetAll(groupOfIds.ToArray(), PerformGetAll)); + entities.AddRange(CachePolicy.GetAll(group.ToArray(), PerformGetAll)); } return entities; diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberRepository.cs index 22083eae30..6485dc286a 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberRepository.cs @@ -530,16 +530,13 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement var matchedMembers = Get(query).ToArray(); var membersInGroup = new List(); - //then we need to filter the matched members that are in the role - //since the max sql params are 2100 on sql server, we'll reduce that to be safe for potentially other servers and run the queries in batches - var inGroups = matchedMembers.InGroupsOf(1000); - foreach (var batch in inGroups) - { - var memberIdBatch = batch.Select(x => x.Id); + //then we need to filter the matched members that are in the role + foreach (var group in matchedMembers.Select(x => x.Id).InGroupsOf(Constants.Sql.MaxParameterCount)) + { var sql = Sql().SelectAll().From() .Where(dto => dto.MemberGroup == memberGroup.Id) - .WhereIn(dto => dto.Member, memberIdBatch); + .WhereIn(dto => dto.Member, group); var memberIdsInGroup = Database.Fetch(sql) .Select(x => x.Member).ToArray(); diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/PermissionRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/PermissionRepository.cs index 582120992b..be98b7a7f6 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/PermissionRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/PermissionRepository.cs @@ -38,44 +38,41 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement /// /// /// - /// This method will not support passing in more than 2000 group Ids + /// This method will not support passing in more than 2000 group IDs when also passing in entity IDs. /// public EntityPermissionCollection GetPermissionsForEntities(int[] groupIds, params int[] entityIds) { var result = new EntityPermissionCollection(); - foreach (var groupOfGroupIds in groupIds.InGroupsOf(2000)) + if (entityIds.Length == 0) { - //copy local - var localIds = groupOfGroupIds.ToArray(); - - if (entityIds.Length == 0) + foreach (var group in groupIds.InGroupsOf(Constants.Sql.MaxParameterCount)) { var sql = Sql() .SelectAll() .From() - .Where(dto => localIds.Contains(dto.UserGroupId)); + .Where(dto => group.Contains(dto.UserGroupId)); + var permissions = AmbientScope.Database.Fetch(sql); foreach (var permission in ConvertToPermissionList(permissions)) { result.Add(permission); } } - else + } + else + { + foreach (var group in entityIds.InGroupsOf(Constants.Sql.MaxParameterCount - groupIds.Length)) { - //iterate in groups of 2000 since we don't want to exceed the max SQL param count - foreach (var groupOfEntityIds in entityIds.InGroupsOf(2000)) + var sql = Sql() + .SelectAll() + .From() + .Where(dto => groupIds.Contains(dto.UserGroupId) && group.Contains(dto.NodeId)); + + var permissions = AmbientScope.Database.Fetch(sql); + foreach (var permission in ConvertToPermissionList(permissions)) { - var ids = groupOfEntityIds; - var sql = Sql() - .SelectAll() - .From() - .Where(dto => localIds.Contains(dto.UserGroupId) && ids.Contains(dto.NodeId)); - var permissions = AmbientScope.Database.Fetch(sql); - foreach (var permission in ConvertToPermissionList(permissions)) - { - result.Add(permission); - } + result.Add(permission); } } } @@ -133,11 +130,10 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement var db = AmbientScope.Database; - //we need to batch these in groups of 2000 so we don't exceed the max 2100 limit var sql = "DELETE FROM umbracoUserGroup2NodePermission WHERE userGroupId = @groupId AND nodeId in (@nodeIds)"; - foreach (var idGroup in entityIds.InGroupsOf(2000)) + foreach (var group in entityIds.InGroupsOf(Constants.Sql.MaxParameterCount)) { - db.Execute(sql, new { groupId, nodeIds = idGroup }); + db.Execute(sql, new { groupId, nodeIds = group }); } var toInsert = new List(); diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RedirectUrlRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RedirectUrlRepository.cs index 1536768bae..f035ffbd9b 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RedirectUrlRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/RedirectUrlRepository.cs @@ -39,8 +39,9 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement protected override IEnumerable PerformGetAll(params Guid[] ids) { - if (ids.Length > 2000) - throw new NotSupportedException("This repository does not support more than 2000 ids."); + if (ids.Length > Constants.Sql.MaxParameterCount) + throw new NotSupportedException($"This repository does not support more than {Constants.Sql.MaxParameterCount} ids."); + var sql = GetBaseQuery(false).WhereIn(x => x.Id, ids); var dtos = Database.Fetch(sql); return dtos.WhereNotNull().Select(Map); diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TagRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TagRepository.cs index 8fbc784576..736d183c85 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TagRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TagRepository.cs @@ -38,7 +38,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement { var dtos = ids.Length == 0 ? Database.Fetch(Sql().Select().From()) - : Database.FetchByGroups(ids, 2000, batch => Sql().Select().From().WhereIn(x => x.Id, batch)); + : Database.FetchByGroups(ids, Constants.Sql.MaxParameterCount, batch => Sql().Select().From().WhereIn(x => x.Id, batch)); return dtos.Select(TagFactory.BuildEntity).ToList(); } diff --git a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs index 91af372434..cdb284fdb0 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs @@ -1026,6 +1026,15 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers case UmbracoEntityTypes.Macro: + case UmbracoEntityTypes.Template: + var template = Services.FileService.GetTemplate(key); + if (template is null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + return Mapper.Map(template); + default: throw new NotSupportedException("The " + typeof(EntityController) + " does not currently support data for the type " + entityType); @@ -1059,6 +1068,15 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers case UmbracoEntityTypes.Macro: + case UmbracoEntityTypes.Template: + var template = Services.FileService.GetTemplate(id); + if (template is null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + return Mapper.Map(template); + default: throw new NotSupportedException("The " + typeof(EntityController) + " does not currently support data for the type " + entityType); diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index ec4ead689c..43d7a3cecd 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -44,7 +44,7 @@ "lazyload-js": "1.0.0", "moment": "2.22.2", "ng-file-upload": "12.2.13", - "nouislider": "15.4.0", + "nouislider": "15.5.0", "npm": "^6.14.7", "spectrum-colorpicker2": "2.0.8", "tinymce": "4.9.11", 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 4a1988cc27..50a32e0b05 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 @@ -200,6 +200,10 @@ } })); + evts.push(eventsService.on("rte.shortcut.saveAndPublish", function () { + $scope.saveAndPublish(); + })); + evts.push(eventsService.on("content.saved", function () { // Clear out localstorage keys that start with tinymce__ // When we save/perist a content node diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgridselector.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgridselector.directive.js index bf03749faa..4c628391cb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgridselector.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgridselector.directive.js @@ -1,9 +1,9 @@ (function () { 'use strict'; - function GridSelector($location, overlayService, editorService) { + function GridSelector(overlayService, editorService) { - function link(scope, el, attr, ctrl) { + function link(scope) { var eventBindings = []; scope.dialogModel = {}; @@ -33,26 +33,30 @@ }; scope.openItemPicker = function ($event) { - var dialogModel = { - view: "itempicker", - title: "Choose " + scope.itemLabel, - availableItems: scope.availableItems, - selectedItems: scope.selectedItems, - position: "target", - event: $event, - submit: function (model) { - scope.selectedItems.push(model.selectedItem); - // if no default item - set item as default - if (scope.defaultItem === null) { - scope.setAsDefaultItem(model.selectedItem); + if (scope.itemPicker) { + scope.itemPicker(); + } else { + var dialogModel = { + view: "itempicker", + title: "Choose " + scope.itemLabel, + availableItems: scope.availableItems, + selectedItems: scope.selectedItems, + position: "target", + event: $event, + submit: function (model) { + scope.selectedItems.push(model.selectedItem); + // if no default item - set item as default + if (scope.defaultItem === null) { + scope.setAsDefaultItem(model.selectedItem); + } + overlayService.close(); + }, + close: function () { + overlayService.close(); } - overlayService.close(); - }, - close: function() { - overlayService.close(); - } - }; - overlayService.open(dialogModel); + }; + overlayService.open(dialogModel); + } }; scope.openTemplate = function (selectedItem) { @@ -156,7 +160,8 @@ availableItems: "=", defaultItem: "=", itemName: "@", - updatePlaceholder: "=" + updatePlaceholder: "=", + itemPicker: "=" }, link: link }; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js index fe802a8a28..1f65bd7cea 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js @@ -179,7 +179,7 @@ When building a custom infinite editor view you can use the same components as a } else { focus(); } - }); + }); /** * @ngdoc method @@ -972,6 +972,28 @@ When building a custom infinite editor view you can use the same components as a open(editor); } + /** + * @ngdoc method + * @name umbraco.services.editorService#templatePicker + * @methodOf umbraco.services.editorService + * + * @description + * Opens a template picker in infinite editing, the submit callback returns an array of selected items. + * + * @param {object} editor rendering options. + * @param {boolean} editor.multiPicker Pick one or multiple items. + * @param {function} editor.submit Callback function when the submit button is clicked. Returns the editor model object. + * @param {function} editor.close Callback function when the close button is clicked. + * @returns {object} editor object. + */ + function templatePicker(editor) { + editor.view = "views/common/infiniteeditors/treepicker/treepicker.html"; + if (!editor.size) editor.size = "small"; + editor.section = "settings"; + editor.treeAlias = "templates"; + open(editor); + } + /** * @ngdoc method * @name umbraco.services.editorService#macroPicker @@ -1134,6 +1156,7 @@ When building a custom infinite editor view you can use the same components as a templateSections: templateSections, userPicker: userPicker, itemPicker: itemPicker, + templatePicker: templatePicker, macroPicker: macroPicker, memberGroupPicker: memberGroupPicker, memberPicker: memberPicker, diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js index 4c3901e63c..4556641eca 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js @@ -1226,6 +1226,12 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s }); }); + editor.addShortcut('Ctrl+P', '', function () { + angularHelper.safeApply($rootScope, function () { + eventsService.emit("rte.shortcut.saveAndPublish"); + }); + }); + }, insertLinkInEditor: function (editor, target, anchorElm) { diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html index 7ec69018b6..9ebb9d4e45 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html @@ -30,21 +30,22 @@
- + Inherit tabs and properties from an existing Document Type. New tabs will be added to the current Document Type or + merged if a tab with an identical name exists.
- + There are no Content Types available to use as a composition. - + This Content Type is used in a composition, and therefore cannot be composed itself.
-
-

+
Where is this composition used?
+

This composition is currently used in the composition of the following Content Types:

  • diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/overlays/confirmremove.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/overlays/confirmremove.html index 6fc3bd826d..33f48b8c1e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/overlays/confirmremove.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/overlays/confirmremove.html @@ -1,9 +1,10 @@
    - + Removing a composition will delete all the associated property data. Once you save the Document Type there's no way + back.
    - + Are you sure?
    diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.html index a4fef28740..d3c6a3538d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.html @@ -23,22 +23,22 @@
    - using this editor will get updated with the new settings. + All Document Types using this editor will get updated with the new settings.
    - +
    - +
    -
    +
    Configuration
    diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html index 99f4fc04e7..9a01d3329d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html @@ -12,21 +12,21 @@
    - + URL
    - + Alternative text (optional)
    - + Caption (optional)
    diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.html index 8379062807..564f0911fe 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.html @@ -55,9 +55,11 @@
    @@ -87,7 +89,7 @@
    -
    +
    Validation
    Current version

    {{vm.currentVersion.name}} (Created: {{vm.currentVersion.createDate}})

    -
    +
    Rollback to
    - + Required
    - +
    - + If mandatory, the child template must contain a @section definition, otherwise an error is shown.
    - +
    - +
    - +
    -
    +
    Define a named section
    - + Defines a part of your template as a named section by wrapping it in @section { ... }. + This can be rendered in a specific area of the parent of this template, by using @RenderSection. +
    - +
    - + - + Required
    - +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.controller.js index ed5c4096bc..72eb504c60 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.controller.js @@ -141,6 +141,9 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", }); } } + else if (vm.treeAlias === "templates") { + vm.entityType = "Template"; + } // TODO: Seems odd this logic is here, i don't think it needs to be and should just exist on the property editor using this if ($scope.model.minNumber) { diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.html index 8f2627795f..b926d9e266 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.html @@ -1,141 +1,144 @@
    -
    +
    -
    +
    + Your profile +
    - + + - - + + - - + + - - +
    + +
    + +
    + External login providers +
    + +
    + +
    + +
    +
    + + +
    + + +
    -
    +
    -
    - External login providers -
    -
    +
    +
    + Your recent history +
    + +
    -
    +
    -
    -
    - - -
    +
    - -
    - -
    + + + + + + + + + + +
    + +
    +
    +
    {{tab.label}}
    +
    +
    +
    - - -
    -
    - -
    - -
    - -
    - Change password -
    - -
    - - - - - - - - - - -
    - -
    - -
    -
    -
    {{tab.label}}
    -
    -
    -
    -
    -
    +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-app-header.html b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-app-header.html index 3ad4ebc188..e0fb4aeb77 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-app-header.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-app-header.html @@ -10,7 +10,7 @@
    • -
    • -
    @@ -34,7 +34,7 @@
    - : {{ vm.group.inheritedFromName }} + Inherited from: {{ vm.group.inheritedFromName }} , @@ -46,9 +46,9 @@ -
    +
    Required
    -
    +
    Required
    diff --git a/src/Umbraco.Web.UI.Client/src/views/components/contenttype/umb-content-type-property.html b/src/Umbraco.Web.UI.Client/src/views/components/contenttype/umb-content-type-property.html index 8751a4723f..14f647e761 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/contenttype/umb-content-type-property.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/contenttype/umb-content-type-property.html @@ -28,7 +28,7 @@
    {{propertyTypeForm.groupName.errorMsg}}
    -
    +
    Required label
    @@ -61,37 +61,37 @@ {{vm.property.dataTypeName}} - + Preview
    * - + Mandatory
    - + Show on member profile
    - + Member can edit
    - + Is sensitive data
    - + Vary by culture
    - + Vary by segments
    @@ -100,13 +100,13 @@
    - + Inherited from {{vm.property.contentTypeName}}
    - + Locked
    diff --git a/src/Umbraco.Web.UI.Client/src/views/components/contenttype/umb-content-type-tab.html b/src/Umbraco.Web.UI.Client/src/views/components/contenttype/umb-content-type-tab.html index 59476f7e26..b62e3f17d9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/contenttype/umb-content-type-tab.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/contenttype/umb-content-type-tab.html @@ -1,6 +1,6 @@ -
    - : {{ vm.tab.inheritedFromName }} + Inherited from: {{ vm.tab.inheritedFromName }} , @@ -50,7 +50,7 @@
    {{tabNameForm.tabName.errorMsg}}
    -
    +
    Required
    @@ -61,9 +61,9 @@ -
    +
    Required
    -
    +
    Required
    diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html index 993622e880..3575453bd8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html @@ -55,7 +55,7 @@ ng-if="sortingMode" class="umb-group-builder__convert-dropzone" umb-droppable="droppableOptionsConvert"> - + Convert to tab
    - + You have not added any groups
    @@ -118,7 +118,7 @@ data-element="property-add" class="umb-group-builder__group-add-property" ng-click="addNewProperty(tab)"> - + Add property - + Add property
    @@ -183,6 +183,6 @@ class="umb-group-builder__group -placeholder" ng-click="addGroupToActiveTab()" data-element="group-add"> - + Add group
    diff --git a/src/Umbraco.Web.UI.Client/src/views/content/assigndomain.html b/src/Umbraco.Web.UI.Client/src/views/content/assigndomain.html index 3bf10d610e..1625552955 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/assigndomain.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/assigndomain.html @@ -8,7 +8,7 @@
    Culture
    - + @@ -25,18 +25,19 @@
    Domains
    - + Valid domain names are: "example.com", "www.example.com", "example.com:8080", or "https://www.example.com/". + Furthermore also one-level paths in domains are supported, eg. "example.com/en" or "/en".
    @@ -49,9 +50,9 @@ - + Value cannot be empty - ({{domain.other}}) + Domain has already been assigned.({{domain.other}})
    - + Domain * - + Language * @@ -72,7 +72,7 @@
    - + Media Types
    @@ -106,7 +106,7 @@
    - + Member Types
    diff --git a/src/Umbraco.Web.UI.Client/src/views/dataTypes/views/datatype.info.html b/src/Umbraco.Web.UI.Client/src/views/dataTypes/views/datatype.info.html index 7bf985ca56..2b59a8c4e7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dataTypes/views/datatype.info.html +++ b/src/Umbraco.Web.UI.Client/src/views/dataTypes/views/datatype.info.html @@ -24,7 +24,7 @@
    - + Used in Document Types
    @@ -85,7 +85,7 @@
    - + Used in Member Types
    diff --git a/src/Umbraco.Web.UI.Client/src/views/documentTypes/import.controller.js b/src/Umbraco.Web.UI.Client/src/views/documentTypes/import.controller.js index 6170348243..3983377550 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documentTypes/import.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documentTypes/import.controller.js @@ -9,7 +9,7 @@ angular.module("umbraco") vm.cancelButtonLabel = "cancel"; - $scope.handleFiles = function (files, event) { + $scope.handleFiles = function (files, event, invalidFiles) { if (files && files.length > 0) { $scope.upload(files[0]); } diff --git a/src/Umbraco.Web.UI.Client/src/views/documentTypes/importdocumenttype.html b/src/Umbraco.Web.UI.Client/src/views/documentTypes/importdocumenttype.html index 347f94039c..32322558bd 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documentTypes/importdocumenttype.html +++ b/src/Umbraco.Web.UI.Client/src/views/documentTypes/importdocumenttype.html @@ -5,18 +5,19 @@

    - To import a document type, find the '.udt' file on your computer by clicking the 'Browse' button and click - 'Import' (you'll be asked for confirmation on the next screen) + To import a document type, find the '.udt' file on your computer by clicking the 'Import' button (you'll be + asked for confirmation on the next screen)

    -
  • -
  • diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js index 7334fbeadf..11ef37029c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js @@ -65,6 +65,9 @@ vm.layout = []; // The layout object specific to this Block Editor, will be a direct reference from Property Model. vm.availableBlockTypes = []; // Available block entries of this property editor. vm.labels = {}; + vm.options = { + createFlow: false + }; localizationService.localizeMany(["grid_addElement", "content_createEmpty"]).then(function (data) { vm.labels.grid_addElement = data[0]; @@ -380,7 +383,7 @@ function editBlock(blockObject, openSettings, blockIndex, parentForm, options) { - options = options || {}; + options = options || vm.options; // this must be set if (blockIndex === undefined) { @@ -560,7 +563,9 @@ if (inlineEditing === true) { blockObject.activate(); } else if (inlineEditing === false && blockObject.hideContentInOverlay !== true) { + vm.options.createFlow = true; blockObject.edit(); + vm.options.createFlow = false; } } } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html index e93637c671..fa148ecfc7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html @@ -1,7 +1,7 @@
    -

    -

    +

    You have picked a content item currently deleted or in the recycle bin

    +

    You have picked content items currently deleted or in the recycle bin

    diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.html index f5a6191ad1..698ff6daeb 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.html @@ -18,12 +18,14 @@
    -

    +

    Adjust the row by setting cell widths and adding additional cells

    -

    Modifying a row configuration name will result in loss of - data for any existing content that is based on this configuration.

    -

    Modifying only the label will not result in data loss.

    + +

    Modifying a row configuration name will result in loss of + data for any existing content that is based on this configuration.

    +

    Modifying only the label will not result in data loss.

    +
    @@ -70,10 +72,16 @@
    {{currentCell.grid}}
    diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/overlays/rowdeleteconfirm.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/overlays/rowdeleteconfirm.html index 2ba56a5b88..ded2e5b940 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/overlays/rowdeleteconfirm.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/overlays/rowdeleteconfirm.html @@ -11,6 +11,6 @@

    - ? + Are you sure you want to delete?
    diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/grid/grid.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/grid/grid.html index 07d5215793..8bbcb2204c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/grid/grid.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/grid/grid.html @@ -17,12 +17,12 @@ - + Sorry, we can not find what you are looking for. - + Your recycle bin is empty
    @@ -69,12 +69,12 @@ - + Your recycle bin is empty - + Sorry, we can not find what you are looking for.
    diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewpublish.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewpublish.html index c6f7c85c0b..b6933dffc0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewpublish.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewpublish.html @@ -2,7 +2,7 @@
    -

    +

    Publishing will make the selected items visible on the site.

    @@ -13,13 +13,13 @@
    -

    +

    What languages would you like to publish?

    - + Languages
    @@ -34,7 +34,7 @@
    - + Mandatory language
    diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.html index 5806bb8f02..9a6af50f3e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.html @@ -2,7 +2,7 @@
    -

    +

    Unpublishing will remove the selected items and all their descendants from the site.

    @@ -13,13 +13,13 @@
    -

    +

    Select the languages to unpublish. Unpublishing a mandatory language will unpublish all languages.

    - + Languages
    @@ -35,7 +35,7 @@
    - + Mandatory language
    diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js index 7b527804f5..856886a870 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js @@ -559,13 +559,13 @@ } }); - localizationService.localize("template_mastertemplate").then(function (value) { - var title = value; - var masterTemplate = { - title: title, - availableItems: availableMasterTemplates, - submit: function (model) { - var template = model.selectedItem; + localizationService.localize("template_mastertemplate").then(title => { + const editor = { + title, + filterCssClass: 'not-allowed', + filter: item => !availableMasterTemplates.some(template => template.id == item.id), + submit: model => { + var template = model.selection[0]; if (template && template.alias) { vm.template.masterTemplateAlias = template.alias; setLayout(template.alias + ".cshtml"); @@ -575,14 +575,10 @@ } editorService.close(); }, - close: function (oldModel) { - // close dialog - editorService.close(); - // focus editor - vm.editor.focus(); - } - }; - editorService.itemPicker(masterTemplate); + close: () => editorService.close() + } + + editorService.templatePicker(editor); }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html index 29be782415..5569e0a985 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html @@ -181,7 +181,7 @@ - + Sorry, we can not find what you are looking for. @@ -305,7 +305,7 @@ Invite User

    - + Invite new users to give them access to Umbraco. An invite email will be sent to the user with information on how to log in to Umbraco. Invites last for 72 hours.

    @@ -313,7 +313,7 @@ Create user

    - + Create new users to give them access to Umbraco. When a new user is created a password will be generated that you can share with the user.

    @@ -437,7 +437,7 @@
    -

    +

    The new user has successfully been created. To log in to Umbraco use the password below.

    @@ -520,7 +520,7 @@
    -

    +

    An invitation has been sent to the new user with details about how to log in to Umbraco.

    diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index 748220f671..72ad387bae 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -1398,6 +1398,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Remove all medias? Clipboard Not allowed + Open media picker enter external link @@ -1419,7 +1420,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Created Current version - Red text will not be shown in the selected version. , green means added]]> + Red text will be removed in the selected version, green text will be added]]> Document has been rolled back Select a version to compare with the current version This displays the selected version as HTML, if you wish to see the difference between 2 @@ -1458,7 +1459,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Default template To import a Document Type, find the ".udt" file on your computer by clicking the - "Browse" button and click "Import" (you'll be asked for confirmation on the next screen) + "Import" button (you'll be asked for confirmation on the next screen) New Tab Title Node type @@ -1711,6 +1712,9 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Choose extra Choose default are added + Warning + + Modifying a row configuration name will result in loss of data for any existing content that is based on this configuration.

    Modifying only the label will not result in data loss.

    ]]>
    You are deleting the row configuration Deleting a row configuration name will result in loss of data for any existing content that is based on this @@ -1819,6 +1823,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Removing a child node will limit the editors options to create different content types beneath a node. + using this editor will get updated with the new settings. Add language 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 7f139b2da8..eb8538af20 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -1424,6 +1424,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Remove all medias? Clipboard Not allowed + Open media picker enter external link @@ -1446,7 +1447,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Select a version to compare with the current version Current version - Red text will not be shown in the selected version. , green means added]]> + Red text will be removed in the selected version, green text will be added]]> Document has been rolled back This displays the selected version as HTML, if you wish to see the difference between 2 versions at the same time, use the diff view @@ -1477,7 +1478,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Default template To import a Document Type, find the ".udt" file on your computer by clicking the - "Browse" button and click "Import" (you'll be asked for confirmation on the next screen) + "Import" button (you'll be asked for confirmation on the next screen) New Tab Title Node type @@ -1753,6 +1754,9 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Choose extra Choose default are added + Warning + + Modifying a row configuration name will result in loss of data for any existing content that is based on this configuration.

    Modifying only the label will not result in data loss.

    ]]>
    You are deleting the row configuration Deleting a row configuration name will result in loss of data for any existing content that is based on this @@ -1876,6 +1880,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Removing a child node will limit the editors options to create different content types beneath a node. + using this editor will get updated with the new settings. Add language diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml b/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml index bedf544ea0..3ef84f2354 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/nl.xml @@ -832,6 +832,7 @@ Blauw + Tabblad toevoegen Groep toevoegen Eigenschap toevoegen Editor toevoegen @@ -1678,6 +1679,7 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je Je hebt wijzigingen aangebracht aan deze eigenschap. Ben je zeker dat je ze wil weggooien? + Tabblad toevoegen Taal toevoegen