From 4f5fb0c9c381eaf5ccaf1411a34bcbb48e3d609f Mon Sep 17 00:00:00 2001 From: Elitsa Marinovska Date: Tue, 18 Aug 2020 15:53:25 +0200 Subject: [PATCH 01/53] Changes necessary for migrating old tests --- .../TestHelpers/Entities/MockedMedia.cs | 0 .../TestHelpers/Entities/MockedMember.cs | 1 - .../TestHelpers/Entities/MockedUserGroup.cs | 8 ++++++-- .../Extensions/ApplicationBuilderExtensions.cs | 7 ++++--- src/Umbraco.Tests/Services/ContentServiceTests.cs | 1 + src/Umbraco.Tests/Services/UserServiceTests.cs | 2 ++ 6 files changed, 13 insertions(+), 6 deletions(-) rename src/{Umbraco.Tests => Umbraco.Tests.Common}/TestHelpers/Entities/MockedMedia.cs (100%) rename src/{Umbraco.Tests => Umbraco.Tests.Common}/TestHelpers/Entities/MockedMember.cs (98%) rename src/{Umbraco.Tests => Umbraco.Tests.Common}/TestHelpers/Entities/MockedUserGroup.cs (67%) diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedMedia.cs b/src/Umbraco.Tests.Common/TestHelpers/Entities/MockedMedia.cs similarity index 100% rename from src/Umbraco.Tests/TestHelpers/Entities/MockedMedia.cs rename to src/Umbraco.Tests.Common/TestHelpers/Entities/MockedMedia.cs diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedMember.cs b/src/Umbraco.Tests.Common/TestHelpers/Entities/MockedMember.cs similarity index 98% rename from src/Umbraco.Tests/TestHelpers/Entities/MockedMember.cs rename to src/Umbraco.Tests.Common/TestHelpers/Entities/MockedMember.cs index b721b508ba..e6916d7de7 100644 --- a/src/Umbraco.Tests/TestHelpers/Entities/MockedMember.cs +++ b/src/Umbraco.Tests.Common/TestHelpers/Entities/MockedMember.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using Umbraco.Core.Models; -using Umbraco.Core.Models.Membership; namespace Umbraco.Tests.TestHelpers.Entities { diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedUserGroup.cs b/src/Umbraco.Tests.Common/TestHelpers/Entities/MockedUserGroup.cs similarity index 67% rename from src/Umbraco.Tests/TestHelpers/Entities/MockedUserGroup.cs rename to src/Umbraco.Tests.Common/TestHelpers/Entities/MockedUserGroup.cs index ce3852c540..0285005a84 100644 --- a/src/Umbraco.Tests/TestHelpers/Entities/MockedUserGroup.cs +++ b/src/Umbraco.Tests.Common/TestHelpers/Entities/MockedUserGroup.cs @@ -1,12 +1,16 @@ using Umbraco.Core.Models.Membership; +using Umbraco.Core.Strings; namespace Umbraco.Tests.TestHelpers.Entities { public class MockedUserGroup { - internal static UserGroup CreateUserGroup(string suffix = "", string[] permissions = null, string[] allowedSections = null) + public static IShortStringHelper ShortStringHelper { get; } = + new DefaultShortStringHelper(new DefaultShortStringHelperConfig()); + + public static UserGroup CreateUserGroup(string suffix = "", string[] permissions = null, string[] allowedSections = null) { - var group = new UserGroup(TestHelper.ShortStringHelper) + var group = new UserGroup(ShortStringHelper) { Alias = "testUserGroup" + suffix, Name = "TestUserGroup" + suffix, diff --git a/src/Umbraco.Tests.Integration/Extensions/ApplicationBuilderExtensions.cs b/src/Umbraco.Tests.Integration/Extensions/ApplicationBuilderExtensions.cs index 3961657afe..edbdcd0722 100644 --- a/src/Umbraco.Tests.Integration/Extensions/ApplicationBuilderExtensions.cs +++ b/src/Umbraco.Tests.Integration/Extensions/ApplicationBuilderExtensions.cs @@ -99,10 +99,11 @@ namespace Umbraco.Tests.Integration.Extensions break; case UmbracoTestOptions.Database.NewSchemaPerFixture: - throw new NotImplementedException(); + // New DB + Schema + var newSchemaFixtureDbId = db.AttachSchema(); - //// Add teardown callback - //integrationTest.OnFixtureTearDown(() => db.Detach()); + // Add teardown callback + integrationTest.OnFixtureTearDown(() => db.Detach(newSchemaFixtureDbId)); break; case UmbracoTestOptions.Database.NewEmptyPerFixture: diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index c8467b057f..81f8a5bcad 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -19,6 +19,7 @@ using Umbraco.Tests.Testing; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Cache; using Umbraco.Core.PropertyEditors; +using Umbraco.Tests.Common.TestHelpers.Entities; using Umbraco.Tests.LegacyXmlPublishedCache; namespace Umbraco.Tests.Services diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs index dbd71870d4..e00cf1364b 100644 --- a/src/Umbraco.Tests/Services/UserServiceTests.cs +++ b/src/Umbraco.Tests/Services/UserServiceTests.cs @@ -13,8 +13,10 @@ using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; +using Umbraco.Tests.Common.TestHelpers.Entities; using Umbraco.Tests.Testing; using Umbraco.Web.Actions; +using MockedUser = Umbraco.Tests.TestHelpers.Entities.MockedUser; namespace Umbraco.Tests.Services From 4edf002dd03050a13f79721d27dd6309e30eadda Mon Sep 17 00:00:00 2001 From: Elitsa Marinovska Date: Tue, 18 Aug 2020 16:10:05 +0200 Subject: [PATCH 02/53] Migrating old tests to .net core test projects --- .../Repositories/DictionaryRepositoryTest.cs | 119 +++++++------- .../Repositories/EntityRepositoryTest.cs | 47 +++--- .../Repositories/KeyValueRepositoryTests.cs | 8 +- .../Repositories/LanguageRepositoryTest.cs | 121 +++++++------- .../Repositories/MacroRepositoryTest.cs | 140 +++++++--------- .../NotificationsRepositoryTest.cs | 21 +-- .../RedirectUrlRepositoryTests.cs | 36 +++-- .../RelationTypeRepositoryTest.cs | 73 ++++----- .../ServerRegistrationRepositoryTest.cs | 74 ++++----- .../Repositories/SimilarNodeNameTests.cs | 5 +- .../Repositories/TemplateRepositoryTest.cs | 150 +++++++++++------- .../Repositories/UserGroupRepositoryTest.cs | 84 +++++----- .../Repositories/UserRepositoryTest.cs | 1 + src/Umbraco.Tests/Umbraco.Tests.csproj | 18 +-- 14 files changed, 427 insertions(+), 470 deletions(-) rename src/{Umbraco.Tests => Umbraco.Tests.Integration}/Persistence/Repositories/DictionaryRepositoryTest.cs (75%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration}/Persistence/Repositories/EntityRepositoryTest.cs (71%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration}/Persistence/Repositories/KeyValueRepositoryTests.cs (90%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration}/Persistence/Repositories/LanguageRepositoryTest.cs (72%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration}/Persistence/Repositories/MacroRepositoryTest.cs (75%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration}/Persistence/Repositories/NotificationsRepositoryTest.cs (93%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration}/Persistence/Repositories/RedirectUrlRepositoryTests.cs (87%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration}/Persistence/Repositories/RelationTypeRepositoryTest.cs (78%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration}/Persistence/Repositories/ServerRegistrationRepositoryTest.cs (76%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration}/Persistence/Repositories/SimilarNodeNameTests.cs (97%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration}/Persistence/Repositories/TemplateRepositoryTest.cs (84%) rename src/{Umbraco.Tests => Umbraco.Tests.Integration}/Persistence/Repositories/UserGroupRepositoryTest.cs (83%) diff --git a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/DictionaryRepositoryTest.cs similarity index 75% rename from src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs rename to src/Umbraco.Tests.Integration/Persistence/Repositories/DictionaryRepositoryTest.cs index e23734acc3..a85873a761 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs +++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/DictionaryRepositoryTest.cs @@ -3,43 +3,43 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; using Umbraco.Core.Models; +using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; -using Umbraco.Tests.TestHelpers; +using Umbraco.Core.Services; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.Testing; -using Umbraco.Core; -using Umbraco.Core.Composing; -namespace Umbraco.Tests.Persistence.Repositories +namespace Umbraco.Tests.Integration.Persistence.Repositories { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class DictionaryRepositoryTest : TestWithDatabaseBase + public class DictionaryRepositoryTest : UmbracoIntegrationTest { - public override void SetUp() + [SetUp] + public void SetUp() { - base.SetUp(); - CreateTestData(); } private IDictionaryRepository CreateRepository() { - return Factory.GetInstance(); + return GetRequiredService(); } [Test] public void Can_Perform_Get_By_Key_On_DictionaryRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var localizationService = GetRequiredService(); + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(); var dictionaryItem = (IDictionaryItem)new DictionaryItem("Testing1235") { Translations = new List { - new DictionaryTranslation(ServiceContext.LocalizationService.GetLanguageByIsoCode("en-US"), "Hello world") + new DictionaryTranslation(localizationService.GetLanguageByIsoCode("en-US"), "Hello world") } }; @@ -55,22 +55,22 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.That(dictionaryItem.Translations.Any(x => x == null), Is.False); Assert.That(dictionaryItem.Translations.First().Value, Is.EqualTo("Hello world")); } - } [Test] public void Can_Perform_Get_By_UniqueId_On_DictionaryRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var localizationService = GetRequiredService(); + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(); var dictionaryItem = (IDictionaryItem)new DictionaryItem("Testing1235") { Translations = new List { - new DictionaryTranslation(ServiceContext.LocalizationService.GetLanguageByIsoCode("en-US"), "Hello world") + new DictionaryTranslation(localizationService.GetLanguageByIsoCode("en-US"), "Hello world") } }; @@ -92,15 +92,16 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_DictionaryRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var localizationService = GetRequiredService(); + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(); var dictionaryItem = (IDictionaryItem)new DictionaryItem("Testing1235") { Translations = new List { - new DictionaryTranslation(ServiceContext.LocalizationService.GetLanguageByIsoCode("en-US"), "Hello world") + new DictionaryTranslation(localizationService.GetLanguageByIsoCode("en-US"), "Hello world") } }; @@ -117,15 +118,14 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.That(dictionaryItem.Translations.Any(x => x == null), Is.False); Assert.That(dictionaryItem.Translations.First().Value, Is.EqualTo("Hello world")); } - } [Test] public void Can_Perform_Get_On_DictionaryRepository_When_No_Language_Assigned() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(); var dictionaryItem = (IDictionaryItem) new DictionaryItem("Testing1235"); @@ -141,15 +141,14 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.That(dictionaryItem.ItemKey, Is.EqualTo("Testing1235")); Assert.That(dictionaryItem.Translations.Any(), Is.False); } - } [Test] public void Can_Perform_GetAll_On_DictionaryRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(); @@ -169,8 +168,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_DictionaryRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(); @@ -189,13 +188,13 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_DictionaryRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(); // Act - var query = scope.SqlContext.Query().Where(x => x.ItemKey == "Article"); + var query = provider.SqlContext.Query().Where(x => x.ItemKey == "Article"); var result = repository.Get(query); // Assert @@ -209,13 +208,13 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_DictionaryRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(); // Act - var query = scope.SqlContext.Query().Where(x => x.ItemKey.StartsWith("Read")); + var query = provider.SqlContext.Query().Where(x => x.ItemKey.StartsWith("Read")); var result = repository.Count(query); // Assert @@ -227,19 +226,19 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_DictionaryRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var languageRepository = Factory.GetInstance(); + var languageRepository = GetRequiredService(); var repository = CreateRepository(); var language = languageRepository.Get(1); var read = new DictionaryItem("Read"); var translations = new List - { - new DictionaryTranslation(language, "Read") - }; + { + new DictionaryTranslation(language, "Read") + }; read.Translations = translations; // Act @@ -257,8 +256,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_DictionaryRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(); @@ -283,13 +282,14 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_WithNewTranslation_On_DictionaryRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var localizationService = GetRequiredService(); + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(); - var languageNo = new Language(TestObjects.GetGlobalSettings(), "nb-NO") { CultureName = "nb-NO" }; - ServiceContext.LocalizationService.Save(languageNo); + var languageNo = new Language(GlobalSettings, "nb-NO") { CultureName = "nb-NO" }; + localizationService.Save(languageNo); // Act var item = repository.Get(1); @@ -312,8 +312,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_DictionaryRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(); @@ -332,8 +332,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_DictionaryRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(); @@ -350,8 +350,8 @@ namespace Umbraco.Tests.Persistence.Repositories { Dictionary keyMap; - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(); keyMap = repository.GetDictionaryItemKeyMap(); @@ -363,18 +363,13 @@ namespace Umbraco.Tests.Persistence.Repositories Console.WriteLine("{0}: {1}", kvp.Key, kvp.Value); } - [TearDown] - public override void TearDown() - { - base.TearDown(); - } - public void CreateTestData() { - var language = ServiceContext.LocalizationService.GetLanguageByIsoCode("en-US"); + var localizationService = GetRequiredService(); + var language = localizationService.GetLanguageByIsoCode("en-US"); - var languageDK = new Language(TestObjects.GetGlobalSettings(), "da-DK") { CultureName = "da-DK" }; - ServiceContext.LocalizationService.Save(languageDK);//Id 2 + var languageDK = new Language(GlobalSettings, "da-DK") { CultureName = "da-DK" }; + localizationService.Save(languageDK);//Id 2 var readMore = new DictionaryItem("Read More"); var translations = new List @@ -383,7 +378,7 @@ namespace Umbraco.Tests.Persistence.Repositories new DictionaryTranslation(languageDK, "Læs mere") }; readMore.Translations = translations; - ServiceContext.LocalizationService.Save(readMore);//Id 1 + localizationService.Save(readMore);//Id 1 var article = new DictionaryItem("Article"); var translations2 = new List @@ -392,7 +387,7 @@ namespace Umbraco.Tests.Persistence.Repositories new DictionaryTranslation(languageDK, "Artikel") }; article.Translations = translations2; - ServiceContext.LocalizationService.Save(article);//Id 2 + localizationService.Save(article);//Id 2 } } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/EntityRepositoryTest.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/EntityRepositoryTest.cs similarity index 71% rename from src/Umbraco.Tests/Persistence/Repositories/EntityRepositoryTest.cs rename to src/Umbraco.Tests.Integration/Persistence/Repositories/EntityRepositoryTest.cs index a4df5bcf78..678e33d34b 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/EntityRepositoryTest.cs +++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/EntityRepositoryTest.cs @@ -4,20 +4,19 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; -using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; -using Umbraco.Tests.TestHelpers; +using Umbraco.Core.Services; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Persistence.Repositories +namespace Umbraco.Tests.Integration.Persistence.Repositories { [TestFixture] [UmbracoTest(Mapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class EntityRepositoryTest : TestWithDatabaseBase + public class EntityRepositoryTest : UmbracoIntegrationTest { - private EntityRepository CreateRepository(IScopeAccessor scopeAccessor) { var entityRepository = new EntityRepository(scopeAccessor); @@ -29,36 +28,44 @@ namespace Umbraco.Tests.Persistence.Repositories { //Create content + var contentService = GetRequiredService(); + var contentTypeService = GetRequiredService(); var createdContent = new List(); var contentType = MockedContentTypes.CreateBasicContentType("blah"); - ServiceContext.ContentTypeService.Save(contentType); - for (int i = 0; i < 10; i++) + contentTypeService.Save(contentType); + for (var i = 0; i < 10; i++) { var c1 = MockedContent.CreateBasicContent(contentType); - ServiceContext.ContentService.Save(c1); + contentService.Save(c1); createdContent.Add(c1); } //Create media - + + var mediaService = GetRequiredService(); + var mediaTypeService = GetRequiredService(); var createdMedia = new List(); var imageType = MockedContentTypes.CreateImageMediaType("myImage"); - ServiceContext.MediaTypeService.Save(imageType); - for (int i = 0; i < 10; i++) + mediaTypeService.Save(imageType); + for (var i = 0; i < 10; i++) { var c1 = MockedMedia.CreateMediaImage(imageType, -1); - ServiceContext.MediaService.Save(c1); + mediaService.Save(c1); createdMedia.Add(c1); } // Create members - var memberType = MockedContentTypes.CreateSimpleMemberType("simple"); - ServiceContext.MemberTypeService.Save(memberType); - var createdMembers = MockedMember.CreateSimpleMember(memberType, 10).ToList(); - ServiceContext.MemberService.Save(createdMembers); - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var memberService = GetRequiredService(); + var memberTypeService = GetRequiredService(); + var memberType = MockedContentTypes.CreateSimpleMemberType("simple"); + memberTypeService.Save(memberType); + var createdMembers = MockedMember.CreateSimpleMember(memberType, 10).ToList(); + memberService.Save(createdMembers); + + + var provider = ScopeProvider; + using (provider.CreateScope()) { var repo = CreateRepository((IScopeAccessor)provider); @@ -66,7 +73,7 @@ namespace Umbraco.Tests.Persistence.Repositories var objectTypes = new[] { Constants.ObjectTypes.Document, Constants.ObjectTypes.Media, Constants.ObjectTypes.Member }; - var query = SqlContext.Query() + var query = provider.SqlContext.Query() .WhereIn(e => e.Id, ids); var entities = repo.GetPagedResultsByQuery(query, objectTypes, 0, 20, out var totalRecords, null, null).ToList(); @@ -88,8 +95,6 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.AreEqual(10, mediaEntities.Count); Assert.AreEqual(10, memberEntities.Count); } - } - } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/KeyValueRepositoryTests.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/KeyValueRepositoryTests.cs similarity index 90% rename from src/Umbraco.Tests/Persistence/Repositories/KeyValueRepositoryTests.cs rename to src/Umbraco.Tests.Integration/Persistence/Repositories/KeyValueRepositoryTests.cs index 50ebc7ff5d..c756b6273b 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/KeyValueRepositoryTests.cs +++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/KeyValueRepositoryTests.cs @@ -4,19 +4,19 @@ using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; -using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Persistence.Repositories +namespace Umbraco.Tests.Integration.Persistence.Repositories { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class KeyValueRepositoryTests : TestWithDatabaseBase + public class KeyValueRepositoryTests : UmbracoIntegrationTest { [Test] public void CanSetAndGet() { - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; // Insert new key/value using (var scope = provider.CreateScope()) diff --git a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/LanguageRepositoryTest.cs similarity index 72% rename from src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs rename to src/Umbraco.Tests.Integration/Persistence/Repositories/LanguageRepositoryTest.cs index b1dbe7b6e0..e127a58cee 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs +++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/LanguageRepositoryTest.cs @@ -1,41 +1,39 @@ using System; using System.Globalization; using System.Linq; -using Moq; using NUnit.Framework; using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; -using Umbraco.Tests.TestHelpers; +using Umbraco.Core.Services; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Persistence.Repositories +namespace Umbraco.Tests.Integration.Persistence.Repositories { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class LanguageRepositoryTest : TestWithDatabaseBase + public class LanguageRepositoryTest : UmbracoIntegrationTest { - public override void SetUp() + [SetUp] + public void SetUp() { - base.SetUp(); - CreateTestData(); } private LanguageRepository CreateRepository(IScopeProvider provider) { - return new LanguageRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), TestObjects.GetGlobalSettings()); + return new LanguageRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, GlobalSettings); } [Test] public void Can_Perform_Get_On_LanguageRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; using (var scope = provider.CreateScope()) { scope.Database.AsUmbracoDatabase().EnableSqlTrace = true; @@ -56,13 +54,13 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Perform_Get_By_Iso_Code_On_LanguageRepository() { - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); var au = CultureInfo.GetCultureInfo("en-AU"); - var language = (ILanguage)new Language(TestObjects.GetGlobalSettings(), au.Name) + var language = (ILanguage)new Language(GlobalSettings, au.Name) { CultureName = au.DisplayName, FallbackLanguageId = 1 @@ -85,8 +83,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Get_When_Id_Doesnt_Exist_Returns_Null() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -102,8 +100,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_LanguageRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -122,8 +120,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_LanguageRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -142,7 +140,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_LanguageRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -162,7 +160,7 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_LanguageRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -180,13 +178,13 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_LanguageRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); // Act - var languageBR = new Language(TestObjects.GetGlobalSettings(), "pt-BR") { CultureName = "pt-BR" }; + var languageBR = new Language(GlobalSettings, "pt-BR") { CultureName = "pt-BR" }; repository.Save(languageBR); // Assert @@ -202,13 +200,13 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_LanguageRepository_With_Boolean_Properties() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); // Act - var languageBR = new Language(TestObjects.GetGlobalSettings(), "pt-BR") { CultureName = "pt-BR", IsDefault = true, IsMandatory = true }; + var languageBR = new Language(GlobalSettings, "pt-BR") { CultureName = "pt-BR", IsDefault = true, IsMandatory = true }; repository.Save(languageBR); // Assert @@ -224,17 +222,17 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_LanguageRepository_With_Fallback_Language() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); // Act - var languageBR = new Language(TestObjects.GetGlobalSettings(), "pt-BR") - { - CultureName = "pt-BR", - FallbackLanguageId = 1 - }; + var languageBR = new Language(GlobalSettings, "pt-BR") + { + CultureName = "pt-BR", + FallbackLanguageId = 1 + }; repository.Save(languageBR); // Assert @@ -248,21 +246,21 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_LanguageRepository_With_New_Default() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); - var languageBR = (ILanguage)new Language(TestObjects.GetGlobalSettings(), "pt-BR") { CultureName = "pt-BR", IsDefault = true, IsMandatory = true }; + var languageBR = (ILanguage)new Language(GlobalSettings, "pt-BR") { CultureName = "pt-BR", IsDefault = true, IsMandatory = true }; repository.Save(languageBR); - var languageEN = new Language(TestObjects.GetGlobalSettings(), "en-AU") { CultureName = "en-AU" }; + var languageEN = new Language(GlobalSettings, "en-AU") { CultureName = "en-AU" }; repository.Save(languageEN); Assert.IsTrue(languageBR.IsDefault); Assert.IsTrue(languageBR.IsMandatory); // Act - var languageNZ = new Language(TestObjects.GetGlobalSettings(), "en-NZ") { CultureName = "en-NZ", IsDefault = true, IsMandatory = true }; + var languageNZ = new Language(GlobalSettings, "en-NZ") { CultureName = "en-NZ", IsDefault = true, IsMandatory = true }; repository.Save(languageNZ); languageBR = repository.Get(languageBR.Id); @@ -276,8 +274,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_LanguageRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -303,8 +301,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Perform_Update_With_Existing_Culture() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -321,8 +319,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_LanguageRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -341,8 +339,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_LanguageRepository_With_Language_Used_As_Fallback() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { // Add language to delete as a fall-back language to another one var repository = CreateRepository(provider); @@ -365,8 +363,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_LanguageRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -380,27 +378,22 @@ namespace Umbraco.Tests.Persistence.Repositories } } - [TearDown] - public override void TearDown() - { - base.TearDown(); - } - private void CreateTestData() { //Id 1 is en-US - when Umbraco is installed - var languageDK = new Language(TestObjects.GetGlobalSettings(), "da-DK") { CultureName = "da-DK" }; - ServiceContext.LocalizationService.Save(languageDK);//Id 2 + var localizationService = GetRequiredService(); + var languageDK = new Language(GlobalSettings, "da-DK") { CultureName = "da-DK" }; + localizationService.Save(languageDK);//Id 2 - var languageSE = new Language(TestObjects.GetGlobalSettings(), "sv-SE") { CultureName = "sv-SE" }; - ServiceContext.LocalizationService.Save(languageSE);//Id 3 + var languageSE = new Language(GlobalSettings, "sv-SE") { CultureName = "sv-SE" }; + localizationService.Save(languageSE);//Id 3 - var languageDE = new Language(TestObjects.GetGlobalSettings(), "de-DE") { CultureName = "de-DE" }; - ServiceContext.LocalizationService.Save(languageDE);//Id 4 + var languageDE = new Language(GlobalSettings, "de-DE") { CultureName = "de-DE" }; + localizationService.Save(languageDE);//Id 4 - var languagePT = new Language(TestObjects.GetGlobalSettings(), "pt-PT") { CultureName = "pt-PT" }; - ServiceContext.LocalizationService.Save(languagePT);//Id 5 + var languagePT = new Language(GlobalSettings, "pt-PT") { CultureName = "pt-PT" }; + localizationService.Save(languagePT);//Id 5 } } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/MacroRepositoryTest.cs similarity index 75% rename from src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs rename to src/Umbraco.Tests.Integration/Persistence/Repositories/MacroRepositoryTest.cs index facfb9c012..624fd9c566 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs +++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/MacroRepositoryTest.cs @@ -1,30 +1,23 @@ -using System.Data.SqlServerCe; +using System.Data.SqlClient; using System.Linq; -using Moq; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Persistence; - using Umbraco.Core.Persistence.Querying; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; -using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Persistence.Repositories +namespace Umbraco.Tests.Integration.Persistence.Repositories { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class MacroRepositoryTest : TestWithDatabaseBase + public class MacroRepositoryTest : UmbracoIntegrationTest { - public override void SetUp() + [SetUp] + public void SetUp() { - base.SetUp(); - CreateTestData(); } @@ -32,44 +25,41 @@ namespace Umbraco.Tests.Persistence.Repositories public void Cannot_Add_Duplicate_Macros() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); var macro = new Macro(ShortStringHelper, "test1", "Test", "~/views/macropartials/test.cshtml"); - ; - Assert.Throws(() => repository.Save(macro)); + Assert.Throws(() => repository.Save(macro)); } - } [Test] public void Cannot_Update_To_Duplicate_Macro_Alias() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); var macro = repository.Get(1); macro.Alias = "test2"; - Assert.Throws(() => repository.Save(macro)); + Assert.Throws(() => repository.Save(macro)); } - } [Test] public void Can_Instantiate_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); // Assert Assert.That(repository, Is.Not.Null); @@ -80,10 +70,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); // Act var macro = repository.Get(1); @@ -100,18 +90,16 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.That(macro.MacroSource, Is.EqualTo("~/views/macropartials/test1.cshtml")); Assert.That(macro.UseInEditor, Is.EqualTo(false)); } - - } [Test] public void Can_Perform_GetAll_On_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); // Act var macros = repository.GetMany(); @@ -119,21 +107,20 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(macros.Count(), Is.EqualTo(3)); } - } [Test] public void Can_Perform_GetByQuery_On_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); // Act var query = scope.SqlContext.Query().Where(x => x.Alias.ToUpper() == "TEST1"); - var result = repository.Get(query); + var result = repository.Get((IQuery) query); // Assert Assert.AreEqual(1, result.Count()); @@ -144,10 +131,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); // Act var query = scope.SqlContext.Query().Where(x => x.Name.StartsWith("Test")); @@ -162,10 +149,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); // Act var macro = new Macro(ShortStringHelper, "test", "Test", "~/views/macropartials/test.cshtml"); @@ -183,10 +170,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); // Act var macro = repository.Get(2); @@ -218,10 +205,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); // Act var macro = repository.Get(3); @@ -239,10 +226,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); // Act var exists = repository.Exists(3); @@ -258,10 +245,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Add_Property_For_Macro() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); var macro = repository.Get(1); macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test")); @@ -284,10 +271,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Add_New_Macro_With_Property() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); var macro = new Macro(ShortStringHelper, "newmacro", "A new macro", "~/views/macropartials/test1.cshtml"); macro.Properties.Add(new MacroProperty("blah1", "New1", 4, "test.editor")); @@ -309,10 +296,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Remove_Macro_Property() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); var macro = new Macro(ShortStringHelper, "newmacro", "A new macro", "~/views/macropartials/test1.cshtml"); macro.Properties.Add(new MacroProperty("blah1", "New1", 4, "test.editor")); @@ -333,10 +320,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Add_Remove_Macro_Properties() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); var macro = new Macro(ShortStringHelper, "newmacro", "A new macro", "~/views/macropartials/test1.cshtml"); var prop1 = new MacroProperty("blah1", "New1", 4, "test.editor"); @@ -364,10 +351,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Update_Property_For_Macro() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); var macro = repository.Get(1); macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test")); @@ -391,10 +378,10 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Update_Macro_Property_Alias() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = provider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); var macro = repository.Get(1); macro.Properties.Add(new MacroProperty("new1", "New1", 3, "test")); @@ -411,25 +398,18 @@ namespace Umbraco.Tests.Persistence.Repositories } } - [TearDown] - public override void TearDown() - { - base.TearDown(); - } - public void CreateTestData() { - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; using (var scope = provider.CreateScope()) { - var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), ShortStringHelper); + var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, ShortStringHelper); repository.Save(new Macro(ShortStringHelper, "test1", "Test1", "~/views/macropartials/test1.cshtml")); repository.Save(new Macro(ShortStringHelper, "test2", "Test2", "~/views/macropartials/test2.cshtml")); repository.Save(new Macro(ShortStringHelper, "test3", "Tet3", "~/views/macropartials/test3.cshtml")); scope.Complete(); } - } } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/NotificationsRepositoryTest.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/NotificationsRepositoryTest.cs similarity index 93% rename from src/Umbraco.Tests/Persistence/Repositories/NotificationsRepositoryTest.cs rename to src/Umbraco.Tests.Integration/Persistence/Repositories/NotificationsRepositoryTest.cs index 12fa1bb9bb..2735f869c0 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/NotificationsRepositoryTest.cs +++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/NotificationsRepositoryTest.cs @@ -7,22 +7,21 @@ using Umbraco.Core; using Umbraco.Core.Models.Entities; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.Dtos; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; -using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Persistence.Repositories +namespace Umbraco.Tests.Integration.Persistence.Repositories { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class NotificationsRepositoryTest : TestWithDatabaseBase + public class NotificationsRepositoryTest : UmbracoIntegrationTest { [Test] public void CreateNotification() { - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; using (var scope = provider.CreateScope()) { var repo = new NotificationsRepository((IScopeAccessor) provider); @@ -56,10 +55,9 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void GetUserNotifications() { - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; using (var scope = provider.CreateScope()) { - var repo = new NotificationsRepository((IScopeAccessor) provider); var userDto = new UserDto { Email = "test", Login = "test", Password = "test", UserName = "test", UserLanguage = "en", CreateDate = DateTime.Now, UpdateDate = DateTime.Now }; @@ -85,10 +83,9 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void GetEntityNotifications() { - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; using (var scope = provider.CreateScope()) { - var repo = new NotificationsRepository((IScopeAccessor) provider); var node1 = new NodeDto { CreateDate = DateTime.Now, Level = 1, NodeObjectType = Constants.ObjectTypes.ContentItem, ParentId = -1, Path = "-1,1", SortOrder = 1, Text = "hello1", Trashed = false, UniqueId = Guid.NewGuid(), UserId = -1 }; @@ -115,10 +112,9 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Delete_By_Entity() { - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; using (var scope = provider.CreateScope()) { - var repo = new NotificationsRepository((IScopeAccessor) provider); var node1 = new NodeDto { CreateDate = DateTime.Now, Level = 1, NodeObjectType = Constants.ObjectTypes.ContentItem, ParentId = -1, Path = "-1,1", SortOrder = 1, Text = "hello1", Trashed = false, UniqueId = Guid.NewGuid(), UserId = -1 }; @@ -145,10 +141,9 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Delete_By_User() { - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; using (var scope = provider.CreateScope()) { - var repo = new NotificationsRepository((IScopeAccessor) provider); var userDto = new UserDto { Email = "test", Login = "test", Password = "test", UserName = "test", UserLanguage = "en", CreateDate = DateTime.Now, UpdateDate = DateTime.Now }; diff --git a/src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/RedirectUrlRepositoryTests.cs similarity index 87% rename from src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs rename to src/Umbraco.Tests.Integration/Persistence/Repositories/RedirectUrlRepositoryTests.cs index 652209b65b..18cbb01c0e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RedirectUrlRepositoryTests.cs +++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/RedirectUrlRepositoryTests.cs @@ -1,32 +1,31 @@ using System; using System.Linq; using NUnit.Framework; -using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; -using Umbraco.Tests.TestHelpers; +using Umbraco.Core.Services; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Persistence.Repositories +namespace Umbraco.Tests.Integration.Persistence.Repositories { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class RedirectUrlRepositoryTests : TestWithDatabaseBase + public class RedirectUrlRepositoryTests : UmbracoIntegrationTest { - public override void SetUp() + [SetUp] + public void SetUp() { - base.SetUp(); - CreateTestData(); } [Test] public void CanSaveAndGet() { - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; using (var scope = provider.CreateScope()) { @@ -56,7 +55,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void CanSaveAndGetMostRecent() { - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; Assert.AreNotEqual(_textpage.Id, _otherpage.Id); @@ -104,7 +103,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void CanSaveAndGetByContent() { - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; using (var scope = provider.CreateScope()) { @@ -148,7 +147,7 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void CanSaveAndDelete() { - var provider = TestObjects.GetScopeProvider(Logger); + var provider = ScopeProvider; using (var scope = provider.CreateScope()) { @@ -195,32 +194,35 @@ namespace Umbraco.Tests.Persistence.Repositories public void CreateTestData() { + var fileService = GetRequiredService(); + var contentService = GetRequiredService(); + var contentTypeService = GetRequiredService(); //Create and Save ContentType "umbTextpage" -> (NodeDto.NodeIdSeed) var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage", "Textpage"); contentType.Key = Guid.NewGuid(); - ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate); // else, FK violation on contentType! - ServiceContext.ContentTypeService.Save(contentType); + fileService.SaveTemplate(contentType.DefaultTemplate); // else, FK violation on contentType! + contentTypeService.Save(contentType); //Create and Save Content "Homepage" based on "umbTextpage" -> (NodeDto.NodeIdSeed + 1) _textpage = MockedContent.CreateSimpleContent(contentType); _textpage.Key = Guid.NewGuid(); - ServiceContext.ContentService.Save(_textpage); + contentService.Save(_textpage); //Create and Save Content "Text Page 1" based on "umbTextpage" -> (NodeDto.NodeIdSeed + 2) _subpage = MockedContent.CreateSimpleContent(contentType, "Text Page 1", _textpage.Id); _subpage.Key = Guid.NewGuid(); - ServiceContext.ContentService.Save(_subpage); + contentService.Save(_subpage); //Create and Save Content "Text Page 1" based on "umbTextpage" -> (NodeDto.NodeIdSeed + 3) _otherpage = MockedContent.CreateSimpleContent(contentType, "Text Page 2", _textpage.Id); _otherpage.Key = Guid.NewGuid(); - ServiceContext.ContentService.Save(_otherpage); + contentService.Save(_otherpage); //Create and Save Content "Text Page Deleted" based on "umbTextpage" -> (NodeDto.NodeIdSeed + 4) _trashed = MockedContent.CreateSimpleContent(contentType, "Text Page Deleted", -20); _trashed.Key = Guid.NewGuid(); ((Content) _trashed).Trashed = true; - ServiceContext.ContentService.Save(_trashed); + contentService.Save(_trashed); } } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/RelationTypeRepositoryTest.cs similarity index 78% rename from src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs rename to src/Umbraco.Tests.Integration/Persistence/Repositories/RelationTypeRepositoryTest.cs index edde8e8f81..9a08c3f9c8 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/RelationTypeRepositoryTest.cs +++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/RelationTypeRepositoryTest.cs @@ -1,43 +1,36 @@ -using System; -using System.Linq; -using Moq; +using System.Linq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Dtos; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; -using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Persistence.Repositories +namespace Umbraco.Tests.Integration.Persistence.Repositories { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class RelationTypeRepositoryTest : TestWithDatabaseBase + public class RelationTypeRepositoryTest : UmbracoIntegrationTest { - public override void SetUp() + [SetUp] + public void SetUp() { - base.SetUp(); - CreateTestData(); } private RelationTypeRepository CreateRepository(IScopeProvider provider) { - return new RelationTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); + return new RelationTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger); } - [Test] public void Can_Perform_Add_On_RelationTypeRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -56,8 +49,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_RelationTypeRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -81,8 +74,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_RelationTypeRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -101,13 +94,13 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_RelationTypeRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); // Act - var relationType = repository.Get(RelationTypeDto.NodeIdSeed + 2); + var relationType = repository.Get(8); // Assert Assert.That(relationType, Is.Not.Null); @@ -124,8 +117,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_RelationTypeRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -144,8 +137,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_With_Params_On_RelationTypeRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -164,14 +157,14 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_RelationTypeRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); // Act var exists = repository.Exists(3); - var doesntExist = repository.Exists(6); + var doesntExist = repository.Exists(9); // Assert Assert.That(exists, Is.True); @@ -183,8 +176,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_RelationTypeRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -201,8 +194,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_RelationTypeRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -219,22 +212,16 @@ namespace Umbraco.Tests.Persistence.Repositories } } - [TearDown] - public override void TearDown() - { - base.TearDown(); - } - public void CreateTestData() { var relateContent = new RelationType("Relate Content on Copy", "relateContentOnCopy", true, Constants.ObjectTypes.Document, Constants.ObjectTypes.Document); var relateContentType = new RelationType("Relate ContentType on Copy", "relateContentTypeOnCopy", true, Constants.ObjectTypes.DocumentType, Constants.ObjectTypes.DocumentType); var relateContentMedia = new RelationType("Relate Content to Media", "relateContentToMedia", true, Constants.ObjectTypes.Document, Constants.ObjectTypes.Media); - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { - var repository = new RelationTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); + var repository = new RelationTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger); repository.Save(relateContent);//Id 2 repository.Save(relateContentType);//Id 3 diff --git a/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/ServerRegistrationRepositoryTest.cs similarity index 76% rename from src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs rename to src/Umbraco.Tests.Integration/Persistence/Repositories/ServerRegistrationRepositoryTest.cs index b84a79b3d1..0ac8b3a829 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ServerRegistrationRepositoryTest.cs +++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/ServerRegistrationRepositoryTest.cs @@ -1,27 +1,25 @@ using System; -using System.Data.SqlServerCe; +using System.Data.SqlClient; using System.Linq; using NUnit.Framework; using Umbraco.Core.Cache; using Umbraco.Core.Models; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; -using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Persistence.Repositories +namespace Umbraco.Tests.Integration.Persistence.Repositories { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class ServerRegistrationRepositoryTest : TestWithDatabaseBase + public class ServerRegistrationRepositoryTest : UmbracoIntegrationTest { private AppCaches _appCaches; - public override void SetUp() + [SetUp] + public void SetUp() { - base.SetUp(); - _appCaches = AppCaches.Disabled; CreateTestData(); } @@ -35,41 +33,39 @@ namespace Umbraco.Tests.Persistence.Repositories public void Cannot_Add_Duplicate_Server_Identities() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); var server = new ServerRegistration("http://shazwazza.com", "COMPUTER1", DateTime.Now); - Assert.Throws(() => repository.Save(server)); + Assert.Throws(() => repository.Save(server)); } - } [Test] public void Cannot_Update_To_Duplicate_Server_Identities() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); var server = repository.Get(1); server.ServerIdentity = "COMPUTER2"; - Assert.Throws(() => repository.Save(server)); + Assert.Throws(() => repository.Save(server)); } - } [Test] public void Can_Instantiate_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -82,8 +78,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -95,16 +91,14 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.That(server.HasIdentity, Is.True); Assert.That(server.ServerAddress, Is.EqualTo("http://localhost")); } - - } [Test] public void Can_Perform_GetAll_On_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -114,7 +108,6 @@ namespace Umbraco.Tests.Persistence.Repositories // Assert Assert.That(servers.Count(), Is.EqualTo(3)); } - } // queries are not supported due to in-memory caching @@ -123,7 +116,7 @@ namespace Umbraco.Tests.Persistence.Repositories //public void Can_Perform_GetByQuery_On_Repository() //{ // // Arrange - // var provider = TestObjects.GetScopeProvider(Logger); + // var provider = ScopeProvider; // using (var unitOfWork = provider.GetUnitOfWork()) // using (var repository = CreateRepository(provider)) // { @@ -140,7 +133,7 @@ namespace Umbraco.Tests.Persistence.Repositories //public void Can_Perform_Count_On_Repository() //{ // // Arrange - // var provider = TestObjects.GetScopeProvider(Logger); + // var provider = ScopeProvider; // using (var unitOfWork = provider.GetUnitOfWork()) // using (var repository = CreateRepository(provider)) // { @@ -157,8 +150,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_On_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -176,8 +169,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -201,8 +194,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -222,8 +215,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_Repository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -237,16 +230,10 @@ namespace Umbraco.Tests.Persistence.Repositories } } - [TearDown] - public override void TearDown() - { - base.TearDown(); - } - public void CreateTestData() { - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -255,7 +242,6 @@ namespace Umbraco.Tests.Persistence.Repositories repository.Save(new ServerRegistration("https://www.another.domain.com", "Computer3", DateTime.Now)); scope.Complete(); } - } } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/SimilarNodeNameTests.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/SimilarNodeNameTests.cs similarity index 97% rename from src/Umbraco.Tests/Persistence/Repositories/SimilarNodeNameTests.cs rename to src/Umbraco.Tests.Integration/Persistence/Repositories/SimilarNodeNameTests.cs index 582e5a4815..b60709c8bf 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/SimilarNodeNameTests.cs +++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/SimilarNodeNameTests.cs @@ -1,9 +1,8 @@ using System.Linq; using NUnit.Framework; -using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; -namespace Umbraco.Tests.Persistence.Repositories +namespace Umbraco.Tests.Integration.Persistence.Repositories { [TestFixture] public class SimilarNodeNameTests @@ -36,8 +35,6 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.IsTrue(result > 0, "Expected >0 but was " + result); } - - [Test] public void OrderByTest() { diff --git a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/TemplateRepositoryTest.cs similarity index 84% rename from src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs rename to src/Umbraco.Tests.Integration/Persistence/Repositories/TemplateRepositoryTest.cs index b7c1f6a2a8..ebab6e5d17 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs +++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/TemplateRepositoryTest.cs @@ -7,23 +7,23 @@ using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.Composing; -using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; -using Umbraco.Tests.TestHelpers; +using Umbraco.Core.Services; +using Umbraco.Tests.Integration.Implementations; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Persistence.Repositories +namespace Umbraco.Tests.Integration.Persistence.Repositories { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class TemplateRepositoryTest : TestWithDatabaseBase + public class TemplateRepositoryTest : UmbracoIntegrationTest { private IFileSystems _fileSystems; @@ -32,12 +32,12 @@ namespace Umbraco.Tests.Persistence.Repositories return new TemplateRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, _fileSystems, IOHelper, ShortStringHelper); } - public override void SetUp() + [SetUp] + public void SetUp() { - base.SetUp(); - + var testHelper = new TestHelper(); _fileSystems = Mock.Of(); - var viewsFileSystem = new PhysicalFileSystem(IOHelper, HostingEnvironment, Logger, Constants.SystemDirectories.MvcViews); + var viewsFileSystem = new PhysicalFileSystem(IOHelper, testHelper.GetHostingEnvironment(), Logger, Constants.SystemDirectories.MvcViews); Mock.Get(_fileSystems).Setup(x => x.MvcViewsFileSystem).Returns(viewsFileSystem); } @@ -45,9 +45,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Instantiate_Repository() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); // Assert Assert.That(repository, Is.Not.Null); @@ -58,9 +60,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_View() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); // Act var template = new Template(ShortStringHelper, "test", "test"); @@ -77,9 +81,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_View_With_Default_Content() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); // Act var template = new Template(ShortStringHelper, "test", "test") @@ -101,9 +107,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_View_With_Default_Content_With_Parent() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); //NOTE: This has to be persisted first var template = new Template(ShortStringHelper, "test", "test"); @@ -127,9 +135,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Add_Unique_Alias() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); // Act var template = new Template(ShortStringHelper, "test", "test") @@ -153,9 +163,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_Unique_Alias() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); // Act var template = new Template(ShortStringHelper, "test", "test") @@ -184,9 +196,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_View() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); // Act var template = new Template(ShortStringHelper, "test", "test") @@ -210,9 +224,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_View() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); var template = new Template(ShortStringHelper, "test", "test") { @@ -235,23 +251,28 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_When_Assigned_To_Doc() { // Arrange - using (ScopeProvider.CreateScope()) - { - var templateRepository = CreateRepository(ScopeProvider); + var provider = ScopeProvider; + var scopeAccessor = (IScopeAccessor) provider; + var dataTypeService = GetRequiredService(); + var fileService = GetRequiredService(); - var tagRepository = new TagRepository(ScopeProvider, AppCaches.Disabled, Logger); - var commonRepository = new ContentTypeCommonRepository(ScopeProvider, templateRepository, AppCaches, ShortStringHelper); - var languageRepository = new LanguageRepository(ScopeProvider, AppCaches.Disabled, Logger, TestObjects.GetGlobalSettings()); - var contentTypeRepository = new ContentTypeRepository(ScopeProvider, AppCaches.Disabled, Logger, commonRepository, languageRepository, ShortStringHelper); - var relationTypeRepository = new RelationTypeRepository(ScopeProvider, AppCaches.Disabled, Logger); - var entityRepository = new EntityRepository(ScopeProvider); - var relationRepository = new RelationRepository(ScopeProvider, Logger, relationTypeRepository, entityRepository); + using (provider.CreateScope()) + { + var templateRepository = CreateRepository(provider); + + var tagRepository = new TagRepository(scopeAccessor, AppCaches.Disabled, Logger); + var commonRepository = new ContentTypeCommonRepository(scopeAccessor, templateRepository, AppCaches, ShortStringHelper); + var languageRepository = new LanguageRepository(scopeAccessor, AppCaches.Disabled, Logger, GlobalSettings); + var contentTypeRepository = new ContentTypeRepository(scopeAccessor, AppCaches.Disabled, Logger, commonRepository, languageRepository, ShortStringHelper); + var relationTypeRepository = new RelationTypeRepository(scopeAccessor, AppCaches.Disabled, Logger); + var entityRepository = new EntityRepository(scopeAccessor); + var relationRepository = new RelationRepository(scopeAccessor, Logger, relationTypeRepository, entityRepository); var propertyEditors = new Lazy(() => new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty()))); var dataValueReferences = new DataValueReferenceFactoryCollection(Enumerable.Empty()); - var contentRepo = new DocumentRepository(ScopeProvider, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors, dataValueReferences, DataTypeService); + var contentRepo = new DocumentRepository(scopeAccessor, AppCaches.Disabled, Logger, contentTypeRepository, templateRepository, tagRepository, languageRepository, relationRepository, relationTypeRepository, propertyEditors, dataValueReferences, dataTypeService); var contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage2", "Textpage"); - ServiceContext.FileService.SaveTemplate(contentType.DefaultTemplate); // else, FK violation on contentType! + fileService.SaveTemplate(contentType.DefaultTemplate); // else, FK violation on contentType! contentTypeRepository.Save(contentType); var textpage = MockedContent.CreateSimpleContent(contentType); contentRepo.Save(textpage); @@ -278,9 +299,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Delete_On_Nested_Templates() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); var parent = new Template(ShortStringHelper, "parent", "parent") { @@ -315,9 +338,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_All() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); var created = CreateHierarchy(repository).ToArray(); @@ -342,9 +367,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_Children() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); var created = CreateHierarchy(repository).ToArray(); @@ -364,9 +391,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_Children_At_Root() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); CreateHierarchy(repository).ToArray(); @@ -383,9 +412,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Get_Descendants() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); var created = CreateHierarchy(repository).ToArray(); // Act @@ -405,9 +436,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Path_Is_Set_Correctly_On_Creation() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); var parent = new Template(ShortStringHelper, "parent", "parent"); var child1 = new Template(ShortStringHelper, "child1", "child1"); @@ -465,9 +498,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Path_Is_Set_Correctly_On_Update() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); var parent = new Template(ShortStringHelper, "parent", "parent"); var child1 = new Template(ShortStringHelper, "child1", "child1"); @@ -503,9 +538,11 @@ namespace Umbraco.Tests.Persistence.Repositories public void Path_Is_Set_Correctly_On_Update_With_Master_Template_Removal() { // Arrange - using (ScopeProvider.CreateScope()) + var provider = ScopeProvider; + + using (provider.CreateScope()) { - var repository = CreateRepository(ScopeProvider); + var repository = CreateRepository(provider); var parent = new Template(ShortStringHelper, "parent", "parent"); var child1 = new Template(ShortStringHelper, "child1", "child1"); @@ -526,14 +563,13 @@ namespace Umbraco.Tests.Persistence.Repositories } [TearDown] - public override void TearDown() + public void TearDown() { - base.TearDown(); - + var testHelper = new TestHelper(); _fileSystems = null; //Delete all files - var fsViews = new PhysicalFileSystem(IOHelper, HostingEnvironment, Logger, Constants.SystemDirectories.MvcViews); + var fsViews = new PhysicalFileSystem(IOHelper, testHelper.GetHostingEnvironment(), Logger, Constants.SystemDirectories.MvcViews); var views = fsViews.GetFiles("", "*.cshtml"); foreach (var file in views) fsViews.DeleteFile(file); diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs b/src/Umbraco.Tests.Integration/Persistence/Repositories/UserGroupRepositoryTest.cs similarity index 83% rename from src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs rename to src/Umbraco.Tests.Integration/Persistence/Repositories/UserGroupRepositoryTest.cs index a051980ad2..b18d1a95c2 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserGroupRepositoryTest.cs +++ b/src/Umbraco.Tests.Integration/Persistence/Repositories/UserGroupRepositoryTest.cs @@ -1,33 +1,30 @@ -using System; -using System.Linq; -using Moq; +using System.Linq; using NUnit.Framework; -using Umbraco.Core.Logging; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; -using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.Integration.Testing; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; -namespace Umbraco.Tests.Persistence.Repositories +namespace Umbraco.Tests.Integration.Persistence.Repositories { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] - public class UserGroupRepositoryTest : TestWithDatabaseBase + public class UserGroupRepositoryTest : UmbracoIntegrationTest { private UserGroupRepository CreateRepository(IScopeProvider provider) { - return new UserGroupRepository((IScopeAccessor) provider, Core.Cache.AppCaches.Disabled, Mock.Of(), ShortStringHelper); + return new UserGroupRepository((IScopeAccessor) provider, Core.Cache.AppCaches.Disabled, Logger, ShortStringHelper); } [Test] public void Can_Perform_Add_On_UserGroupRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -46,8 +43,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Multiple_Adds_On_UserGroupRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -70,8 +67,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Verify_Fresh_Entity_Is_Not_Dirty() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -80,7 +77,7 @@ namespace Umbraco.Tests.Persistence.Repositories scope.Complete(); // Act - var resolved = repository.Get(userGroup.Id); + var resolved = repository.Get((int) userGroup.Id); bool dirty = ((UserGroup)resolved).IsDirty(); // Assert @@ -92,22 +89,21 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Update_On_UserGroupRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); var userGroup = MockedUserGroup.CreateUserGroup(); repository.Save(userGroup); - // Act - var resolved = repository.Get(userGroup.Id); + var resolved = repository.Get((int) userGroup.Id); resolved.Name = "New Name"; resolved.Permissions = new[] { "Z", "Y", "X" }; repository.Save(resolved); scope.Complete(); - var updatedItem = repository.Get(userGroup.Id); + var updatedItem = repository.Get((int) userGroup.Id); // Assert Assert.That(updatedItem.Id, Is.EqualTo(resolved.Id)); @@ -119,8 +115,8 @@ namespace Umbraco.Tests.Persistence.Repositories [Test] public void Can_Perform_Delete_On_UserGroupRepository() { - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -135,7 +131,7 @@ namespace Umbraco.Tests.Persistence.Repositories repository2.Delete(userGroup); scope.Complete(); - var resolved = repository2.Get(id); + var resolved = repository2.Get((int) id); // Assert Assert.That(resolved, Is.Null); @@ -146,8 +142,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Get_On_UserGroupRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -156,7 +152,7 @@ namespace Umbraco.Tests.Persistence.Repositories scope.Complete(); // Act - var resolved = repository.Get(userGroup.Id); + var resolved = repository.Get((int) userGroup.Id); // Assert Assert.That(resolved.Id, Is.EqualTo(userGroup.Id)); @@ -172,8 +168,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetByQuery_On_UserGroupRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -192,8 +188,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_By_Param_Ids_On_UserGroupRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -213,8 +209,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_GetAll_On_UserGroupRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -234,8 +230,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Exists_On_UserGroupRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (provider.CreateScope()) { var repository = CreateRepository(provider); @@ -253,8 +249,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Perform_Count_On_UserGroupRepository() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -273,8 +269,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Remove_Section_For_Group() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -308,8 +304,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Add_Section_ForGroup() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -359,8 +355,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Can_Update_Section_For_Group() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); @@ -387,8 +383,8 @@ namespace Umbraco.Tests.Persistence.Repositories public void Get_Groups_Assigned_To_Section() { // Arrange - var provider = TestObjects.GetScopeProvider(Logger); - using (var scope = ScopeProvider.CreateScope()) + var provider = ScopeProvider; + using (var scope = provider.CreateScope()) { var repository = CreateRepository(provider); diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index a14eea1d91..fc7f4f4555 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -15,6 +15,7 @@ using Umbraco.Core.PropertyEditors; using System; using Umbraco.Core.Configuration; using Umbraco.Core.Serialization; +using MockedUser = Umbraco.Tests.TestHelpers.Entities.MockedUser; namespace Umbraco.Tests.Persistence.Repositories { diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 9a552d04d8..debdfd3c6b 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -139,18 +139,13 @@ - - - - - @@ -189,8 +184,6 @@ - - @@ -228,7 +221,6 @@ - @@ -294,12 +286,9 @@ - - - @@ -345,7 +334,6 @@ - @@ -373,12 +361,9 @@ - - - @@ -558,8 +543,7 @@ - - + From 19037d0a89c219fb44eb2d3623c48fd92df5b012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 20 Aug 2020 10:27:14 +0200 Subject: [PATCH 03/53] append date to the clipboard entry, and use it for sorting entries in the UI. --- .../src/common/services/clipboard.service.js | 95 +++++++++---------- .../umbBlockListPropertyEditor.component.js | 6 ++ .../nestedcontent/nestedcontent.controller.js | 10 +- 3 files changed, 61 insertions(+), 50 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js b/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js index cb583546a5..0d2ca6623b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js @@ -11,13 +11,13 @@ * */ function clipboardService(notificationsService, eventsService, localStorageService, iconHelper) { - + var clearPropertyResolvers = []; - + var STORAGE_KEY = "umbClipboardService"; - + var retriveStorage = function() { if (localStorageService.isSupported === false) { return null; @@ -27,32 +27,32 @@ function clipboardService(notificationsService, eventsService, localStorageServi if (dataString != null) { dataJSON = JSON.parse(dataString); } - + if(dataJSON == null) { dataJSON = new Object(); } - + if(dataJSON.entries === undefined) { dataJSON.entries = []; } - + return dataJSON; } - + var saveStorage = function(storage) { var storageString = JSON.stringify(storage); - + try { var storageJSON = JSON.parse(storageString); localStorageService.set(STORAGE_KEY, storageString); - + eventsService.emit("clipboardService.storageUpdate"); - + return true; } catch(e) { return false; } - + return false; } @@ -86,17 +86,17 @@ function clipboardService(notificationsService, eventsService, localStorageServi var isEntryCompatible = function(entry, type, allowedAliases) { return entry.type === type - && + && ( (entry.alias && allowedAliases.filter(allowedAlias => allowedAlias === entry.alias).length > 0) - || + || (entry.aliases && entry.aliases.filter(entryAlias => allowedAliases.filter(allowedAlias => allowedAlias === entryAlias).length > 0).length === entry.aliases.length) ); } - - + + var service = {}; - + /** * @ngdoc method @@ -160,29 +160,29 @@ function clipboardService(notificationsService, eventsService, localStorageServi * Saves a single JS-object with a type and alias to the clipboard. */ service.copy = function(type, alias, data, displayLabel, displayIcon, uniqueKey, firstLevelClearupMethod) { - + var storage = retriveStorage(); displayLabel = displayLabel || data.name; displayIcon = displayIcon || iconHelper.convertFromLegacyIcon(data.icon); uniqueKey = uniqueKey || data.key || console.error("missing unique key for this content"); - + // remove previous copies of this entry: storage.entries = storage.entries.filter( (entry) => { return entry.unique !== uniqueKey; } ); - - var entry = {unique:uniqueKey, type:type, alias:alias, data:prepareEntryForStorage(data, firstLevelClearupMethod), label:displayLabel, icon:displayIcon}; + + var entry = {unique:uniqueKey, type:type, alias:alias, data:prepareEntryForStorage(data, firstLevelClearupMethod), label:displayLabel, icon:displayIcon, date:Date.now()}; storage.entries.push(entry); - + if (saveStorage(storage) === true) { notificationsService.success("Clipboard", "Copied to clipboard."); } else { notificationsService.error("Clipboard", "Couldnt copy this data to clipboard."); } - + }; @@ -203,32 +203,31 @@ function clipboardService(notificationsService, eventsService, localStorageServi * Saves a single JS-object with a type and alias to the clipboard. */ service.copyArray = function(type, aliases, datas, displayLabel, displayIcon, uniqueKey, firstLevelClearupMethod) { - + var storage = retriveStorage(); - + // Clean up each entry var copiedDatas = datas.map(data => prepareEntryForStorage(data, firstLevelClearupMethod)); - + // remove previous copies of this entry: storage.entries = storage.entries.filter( (entry) => { return entry.unique !== uniqueKey; } ); - - var entry = {unique:uniqueKey, type:type, aliases:aliases, data:copiedDatas, label:displayLabel, icon:displayIcon}; + var entry = {unique:uniqueKey, type:type, aliases:aliases, data:copiedDatas, label:displayLabel, icon:displayIcon, date:Date.now()}; storage.entries.push(entry); - + if (saveStorage(storage) === true) { notificationsService.success("Clipboard", "Copied to clipboard."); } else { notificationsService.error("Clipboard", "Couldnt copy this data to clipboard."); } - + }; - - + + /** * @ngdoc method * @name umbraco.services.supportsCopy#supported @@ -240,7 +239,7 @@ function clipboardService(notificationsService, eventsService, localStorageServi service.isSupported = function() { return localStorageService.isSupported; }; - + /** * @ngdoc method * @name umbraco.services.supportsCopy#hasEntriesOfType @@ -253,14 +252,14 @@ function clipboardService(notificationsService, eventsService, localStorageServi * Determines whether the current clipboard has entries that match a given type and one of the aliases. */ service.hasEntriesOfType = function(type, aliases) { - + if(service.retriveEntriesOfType(type, aliases).length > 0) { return true; } - + return false; }; - + /** * @ngdoc method * @name umbraco.services.supportsCopy#retriveEntriesOfType @@ -268,24 +267,24 @@ function clipboardService(notificationsService, eventsService, localStorageServi * * @param {string} type A string defining the type of data to recive. * @param {string} aliases A array of strings providing the alias of the data you want to recive. - * + * * @description * Returns an array of entries matching the given type and one of the provided aliases. */ service.retriveEntriesOfType = function(type, allowedAliases) { - + var storage = retriveStorage(); - + // Find entries that are fulfilling the criteria for this nodeType and nodeTypesAliases. var filteretEntries = storage.entries.filter( (entry) => { return isEntryCompatible(entry, type, allowedAliases); } ); - + return filteretEntries; }; - + /** * @ngdoc method * @name umbraco.services.supportsCopy#retriveEntriesOfType @@ -293,14 +292,14 @@ function clipboardService(notificationsService, eventsService, localStorageServi * * @param {string} type A string defining the type of data to recive. * @param {string} aliases A array of strings providing the alias of the data you want to recive. - * + * * @description * Returns an array of data of entries matching the given type and one of the provided aliases. */ service.retriveDataOfType = function(type, aliases) { return service.retriveEntriesOfType(type, aliases).map((x) => x.data); }; - + /** * @ngdoc method * @name umbraco.services.supportsCopy#retriveEntriesOfType @@ -308,12 +307,12 @@ function clipboardService(notificationsService, eventsService, localStorageServi * * @param {string} type A string defining the type of data to remove. * @param {string} aliases A array of strings providing the alias of the data you want to remove. - * + * * @description * Removes entries matching the given type and one of the provided aliases. */ service.clearEntriesOfType = function(type, allowedAliases) { - + var storage = retriveStorage(); // Find entries that are NOT fulfilling the criteria for this nodeType and nodeTypesAliases. @@ -322,14 +321,14 @@ function clipboardService(notificationsService, eventsService, localStorageServi return !isEntryCompatible(entry, type, allowedAliases); } ); - + storage.entries = filteretEntries; saveStorage(storage); }; - - - + + + return service; } 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 489c1353ff..d3099154c7 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 @@ -456,6 +456,7 @@ blockPickerModel.clipboardItems.push( { type: "elementType", + date: entry.date, pasteData: entry.data, blockConfigModel: modelObject.getScaffoldFromAlias(entry.alias), elementTypeModel: { @@ -471,6 +472,7 @@ blockPickerModel.clipboardItems.push( { type: "elementTypeArray", + date: entry.date, pasteData: entry.data, blockConfigModel: {}, // no block configuration for paste items of elementTypeArray. elementTypeModel: { @@ -481,6 +483,10 @@ ); }); + blockPickerModel.clipboardItems.sort( (a, b) => { + return b.date - a.date + }); + // open block picker overlay editorService.open(blockPickerModel); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js index fe9725a7d8..ee406caa8a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js @@ -27,7 +27,7 @@ } } } - + clipboardService.registrerClearPropertyResolver(clearNestedContentPropertiesForStorage) @@ -49,7 +49,7 @@ } } } - + clipboardService.registrerClearPropertyResolver(clearInnerNestedContentPropertiesForStorage) }]); @@ -245,6 +245,7 @@ _.each(singleEntriesForPaste, function (entry) { vm.overlayMenu.pasteItems.push({ type: "elementType", + date: entry.date, name: entry.label, data: entry.data, icon: entry.icon @@ -255,12 +256,17 @@ _.each(arrayEntriesForPaste, function (entry) { vm.overlayMenu.pasteItems.push({ type: "elementTypeArray", + date: entry.date, name: entry.label, data: entry.data, icon: entry.icon }); }); + vm.overlayMenu.pasteItems.sort( (a, b) => { + return b.date - a.date + }); + vm.overlayMenu.title = labels.grid_addElement; vm.overlayMenu.hideHeader = vm.overlayMenu.pasteItems.length > 0; From a2b82970acb1013a06278c405ad113c34e3a2a7b Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 20 Aug 2020 11:54:35 +0200 Subject: [PATCH 04/53] Migrate GetCurrentUserLinkedLogins api --- .../Controllers/AuthenticationController.cs | 2 ++ .../Controllers/CurrentUserController.cs | 7 +++++ .../src/common/resources/auth.resource.js | 27 +++++++------------ .../common/resources/currentuser.resource.js | 22 ++++++++++----- .../common/overlays/user/user.controller.js | 4 +-- .../Editors/AuthenticationController.cs | 10 ------- 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs index 4faac5ce52..06eef1c1bb 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs @@ -416,6 +416,8 @@ namespace Umbraco.Web.BackOffice.Controllers return Ok(); } + + /// /// Return the for the given /// diff --git a/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs b/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs index 69b566d0cd..3bf44f4e9c 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs @@ -235,5 +235,12 @@ namespace Umbraco.Web.BackOffice.Controllers throw HttpResponseException.CreateValidationErrorResponse(ModelState); } + [UmbracoAuthorize] + [ValidateAngularAntiForgeryToken] + public async Task> GetCurrentUserLinkedLogins() + { + var identityUser = await _backOfficeUserManager.FindByIdAsync(_webSecurity.GetUserId().ResultOr(0).ToString()); + return identityUser.Logins.ToDictionary(x => x.LoginProvider, x => x.ProviderKey); + } } } diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js index 078ad2ad43..7dc34c3b5a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js @@ -4,7 +4,7 @@ * @description * This Resource perfomrs actions to common authentication tasks for the Umbraco backoffice user * - * @requires $q + * @requires $q * @requires $http * @requires umbRequestHelper * @requires angularHelper @@ -62,7 +62,7 @@ function authResource($q, $http, umbRequestHelper, angularHelper) { * .then(function(data) { * //Do stuff for login... * }); - * + * * @param {string} login Username of backoffice user * @param {string} password Password of backoffice user * @returns {Promise} resourcePromise object @@ -91,9 +91,9 @@ function authResource($q, $http, umbRequestHelper, angularHelper) { * There are not parameters for this since when the user has clicked on their invite email they will be partially * logged in (but they will not be approved) so we need to use this method to verify the non approved logged in user's details. * Using the getCurrentUser will not work since that only works for approved users - * @returns {} + * @returns {} */ - getCurrentInvitedUser: function () { + getCurrentInvitedUser: function () { return umbRequestHelper.resourcePromise( $http.get( umbRequestHelper.getApiUrl( @@ -117,7 +117,7 @@ function authResource($q, $http, umbRequestHelper, angularHelper) { * .then(function(data) { * //Do stuff for password reset request... * }); - * + * * @param {string} email Email address of backoffice user * @returns {Promise} resourcePromise object * @@ -164,7 +164,7 @@ function authResource($q, $http, umbRequestHelper, angularHelper) { * .then(function(data) { * //Allow reset of password * }); - * + * * @param {integer} userId User Id * @param {string} resetCode Password reset code * @returns {Promise} resourcePromise object @@ -195,14 +195,14 @@ function authResource($q, $http, umbRequestHelper, angularHelper) { }), 'Password reset code validation failed for userId ' + userId + ', code' + resetCode); }, - + /** * @ngdoc method * @name umbraco.resources.currentUserResource#getPasswordConfig * @methodOf umbraco.resources.currentUserResource * * @description - * Gets the configuration of the user membership provider which is used to configure the change password form + * Gets the configuration of the user membership provider which is used to configure the change password form */ getPasswordConfig: function (userId) { return umbRequestHelper.resourcePromise( @@ -227,7 +227,7 @@ function authResource($q, $http, umbRequestHelper, angularHelper) { * .then(function(data) { * //Password set * }); - * + * * @param {integer} userId User Id * @param {string} password New password * @param {string} confirmPassword Confirmation of new password @@ -346,15 +346,6 @@ function authResource($q, $http, umbRequestHelper, angularHelper) { 'Server call failed for getting current user'); }, - getCurrentUserLinkedLogins: function () { - - return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "authenticationApiBaseUrl", - "GetCurrentUserLinkedLogins")), - 'Server call failed for getting current users linked logins'); - }, /** * @ngdoc method diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/currentuser.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/currentuser.resource.js index 60b87e919f..a3be6996b1 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/currentuser.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/currentuser.resource.js @@ -2,7 +2,7 @@ * @ngdoc service * @name umbraco.resources.currentUserResource * @description Used for read/updates for the currently logged in user - * + * * **/ function currentUserResource($q, $http, umbRequestHelper, umbDataFormatter) { @@ -35,10 +35,10 @@ function currentUserResource($q, $http, umbRequestHelper, umbDataFormatter) { * .then(function() { * alert('You are allowed to publish this item'); * }); - * + * * * @param {String} permission char representing the permission to check - * @param {Int} id id of content item to delete + * @param {Int} id id of content item to delete * @returns {Promise} resourcePromise object. * */ @@ -52,6 +52,16 @@ function currentUserResource($q, $http, umbRequestHelper, umbDataFormatter) { 'Failed to check permission for item ' + id); }, + getCurrentUserLinkedLogins: function () { + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "currentUserApiBaseUrl", + "GetCurrentUserLinkedLogins")), + 'Server call failed for getting current users linked logins'); + }, + saveTourStatus: function (tourStatus) { if (!tourStatus) { @@ -68,7 +78,7 @@ function currentUserResource($q, $http, umbRequestHelper, umbDataFormatter) { }, getTours: function () { - + return umbRequestHelper.resourcePromise( $http.get( umbRequestHelper.getApiUrl( @@ -98,7 +108,7 @@ function currentUserResource($q, $http, umbRequestHelper, umbDataFormatter) { * * @description * Changes the current users password - * + * * @returns {Promise} resourcePromise object containing the user array. * */ @@ -108,7 +118,7 @@ function currentUserResource($q, $http, umbRequestHelper, umbDataFormatter) { if (!changePasswordArgs) { throw 'No password data to change'; } - + return umbRequestHelper.resourcePromise( $http.post( umbRequestHelper.getApiUrl( diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js index 812e53a0a6..4fc16f760a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js @@ -71,7 +71,7 @@ angular.module("umbraco") //set the timer //updateTimeout(); - authResource.getCurrentUserLinkedLogins().then(function(logins) { + currentUserResource.getCurrentUserLinkedLogins().then(function(logins) { //reset all to be un-linked for (var provider in $scope.externalLoginProviders) { $scope.externalLoginProviders[provider].linkedProviderKey = undefined; @@ -142,7 +142,7 @@ angular.module("umbraco") currentUserResource.changePassword($scope.changePasswordModel.value).then(function(data) { - //reset old data + //reset old data clearPasswordFields(); formHelper.resetForm({ scope: $scope }); diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index e4773a85d5..c3eedaab3b 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -107,16 +107,6 @@ namespace Umbraco.Web.Editors } } - - // TODO: This should be on the CurrentUserController? - [WebApi.UmbracoAuthorize] - [ValidateAngularAntiForgeryToken] - public async Task> GetCurrentUserLinkedLogins() - { - var identityUser = await UserManager.FindByIdAsync(Security.GetUserId().ResultOr(0).ToString()); - return identityUser.Logins.ToDictionary(x => x.LoginProvider, x => x.ProviderKey); - } - /// /// Used to retrieve the 2FA providers for code submission /// From bcfc9414d3b5df1641fac463e9c5f609291f64a7 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 20 Aug 2020 13:19:27 +0200 Subject: [PATCH 05/53] Update user on successfully login --- .../Security/BackOfficeSignInManager.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.Common/Security/BackOfficeSignInManager.cs b/src/Umbraco.Web.Common/Security/BackOfficeSignInManager.cs index b39e54935d..07f7470243 100644 --- a/src/Umbraco.Web.Common/Security/BackOfficeSignInManager.cs +++ b/src/Umbraco.Web.Common/Security/BackOfficeSignInManager.cs @@ -45,7 +45,7 @@ namespace Umbraco.Web.Common.Security { // override to handle logging/events var result = await base.PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure); - return HandlePasswordSignIn(user, user.UserName, result); + return await HandlePasswordSignIn(user, user.UserName, result); } public override async Task PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure) @@ -53,7 +53,7 @@ namespace Umbraco.Web.Common.Security // override to handle logging/events var user = await UserManager.FindByNameAsync(userName); if (user == null) - return HandlePasswordSignIn(null, userName, SignInResult.Failed); + return await HandlePasswordSignIn(null, userName, SignInResult.Failed); return await PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure); } @@ -62,7 +62,7 @@ namespace Umbraco.Web.Common.Security // override to handle logging/events var result = await base.TwoFactorSignInAsync(provider, code, isPersistent, rememberClient); var user = await GetTwoFactorAuthenticationUserAsync(); // will never be null if the above succeeds - return HandlePasswordSignIn(user, user?.UserName, result); + return await HandlePasswordSignIn(user, user?.UserName, result); } public override bool IsSignedIn(ClaimsPrincipal principal) @@ -125,13 +125,20 @@ namespace Umbraco.Web.Common.Security //await Context.SignOutAsync(IdentityConstants.TwoFactorUserIdScheme); } - private SignInResult HandlePasswordSignIn(BackOfficeIdentityUser user, string username, SignInResult result) + private async Task HandlePasswordSignIn(BackOfficeIdentityUser user, string username, SignInResult result) { if (username.IsNullOrWhiteSpace()) username = "UNKNOWN"; // could happen in 2fa or something else weird if (result.Succeeded) { + //track the last login date + user.LastLoginDateUtc = DateTime.UtcNow; + if (user.AccessFailedCount > 0) + //we have successfully logged in, reset the AccessFailedCount + user.AccessFailedCount = 0; + await _userManager.UpdateAsync(user); + Logger.LogInformation("User: {UserName} logged in from IP address {IpAddress}", username, Context.Connection.RemoteIpAddress); if (user != null) _userManager.RaiseLoginSuccessEvent(user, user.Id); From 6fb73502ed0c513b86980ee96e0fd502c2e8642b Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 20 Aug 2020 14:46:22 +0200 Subject: [PATCH 06/53] Fix issue with sending notifications, due to the StmpClient. Not we use the EmailSender that handles StmpClient correct --- .../Services/Implement/NotificationService.cs | 63 ++++++++----------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs index d6c30b24c6..cf53fb34cd 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs @@ -3,10 +3,10 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Net; using System.Net.Mail; using System.Text; using System.Threading; -using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; @@ -16,7 +16,6 @@ using Umbraco.Core.Models.Entities; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Scoping; -using Umbraco.Core.Strings; namespace Umbraco.Core.Services.Implement { @@ -29,15 +28,17 @@ namespace Umbraco.Core.Services.Implement private readonly INotificationsRepository _notificationsRepository; private readonly IGlobalSettings _globalSettings; private readonly IContentSettings _contentSettings; + private readonly IEmailSender _emailSender; private readonly ILogger _logger; private readonly IIOHelper _ioHelper; public NotificationService(IScopeProvider provider, IUserService userService, IContentService contentService, ILocalizationService localizationService, - ILogger logger, IIOHelper ioHelper, INotificationsRepository notificationsRepository, IGlobalSettings globalSettings, IContentSettings contentSettings) + ILogger logger, IIOHelper ioHelper, INotificationsRepository notificationsRepository, IGlobalSettings globalSettings, IContentSettings contentSettings, IEmailSender emailSender) { _notificationsRepository = notificationsRepository; _globalSettings = globalSettings; _contentSettings = contentSettings; + _emailSender = emailSender; _uowProvider = provider ?? throw new ArgumentNullException(nameof(provider)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _contentService = contentService ?? throw new ArgumentNullException(nameof(contentService)); @@ -405,8 +406,9 @@ namespace Umbraco.Core.Services.Implement string.Concat(siteUri.Authority, _ioHelper.ResolveUrl(_globalSettings.UmbracoPath)), summary.ToString()); + var fromMail = _contentSettings.NotificationEmailAddress ?? _globalSettings.SmtpSettings.From; // create the mail message - var mail = new MailMessage(_contentSettings.NotificationEmailAddress, mailingUser.Email); + var mail = new MailMessage(fromMail, mailingUser.Email); // populate the message @@ -508,51 +510,38 @@ namespace Umbraco.Core.Services.Implement { ThreadPool.QueueUserWorkItem(state => { - var s = new SmtpClient(); - try + _logger.Debug("Begin processing notifications."); + while (true) { - _logger.Debug("Begin processing notifications."); - while (true) + NotificationRequest request; + while (notificationRequests.TryTake(out request, 8 * 1000)) // stay on for 8s { - NotificationRequest request; - while (notificationRequests.TryTake(out request, 8 * 1000)) // stay on for 8s + try { - try - { - if (Sendmail != null) Sendmail(s, request.Mail, _logger); else s.Send(request.Mail); - _logger.Debug("Notification '{Action}' sent to {Username} ({Email})", request.Action, request.UserName, request.Email); - } - catch (Exception ex) - { - _logger.Error(ex, "An error occurred sending notification"); - s.Dispose(); - s = new SmtpClient(); - } - finally - { - request.Mail.Dispose(); - } + _emailSender.SendAsync(request.Mail).GetAwaiter().GetResult(); + _logger.Debug("Notification '{Action}' sent to {Username} ({Email})", request.Action, request.UserName, request.Email); } - lock (Locker) + catch (Exception ex) { - if (notificationRequests.Count > 0) continue; // last chance - _running = false; // going down - break; + _logger.Error(ex, "An error occurred sending notification"); + } + finally + { + request.Mail.Dispose(); } } + lock (Locker) + { + if (notificationRequests.Count > 0) continue; // last chance + _running = false; // going down + break; + } } - finally - { - s.Dispose(); - } + _logger.Debug("Done processing notifications."); }); } - // for tests - internal static Action Sendmail; - //= (_, msg, logger) => logger.Debug("Email " + msg.To.ToString()); - #endregion } } From d2f7c11e89742b0daf4adaae5edcbc3afca71282 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 21 Aug 2020 00:02:35 +1000 Subject: [PATCH 07/53] Fixes issue with scopes being disposed or referenced incorrectly --- .../UmbracoContentIndex.cs | 4 ++-- .../Search/ExamineComponent.cs | 22 ++++++++++++++++++- .../Sync/DatabaseServerMessenger.cs | 13 ++++++----- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Examine.Lucene/UmbracoContentIndex.cs b/src/Umbraco.Examine.Lucene/UmbracoContentIndex.cs index 904bf68623..dc2a5570a6 100644 --- a/src/Umbraco.Examine.Lucene/UmbracoContentIndex.cs +++ b/src/Umbraco.Examine.Lucene/UmbracoContentIndex.cs @@ -86,7 +86,7 @@ namespace Umbraco.Examine || !validator.ValidateProtectedContent(path, v.Category)) ? 0 : 1; - }); + }).ToList(); var hasDeletes = false; var hasUpdates = false; @@ -105,7 +105,7 @@ namespace Umbraco.Examine { hasUpdates = true; //these are the valid ones, so just index them all at once - base.PerformIndexItems(group, onComplete); + base.PerformIndexItems(group.ToList(), onComplete); } } diff --git a/src/Umbraco.Infrastructure/Search/ExamineComponent.cs b/src/Umbraco.Infrastructure/Search/ExamineComponent.cs index 037981d8b4..35a8804ecb 100644 --- a/src/Umbraco.Infrastructure/Search/ExamineComponent.cs +++ b/src/Umbraco.Infrastructure/Search/ExamineComponent.cs @@ -583,6 +583,26 @@ namespace Umbraco.Web.Search public static void Execute(ExamineComponent examineComponent, IContent content, bool isPublished) { + // TODO: This is ugly, it is going to build the value set 3x and for 2 of those times it will be the same value + // set. We can do better. + + // TODO: We are .ToList() ing each of the calls to GetValueSets here. This is currently required but isn't the way + // that this was intended to work. Ideally, the IEnumerable package gets passed to Examine and it is only iterated/executed + // when the indexing takes place which would occur on a background thread. This is problematic with how the ContentValueSetBuilder + // in combination with UmbracoContentIndex.PerformIndexItems works because (at least what I've come to believe) we are using yield + // return in the GetValueSets call in combination with trying to lazily resolve the enumerable but because we GroupBy in + // UmbracoContentIndex.PerformIndexItems it's eagerly executed but then lazily executed again on the background thread and I believe + // that in doing this when the call is made to _userService.GetProfilesById it's trying to resolve a scope from an AsyncLocal instance + // that has already been disposed higher up it's chain. I 'think' to how the eager/lazy enumeration happens with yield return that it's + // capturing a scope/AsyncLocal instance that it shouldn't really be using. + + // TODO: We don't want these value sets to be eagerly built in this thread since this is most likely going to be a request thread. + // This is why the lazy execution of the Enumerable had the intended affect of executing only when requested on the background thread. + // This could still be acheived: Either we have a custom Enumerable/Enumerator to do this, or we simply call the below code + // on a background thread... which would be much easier! + + // TODO: I think this is an issue in v8 too! + foreach (var index in examineComponent._examineManager.Indexes.OfType() //filter the indexers .Where(x => isPublished || !x.PublishedValuesOnly) @@ -593,7 +613,7 @@ namespace Umbraco.Web.Search ? examineComponent._publishedContentValueSetBuilder : (IValueSetBuilder)examineComponent._contentValueSetBuilder; - index.IndexItems(builder.GetValueSets(content)); + index.IndexItems(builder.GetValueSets(content).ToList()); } } } diff --git a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs index c915013162..2f6bb61e42 100644 --- a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs @@ -63,6 +63,13 @@ namespace Umbraco.Core.Sync _lastPruned = _lastSync = DateTime.UtcNow; _syncIdle = new ManualResetEvent(true); _distCacheFilePath = new Lazy(() => GetDistCacheFilePath(hostingEnvironment)); + + // See notes on LocalIdentity + LocalIdentity = NetworkHelper.MachineName // eg DOMAIN\SERVER + + "/" + _hostingEnvironment.ApplicationId // eg /LM/S3SVC/11/ROOT + + " [P" + Process.GetCurrentProcess().Id // eg 1234 + + "/D" + AppDomain.CurrentDomain.Id // eg 22 + + "] " + Guid.NewGuid().ToString("N").ToUpper(); // make it truly unique } protected ILogger Logger { get; } @@ -526,11 +533,7 @@ namespace Umbraco.Core.Sync /// Practically, all we really need is the guid, the other infos are here for information /// and debugging purposes. /// - protected string LocalIdentity => NetworkHelper.MachineName // eg DOMAIN\SERVER - + "/" + _hostingEnvironment.ApplicationId // eg /LM/S3SVC/11/ROOT - + " [P" + Process.GetCurrentProcess().Id // eg 1234 - + "/D" + AppDomain.CurrentDomain.Id // eg 22 - + "] " + Guid.NewGuid().ToString("N").ToUpper(); // make it truly unique + protected string LocalIdentity { get; } private string GetDistCacheFilePath(IHostingEnvironment hostingEnvironment) { From 140b1e950e19f8e590c4b76be964fbbe7fde62f1 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Fri, 21 Aug 2020 08:42:14 +0200 Subject: [PATCH 08/53] Fix tests --- src/Umbraco.Tests/TestHelpers/TestHelper.cs | 4 ++++ src/Umbraco.Tests/TestHelpers/TestObjects.cs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index 5512f50254..9aeb668518 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -42,6 +42,8 @@ namespace Umbraco.Tests.TestHelpers public static class TestHelper { private static readonly TestHelperInternal _testHelperInternal = new TestHelperInternal(); + private static IEmailSender _emailSender; + private class TestHelperInternal : TestHelperBase { public TestHelperInternal() : base(typeof(TestHelperInternal).Assembly) @@ -103,6 +105,8 @@ namespace Umbraco.Tests.TestHelpers public static IWebRoutingSettings WebRoutingSettings => _testHelperInternal.WebRoutingSettings; + public static IEmailSender EmailSender { get; } = new EmailSender(SettingsForTests.GenerateMockGlobalSettings()); + /// /// Some test files are copied to the /bin (/bin/debug) on build, this is a utility to return their physical path based on a virtual path name diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 7e8914f78e..44f6be8e7d 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -161,7 +161,7 @@ namespace Umbraco.Tests.TestHelpers var dataTypeService = GetLazyService(factory, c => new DataTypeService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), ioHelper, localizedTextService.Value, localizationService.Value, TestHelper.ShortStringHelper)); var propertyValidationService = new Lazy(() => new PropertyValidationService(propertyEditorCollection, dataTypeService.Value, localizedTextService.Value)); var contentService = GetLazyService(factory, c => new ContentService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), propertyValidationService, TestHelper.ShortStringHelper)); - var notificationService = GetLazyService(factory, c => new NotificationService(scopeProvider, userService.Value, contentService.Value, localizationService.Value, logger, ioHelper, GetRepo(c), globalSettings, contentSettings)); + var notificationService = GetLazyService(factory, c => new NotificationService(scopeProvider, userService.Value, contentService.Value, localizationService.Value, logger, ioHelper, GetRepo(c), globalSettings, contentSettings, TestHelper.EmailSender)); var serverRegistrationService = GetLazyService(factory, c => new ServerRegistrationService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), TestHelper.GetHostingEnvironment())); var memberGroupService = GetLazyService(factory, c => new MemberGroupService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var memberService = GetLazyService(factory, c => new MemberService(scopeProvider, logger, eventMessagesFactory, memberGroupService.Value, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); From 16db36eecd10cb339ba469b5f6086b3848b5e404 Mon Sep 17 00:00:00 2001 From: Mole Date: Fri, 21 Aug 2020 13:53:27 +0200 Subject: [PATCH 09/53] Start working on tests --- .../FileNames/UiFileNames.cs | 38 +++++++++++++++++++ .../AutoFixture/AutoMoqDataAttribute.cs | 14 +++++++ .../Extensions/LinkGeneratorExtensions.cs | 10 +++++ .../Extensions/UrlHelperExtensions.cs | 12 ------ .../Install/InstallController.cs | 2 +- 5 files changed, 63 insertions(+), 13 deletions(-) create mode 100644 src/Umbraco.Tests.Integration/FileNames/UiFileNames.cs diff --git a/src/Umbraco.Tests.Integration/FileNames/UiFileNames.cs b/src/Umbraco.Tests.Integration/FileNames/UiFileNames.cs new file mode 100644 index 0000000000..b5ebc3f5bf --- /dev/null +++ b/src/Umbraco.Tests.Integration/FileNames/UiFileNames.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using NUnit.Framework; + +namespace Umbraco.Tests.Integration.FileNames +{ + [TestFixture] + public class UiFileNames + { + [Test] + public void MacroTemplates() + { + var files = Directory.GetFiles(@"..\\..\\..\\..\\Umbraco.Web.UI.NetCore\\umbraco\\PartialViewMacros\\Templates"); + foreach(var file in files) + { + var fileName = file.Split("\\").Last(); + Assert.AreEqual(char.ToUpper(fileName[0]), fileName[0], $"{fileName} does not start with an uppercase letter."); + var titleCase = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(fileName.ToLower()); + } + } + + [Test] + public void LanguageFilesAreLowercase() + { + var files = Directory.GetFiles(@"..\\..\\..\\..\\Umbraco.Web.UI.NetCore\\umbraco\\config\\lang"); + foreach(var file in files) + { + var fileName = file.Split("\\").Last(); + Assert.AreEqual(fileName.ToLower(), fileName); + } + + } + } +} diff --git a/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs b/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs index 568704583d..dab22fbb62 100644 --- a/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs +++ b/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs @@ -8,6 +8,8 @@ using Moq; using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration; using Umbraco.Web.BackOffice.Controllers; +using Umbraco.Core; +using Umbraco.Web.Common.Install; namespace Umbraco.Tests.UnitTests.AutoFixture { @@ -36,12 +38,24 @@ namespace Umbraco.Tests.UnitTests.AutoFixture (a,b,c) => BackOfficeIdentityUser.CreateNew(Mock.Of(),a,b,c))); fixture .Customize(new ConstructorCustomization(typeof(UsersController), new GreedyConstructorQuery())) + .Customize(new ConstructorCustomization(typeof(InstallController), new GreedyConstructorQuery())) .Customize(new ConstructorCustomization(typeof(BackOfficeUserManager), new GreedyConstructorQuery())) .Customize(new AutoMoqCustomization()); // When requesting an IUserStore ensure we actually uses a IUserLockoutStore fixture.Customize>(cc => cc.FromFactory(() => Mock.Of>())); + fixture.Customize( + u => u.FromFactory( + (a, b, c) => new ConfigConnectionString(a, b, c))); + + fixture.Customize( + u => u.FromFactory( + () => new UmbracoVersion())); + + var connectionStrings = Mock.Of(); + Mock.Get(connectionStrings).Setup(x => x[Constants.System.UmbracoConnectionName]).Returns((ConfigConnectionString)new ConfigConnectionString(string.Empty, string.Empty, string.Empty)); + fixture.Customize(x => x.FromFactory(() => connectionStrings )); diff --git a/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs b/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs index dbfbee912e..66f219c266 100644 --- a/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs @@ -47,6 +47,16 @@ namespace Umbraco.Extensions return linkGenerator.GetPathByAction(nameof(InstallController.Index), ControllerExtensions.GetControllerName(), new { area = Constants.Web.Mvc.InstallArea }); } + /// + /// Returns the URL for the installer api + /// + /// + /// + public static string GetInstallerApiUrl(this LinkGenerator linkGenerator) + { + return linkGenerator.GetPathByAction(nameof(InstallController.Index), ControllerExtensions.GetControllerName(), new { area = Constants.Web.Mvc.InstallArea }); + } + /// /// Return the Url for a Web Api service /// diff --git a/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs b/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs index 8b1d41634d..03329547bc 100644 --- a/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UrlHelperExtensions.cs @@ -32,18 +32,6 @@ namespace Umbraco.Extensions return url.Action("Default", ControllerExtensions.GetControllerName(backOfficeControllerType), new { area = Constants.Web.Mvc.BackOfficeApiArea }); } - /// - /// Return the installer API url - /// - /// - /// - public static string GetInstallerApiUrl(this IUrlHelper url) - { - // there is no default action here so we need to get it by action and trim the action - return url.Action("GetSetup", ControllerExtensions.GetControllerName(), new { area = Constants.Web.Mvc.InstallArea }) - .TrimEnd("GetSetup"); - } - /// /// Return the Url for a Web Api service /// diff --git a/src/Umbraco.Web.Common/Install/InstallController.cs b/src/Umbraco.Web.Common/Install/InstallController.cs index 2b9f716516..dbd0def5e9 100644 --- a/src/Umbraco.Web.Common/Install/InstallController.cs +++ b/src/Umbraco.Web.Common/Install/InstallController.cs @@ -81,7 +81,7 @@ namespace Umbraco.Web.Common.Install } // gen the install base url - ViewData.SetInstallApiBaseUrl(Url.GetInstallerApiUrl()); + ViewData.SetInstallApiBaseUrl(_linkGenerator.GetInstallerApiUrl()); // get the base umbraco folder var baseFolder = _hostingEnvironment.ToAbsolute(_globalSettings.UmbracoPath); From 157068105c3805b59b366d0dbb346e8ae110918a Mon Sep 17 00:00:00 2001 From: Mole Date: Fri, 21 Aug 2020 13:53:57 +0200 Subject: [PATCH 10/53] Remember to actually add the test --- .../InstallControllerTest.cs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs new file mode 100644 index 0000000000..fc59231bee --- /dev/null +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using Umbraco.Core.Configuration; +using Umbraco.Tests.UnitTests.AutoFixture; +using Umbraco.Web.Common.Install; +using Umbraco.Core; +using AutoFixture.NUnit3; +using Umbraco.Core.Hosting; +using System.IO; +using System.Reflection; + +namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common +{ + [TestFixture] + class InstallControllerTest + { + [Test, AutoMoqData] + public async Task InstallViewExists( + [Frozen] IHostingEnvironment hostingEnvironment, + IHostingEnvironment environment, + InstallController sut) + { + Mock.Get(hostingEnvironment).Setup(x => x.ToAbsolute(It.IsAny())).Returns("/"); + var viewResult = await sut.Index() as ViewResult; + var sections = viewResult.ViewName.Split("\\"); + var fileName = sections[sections.Length - 1]; + var location = new FileInfo(typeof(InstallController).Assembly.Location).Directory; + } + } +} From 00f1e4a247c2943e453f031c734f87568062302a Mon Sep 17 00:00:00 2001 From: Mole Date: Fri, 21 Aug 2020 14:20:30 +0200 Subject: [PATCH 11/53] Assert that the view exists in InstallControllerTest --- .../Umbraco.Web.Common/InstallControllerTest.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs index fc59231bee..847d0a900b 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs @@ -13,6 +13,7 @@ using AutoFixture.NUnit3; using Umbraco.Core.Hosting; using System.IO; using System.Reflection; +using System.Linq; namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common { @@ -29,7 +30,11 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common var viewResult = await sut.Index() as ViewResult; var sections = viewResult.ViewName.Split("\\"); var fileName = sections[sections.Length - 1]; - var location = new FileInfo(typeof(InstallController).Assembly.Location).Directory; + + // TODO: Don't use DirectoryInfo to get contents of UmbracoInstall, use something that works everywhere. + var views = new DirectoryInfo(@"..\\..\\..\\..\\Umbraco.Web.UI.NetCore\\umbraco\\UmbracoInstall").GetFiles() + .Select(f => f.Name).ToArray(); + Assert.True(views.Contains(fileName), $"Expected {fileName} to exist, but it didn't"); } } } From b944142905bb818f3c5ac8ddeb2a7e17c3614f47 Mon Sep 17 00:00:00 2001 From: Nikolaj Date: Mon, 24 Aug 2020 08:45:41 +0200 Subject: [PATCH 12/53] Add PreviewViewExists test --- .../AutoFixture/AutoMoqDataAttribute.cs | 1 + .../InstallControllerTest.cs | 20 +++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs b/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs index dab22fbb62..adb1166cd8 100644 --- a/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs +++ b/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs @@ -39,6 +39,7 @@ namespace Umbraco.Tests.UnitTests.AutoFixture fixture .Customize(new ConstructorCustomization(typeof(UsersController), new GreedyConstructorQuery())) .Customize(new ConstructorCustomization(typeof(InstallController), new GreedyConstructorQuery())) + .Customize(new ConstructorCustomization(typeof(PreviewController), new GreedyConstructorQuery())) .Customize(new ConstructorCustomization(typeof(BackOfficeUserManager), new GreedyConstructorQuery())) .Customize(new AutoMoqCustomization()); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs index 847d0a900b..484d7e48a6 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs @@ -14,16 +14,16 @@ using Umbraco.Core.Hosting; using System.IO; using System.Reflection; using System.Linq; +using Umbraco.Web.BackOffice.Controllers; namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common { [TestFixture] - class InstallControllerTest + class InstallControllerTest // TODO: Is this the right place? { [Test, AutoMoqData] public async Task InstallViewExists( [Frozen] IHostingEnvironment hostingEnvironment, - IHostingEnvironment environment, InstallController sut) { Mock.Get(hostingEnvironment).Setup(x => x.ToAbsolute(It.IsAny())).Returns("/"); @@ -36,5 +36,21 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common .Select(f => f.Name).ToArray(); Assert.True(views.Contains(fileName), $"Expected {fileName} to exist, but it didn't"); } + + [Test, AutoMoqData] + public void PrviewViewExists( + [Frozen] IGlobalSettings globalSettings, + PreviewController sut) + { + Mock.Get(globalSettings).Setup(x => x.UmbracoPath).Returns("/"); + + var viewResult = sut.Index() as ViewResult; + var sections = viewResult.ViewName.Split("/"); + var fileName = sections[sections.Length - 1]; + + var views = new DirectoryInfo(@"..\\..\\..\\..\\Umbraco.Web.UI.NetCore\\umbraco\\UmbracoBackOffice").GetFiles() + .Select(f => f.Name).ToArray(); + Assert.True(views.Contains(fileName), $"Expected {fileName} to exist, but it didn't"); + } } } From 31e8acb875b781d3e55648d59d0fadf773d3d705 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 24 Aug 2020 09:23:37 +0200 Subject: [PATCH 13/53] Renamed nuget pacakges to Umbrac.Cms.* --- build/NuSpecs/UmbracoCms.Core.nuspec | 2 +- build/NuSpecs/UmbracoCms.SqlCe.nuspec | 4 ++-- build/NuSpecs/UmbracoCms.Web.nuspec | 4 ++-- build/NuSpecs/UmbracoCms.nuspec | 4 ++-- build/build.ps1 | 4 ++-- build/templates/UmbracoSolution/UmbracoSolution.csproj | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec index c72e01baa3..bb05e91b96 100644 --- a/build/NuSpecs/UmbracoCms.Core.nuspec +++ b/build/NuSpecs/UmbracoCms.Core.nuspec @@ -1,7 +1,7 @@ - UmbracoCms.Core + Umbraco.Cms.Core 9.0.0 Umbraco Cms Core Binaries Umbraco HQ diff --git a/build/NuSpecs/UmbracoCms.SqlCe.nuspec b/build/NuSpecs/UmbracoCms.SqlCe.nuspec index d64b24cf88..7c7fa2d902 100644 --- a/build/NuSpecs/UmbracoCms.SqlCe.nuspec +++ b/build/NuSpecs/UmbracoCms.SqlCe.nuspec @@ -1,7 +1,7 @@ - UmbracoCms.SqlCe + Umbraco.Cms.SqlCe 9.0.0 Umbraco Cms Sql Ce Add-on Umbraco HQ @@ -23,7 +23,7 @@ the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do not want this to happen as the alpha of the next major is, really, the next major already. --> - + diff --git a/build/NuSpecs/UmbracoCms.Web.nuspec b/build/NuSpecs/UmbracoCms.Web.nuspec index a35cea9df7..47aab4cdb8 100644 --- a/build/NuSpecs/UmbracoCms.Web.nuspec +++ b/build/NuSpecs/UmbracoCms.Web.nuspec @@ -1,7 +1,7 @@ - UmbracoCms.Web + Umbraco.Cms.Web 9.0.0 Umbraco Cms Core Binaries Umbraco HQ @@ -23,7 +23,7 @@ the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do not want this to happen as the alpha of the next major is, really, the next major already. --> - + diff --git a/build/NuSpecs/UmbracoCms.nuspec b/build/NuSpecs/UmbracoCms.nuspec index fbcff62bb6..a87d14ed64 100644 --- a/build/NuSpecs/UmbracoCms.nuspec +++ b/build/NuSpecs/UmbracoCms.nuspec @@ -1,7 +1,7 @@ - UmbracoCms + Umbraco.Cms 9.0.0 Umbraco Cms Umbraco HQ @@ -17,7 +17,7 @@ - + - - - - - - - - - 1 - - - - - - - - your@email.here - - - - - - Preview mode - - … - - - Click to end - - - - ]]> - - - - throw - - - ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd,swf,xml,xhtml,html,htm,php,htaccess - - - assets/img/login.jpg - - - - - - false - - - true - - - false - - - - - - - - - - - - - - - - diff --git a/src/Umbraco.Web.UI.NetCore/config/umbracoSettings.config b/src/Umbraco.Web.UI.NetCore/config/umbracoSettings.config deleted file mode 100644 index 5814a82095..0000000000 --- a/src/Umbraco.Web.UI.NetCore/config/umbracoSettings.config +++ /dev/null @@ -1,276 +0,0 @@ - - - - - - - - - - - - - 1 - - - - - - - - your@email.here - - - - - - Preview mode - - … - - - Click to end - - - - ]]> - - - - throw - - - ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd,swf,xml,xhtml,html,htm,php,htaccess - - - assets/img/login.jpg - - - - - - false - - - true - - - false - - - - - - - - - - - - - - - - - - \ No newline at end of file From 892a7e0b3439ccdd048aededfc55703625db1a00 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 24 Aug 2020 14:16:34 +0200 Subject: [PATCH 15/53] Changed default value of HideTopLevelNodeFromPath to true --- src/Umbraco.Configuration/Models/GlobalSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Configuration/Models/GlobalSettings.cs b/src/Umbraco.Configuration/Models/GlobalSettings.cs index 908ba71590..d1f3f12017 100644 --- a/src/Umbraco.Configuration/Models/GlobalSettings.cs +++ b/src/Umbraco.Configuration/Models/GlobalSettings.cs @@ -42,7 +42,7 @@ namespace Umbraco.Configuration.Models public string DefaultUILanguage => _configuration.GetValue(Prefix + "DefaultUILanguage", "en-US"); public bool HideTopLevelNodeFromPath => - _configuration.GetValue(Prefix + "HideTopLevelNodeFromPath", false); + _configuration.GetValue(Prefix + "HideTopLevelNodeFromPath", true); public bool UseHttps => _configuration.GetValue(Prefix + "UseHttps", false); public int VersionCheckPeriod => _configuration.GetValue(Prefix + "VersionCheckPeriod", 7); From b5b492106dc277b1f8b6911ba162f953cfc43c1f Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 24 Aug 2020 14:23:08 +0200 Subject: [PATCH 16/53] Clean up by moving stuff from Startup.cs into extention methods --- ...oBackOfficeApplicationBuilderExtensions.cs | 21 +++++++ ...coBackOfficeServiceCollectionExtensions.cs | 50 +++++++++++++++- src/Umbraco.Web.UI.NetCore/Startup.cs | 60 ++----------------- 3 files changed, 74 insertions(+), 57 deletions(-) diff --git a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeApplicationBuilderExtensions.cs index c34d9936bc..282668e4e6 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeApplicationBuilderExtensions.cs @@ -9,10 +9,31 @@ namespace Umbraco.Extensions { public static class UmbracoBackOfficeApplicationBuilderExtensions { + public static IApplicationBuilder UseUmbraco(this IApplicationBuilder app) + { + if (app == null) throw new ArgumentNullException(nameof(app)); + app.UseStatusCodePages(); + app.UseRouting(); + + app.UseUmbracoCore(); + app.UseUmbracoRouting(); + app.UseRequestLocalization(); + app.UseUmbracoRequestLogging(); + app.UseUmbracoBackOffice(); + app.UseUmbracoInstaller(); + + return app; + } + public static IApplicationBuilder UseUmbracoBackOffice(this IApplicationBuilder app) { if (app == null) throw new ArgumentNullException(nameof(app)); + // Important we handle image manipulations before the static files, otherwise the querystring is just ignored. + // TODO: Since we are dependent on these we need to register them but what happens when we call this multiple times since we are dependent on this for UseUmbracoBackOffice too? + app.UseImageSharp(); + app.UseStaticFiles(); + if (!app.UmbracoCanBoot()) return app; app.UseEndpoints(endpoints => diff --git a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs index 2c7db69b84..fc3efab5e0 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs @@ -1,5 +1,10 @@ -using Microsoft.AspNetCore.Identity; +using System; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Umbraco.Core; @@ -17,6 +22,49 @@ namespace Umbraco.Extensions { public static class UmbracoBackOfficeServiceCollectionExtensions { + public static IServiceCollection AddUmbraco(this IServiceCollection services, IWebHostEnvironment webHostEnvironment, IConfiguration config) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + + // TODO: We will need to decide on if we want to use the ServiceBasedControllerActivator to create our controllers + // or use the default IControllerActivator: DefaultControllerActivator (which doesn't directly use the container to resolve controllers) + // This will affect whether we need to explicitly register controllers in the container like we do today in v8. + // What we absolutely must do though is make sure we explicitly opt-in to using one or the other *always* for our controllers instead of + // relying on a global configuration set by a user since if a custom IControllerActivator is used for our own controllers we may not + // guarantee it will work. And then... is that even possible? + + // TODO: we will need to simplify this and prob just have a one or 2 main method that devs call which call all other required methods, + // but for now we'll just be explicit with all of them + services.AddUmbracoConfiguration(config); + services.AddUmbracoCore(webHostEnvironment, out var factory); + services.AddUmbracoWebComponents(); + services.AddUmbracoRuntimeMinifier(config); + services.AddUmbracoBackOffice(); + services.AddUmbracoBackOfficeIdentity(); + services.AddMiniProfiler(options => + { + options.ShouldProfile = request => false; // WebProfiler determine and start profiling. We should not use the MiniProfilerMiddleware to also profile + }); + + //We need to have runtime compilation of views when using umbraco. We could consider having only this when a specific config is set. + //But as far as I can see, there are still precompiled views, even when this is activated, so maybe it is okay. + services.AddControllersWithViews().AddRazorRuntimeCompilation(); + + + // If using Kestrel: https://stackoverflow.com/a/55196057 + services.Configure(options => + { + options.AllowSynchronousIO = true; + }); + + services.Configure(options => + { + options.AllowSynchronousIO = true; + }); + + return services; + } + /// /// Adds the services required for running the Umbraco back office /// diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs index 21faae22f2..673ac02013 100644 --- a/src/Umbraco.Web.UI.NetCore/Startup.cs +++ b/src/Umbraco.Web.UI.NetCore/Startup.cs @@ -1,7 +1,6 @@ using System; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -17,8 +16,8 @@ namespace Umbraco.Web.UI.NetCore /// /// Constructor /// - /// - /// + /// The Web Host Environment + /// The Configuration /// /// Only a few services are possible to be injected here https://github.com/dotnet/aspnetcore/issues/9337 /// @@ -32,69 +31,18 @@ namespace Umbraco.Web.UI.NetCore // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { - // TODO: We will need to decide on if we want to use the ServiceBasedControllerActivator to create our controllers - // or use the default IControllerActivator: DefaultControllerActivator (which doesn't directly use the container to resolve controllers) - // This will affect whether we need to explicitly register controllers in the container like we do today in v8. - // What we absolutely must do though is make sure we explicitly opt-in to using one or the other *always* for our controllers instead of - // relying on a global configuration set by a user since if a custom IControllerActivator is used for our own controllers we may not - // guarantee it will work. And then... is that even possible? - - // TODO: we will need to simplify this and prob just have a one or 2 main method that devs call which call all other required methods, - // but for now we'll just be explicit with all of them - services.AddUmbracoConfiguration(_config); - services.AddUmbracoCore(_env, out var factory); - services.AddUmbracoWebComponents(); - services.AddUmbracoRuntimeMinifier(_config); - services.AddUmbracoBackOffice(); - services.AddUmbracoBackOfficeIdentity(); - services.AddMiniProfiler(options => - { - options.ShouldProfile = request => false; // WebProfiler determine and start profiling. We should not use the MiniProfilerMiddleware to also profile - }); - - //We need to have runtime compilation of views when using umbraco. We could consider having only this when a specific config is set. - //But as far as I can see, there are still precompiled views, even when this is activated, so maybe it is okay. - services.AddControllersWithViews().AddRazorRuntimeCompilation(); - - - // If using Kestrel: https://stackoverflow.com/a/55196057 - services.Configure(options => - { - options.AllowSynchronousIO = true; - }); - - services.Configure(options => - { - options.AllowSynchronousIO = true; - }); + services.AddUmbraco(_env, _config); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app) { - //app.UseMiniProfiler(); if (_env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } - app.UseStatusCodePages(); - app.UseRouting(); - - app.UseUmbracoCore(); - app.UseUmbracoRouting(); - app.UseRequestLocalization(); - app.UseUmbracoRequestLogging(); - app.UseUmbracoWebsite(); - app.UseUmbracoBackOffice(); - app.UseUmbracoInstaller(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllerRoute( - name: "default", - pattern: "{controller}/{action=Index}/{id?}"); - }); + app.UseUmbraco(); } } } From 0a954d18040fcc7dc98b74d0836f37222f1fd919 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 24 Aug 2020 18:01:56 +0200 Subject: [PATCH 17/53] Fix issue with build targets after nuget rename --- build/NuSpecs/build/{UmbracoCms.props => Umbraco.Cms.props} | 0 build/NuSpecs/build/{UmbracoCms.targets => Umbraco.Cms.targets} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename build/NuSpecs/build/{UmbracoCms.props => Umbraco.Cms.props} (100%) rename build/NuSpecs/build/{UmbracoCms.targets => Umbraco.Cms.targets} (100%) diff --git a/build/NuSpecs/build/UmbracoCms.props b/build/NuSpecs/build/Umbraco.Cms.props similarity index 100% rename from build/NuSpecs/build/UmbracoCms.props rename to build/NuSpecs/build/Umbraco.Cms.props diff --git a/build/NuSpecs/build/UmbracoCms.targets b/build/NuSpecs/build/Umbraco.Cms.targets similarity index 100% rename from build/NuSpecs/build/UmbracoCms.targets rename to build/NuSpecs/build/Umbraco.Cms.targets From c561b256bf101c36ca2df9a716bc763d4ef5fa47 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 24 Aug 2020 18:09:16 +0200 Subject: [PATCH 18/53] Updated solution to include correct filenames --- src/umbraco.sln | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/umbraco.sln b/src/umbraco.sln index 636a5c31c9..b2922abf3e 100644 --- a/src/umbraco.sln +++ b/src/umbraco.sln @@ -62,8 +62,8 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Umbraco.Web.UI.Client", "ht EndProject Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Umbraco.Tests.AcceptanceTest", "http://localhost:58896", "{9E4C8A12-FBE0-4673-8CE2-DF99D5D57817}" ProjectSection(WebsiteProperties) = preProject - UseIISExpress = "true" - TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.5" + UseIISExpress = "true" + TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.5" Debug.AspNetCompiler.VirtualPath = "/localhost_58896" Debug.AspNetCompiler.PhysicalPath = "Umbraco.Tests.AcceptanceTest\" Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_58896\" @@ -84,8 +84,8 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Umbraco.Tests.AcceptanceTes Release.AspNetCompiler.ForceOverwrite = "true" Release.AspNetCompiler.FixedNames = "false" Release.AspNetCompiler.Debug = "False" - DefaultWebSiteLanguage = "Visual C#" - StartServerOnDebug = "false" + DefaultWebSiteLanguage = "Visual C#" + StartServerOnDebug = "false" VWDPort = "58896" VWDPort = "62926" SlnRelativePath = "Umbraco.Tests.AcceptanceTest\" @@ -107,10 +107,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{E3F9F378 EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{5B03EF4E-E0AC-4905-861B-8C3EC1A0D458}" - ProjectSection(SolutionItems) = preProject - ..\build\NuSpecs\build\UmbracoCms.props = ..\build\NuSpecs\build\UmbracoCms.props - ..\build\NuSpecs\build\UmbracoCms.targets = ..\build\NuSpecs\build\UmbracoCms.targets - EndProjectSection +ProjectSection(SolutionItems) = preProject + ..\build\NuSpecs\build\Umbraco.Cms.props = ..\build\NuSpecs\build\Umbraco.Cms.props + ..\build\NuSpecs\build\Umbraco.Cms.targets = ..\build\NuSpecs\build\Umbraco.Cms.targets +EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DocTools", "DocTools", "{53594E5B-64A2-4545-8367-E3627D266AE8}" ProjectSection(SolutionItems) = preProject From 056a5548756803cd29661d65809e42025e08c43c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 24 Aug 2020 21:38:36 +0200 Subject: [PATCH 19/53] use absolute path for thumbnail and dont scale SVGs --- .../components/blockcard/umb-block-card.html | 2 +- .../blockcard/umbBlockCard.component.js | 32 ++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html index 486bcbda4a..225362f4d8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html @@ -1,5 +1,5 @@ -
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js index c0758aa2df..454d264a89 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js @@ -14,9 +14,39 @@ } }); - function BlockCardController() { + function BlockCardController($scope, umbRequestHelper) { var vm = this; + vm.styleBackgroundImage = "transparent"; + + var unwatch = $scope.$watch("vm.blockConfigModel.thumbnail", (newValue, oldValue) => { + console.log("updateThumbnail") + if(newValue !== oldValue) { + vm.updateThumbnail(); + } + }); + + vm.$onInit = function () { + + vm.updateThumbnail(); + + } + vm.$onDestroy = function () { + unwatch(); + } + + vm.updateThumbnail = function () { + if (vm.blockConfigModel.thumbnail == null || vm.blockConfigModel.thumbnail === "") { + vm.styleBackgroundImage = "transparent"; + return; + } + + var path = umbRequestHelper.convertVirtualToAbsolutePath(vm.blockConfigModel.thumbnail); + if (path.toLowerCase().endsWith(".svg") === false) { + path += "?upscale=false&width=400)"; + } + vm.styleBackgroundImage = 'url(\''+path+'\')'; + } } From 7e32de7bb651a5c106f490fa7aad5a8c9fe7ab49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 24 Aug 2020 21:59:34 +0200 Subject: [PATCH 20/53] important fix --- .../src/views/components/blockcard/umb-block-card.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html index 486bcbda4a..f8ccccd166 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html @@ -1,6 +1,6 @@
- +
From 30e6f83358d99a498ebfb0a1dcd18e673ec5f0a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 25 Aug 2020 13:23:11 +0200 Subject: [PATCH 21/53] Update umbBlockCard.component.js change transparent to none --- .../src/views/components/blockcard/umbBlockCard.component.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js index 454d264a89..f1d11e43ff 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js @@ -17,10 +17,9 @@ function BlockCardController($scope, umbRequestHelper) { var vm = this; - vm.styleBackgroundImage = "transparent"; + vm.styleBackgroundImage = "none"; var unwatch = $scope.$watch("vm.blockConfigModel.thumbnail", (newValue, oldValue) => { - console.log("updateThumbnail") if(newValue !== oldValue) { vm.updateThumbnail(); } @@ -37,7 +36,7 @@ vm.updateThumbnail = function () { if (vm.blockConfigModel.thumbnail == null || vm.blockConfigModel.thumbnail === "") { - vm.styleBackgroundImage = "transparent"; + vm.styleBackgroundImage = "none"; return; } From eee3d489f1b182db7cec26c66eda64bcef67c2ae Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 25 Aug 2020 13:32:05 +0100 Subject: [PATCH 22/53] Update src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js --- .../src/views/components/blockcard/umbBlockCard.component.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js index f1d11e43ff..761e7c28ae 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js @@ -42,7 +42,7 @@ var path = umbRequestHelper.convertVirtualToAbsolutePath(vm.blockConfigModel.thumbnail); if (path.toLowerCase().endsWith(".svg") === false) { - path += "?upscale=false&width=400)"; + path += "?upscale=false&width=400"; } vm.styleBackgroundImage = 'url(\''+path+'\')'; } From 3d55dcd3c4e3f222a922929c25fbcfb39644d1be Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Wed, 26 Aug 2020 08:05:15 +0200 Subject: [PATCH 23/53] Merge remote-tracking branch 'netcore/dev' into netcore/netcore --- build/NuSpecs/UmbracoCms.Web.nuspec | 1 + .../Legacy/GlobalSettings.cs | 12 + .../Models/GlobalSettings.cs | 2 + .../Configuration/IGlobalSettings.cs | 10 + src/Umbraco.Core/Constants-AppSettings.cs | 9 +- src/Umbraco.Core/Constants-SvgSanitizer.cs | 23 + .../Constants-SystemDirectories.cs | 2 + .../ContentEditing/PropertyTypeBasic.cs | 8 + src/Umbraco.Core/Models/IconModel.cs | 8 + .../Repositories/IMemberGroupRepository.cs | 10 +- .../EmailAddressConfiguration.cs | 6 +- .../PropertyValueConverterBase.cs | 20 +- .../PropertyEditors/TrueFalseConfiguration.cs | 14 +- .../Scheduling/TempFileCleanup.cs | 2 + .../Services/IMemberGroupService.cs | 4 +- .../BackOfficeExamineSearcher.cs | 3 + .../Logging/Serilog/LoggerConfigExtensions.cs | 24 +- .../Logging/Viewer/SerilogJsonLogViewer.cs | 2 - .../Models/ContentEditing/EntityBasic.cs | 3 +- .../Models/ContentEditing/MediaItemDisplay.cs | 2 +- .../Models/ContentEditing/MemberDisplay.cs | 3 + .../Mapping/ContentTypeMapDefinition.cs | 4 +- .../Models/Mapping/EntityMapDefinition.cs | 6 +- .../Models/Mapping/PropertyTypeGroupMapper.cs | 2 + .../Querying/ExpressionVisitorBase.cs | 4 +- .../Implement/EntityRepository.cs | 6 +- .../Implement/MemberGroupRepository.cs | 12 +- .../Repositories/Implement/UserRepository.cs | 12 +- .../SqlSyntax/SqlServerSyntaxProvider.cs | 5 +- .../Persistence/UmbracoDatabaseFactory.cs | 1 + .../TrueFalsePropertyEditor.cs | 2 +- .../UserPickerConfiguration.cs | 3 +- .../UserPickerPropertyEditor.cs | 4 +- .../MemberPickerValueConverter.cs | 2 + .../Services/Implement/ContentService.cs | 2 + .../Services/Implement/MemberGroupService.cs | 8 + .../Services/Implement/RelationService.cs | 10 +- .../WebAssets/JsInitialize.js | 1 + .../integration/Settings/documentTypes.ts | 2 + .../Settings/partialsViewMacroFiles.ts | 140 +- .../integration/Settings/partialsViews.ts | 152 +- .../cypress/integration/Settings/scripts.ts | 2 +- .../cypress/integration/Settings/templates.ts | 151 +- .../integration/Tour/backofficeTour.ts | 49 + src/Umbraco.Tests.AcceptanceTest/package.json | 4 +- .../Builders/GlobalSettingsBuilder.cs | 4 + .../Services/UserServiceTests.cs | 57 + src/Umbraco.Tests/TestHelpers/TestObjects.cs | 2 +- .../Controllers/BackOfficeServerVariables.cs | 4 + .../Controllers/ContentTypeController.cs | 53 +- .../Controllers/DictionaryController.cs | 79 +- .../Controllers/IconController.cs | 108 ++ .../Controllers/ImagesController.cs | 63 +- .../Controllers/LogController.cs | 7 + .../Controllers/MediaController.cs | 21 +- .../Controllers/MediaTypeController.cs | 48 + .../Controllers/MemberGroupController.cs | 46 + .../Controllers/MemberTypeController.cs | 50 +- .../Controllers/RelationTypeController.cs | 37 + .../Controllers/TemplateController.cs | 41 +- .../Controllers/TemplateQueryController.cs | 6 +- .../Controllers/UsersController.cs | 28 + .../Mapping/MemberMapDefinition.cs | 1 + .../Umbraco.Web.BackOffice.csproj | 1 + .../gulp/tasks/dependencies.js | 16 +- .../lib/bootstrap/less/pager.less | 24 +- .../lib/bootstrap/less/pagination.less | 31 +- src/Umbraco.Web.UI.Client/package.json | 3 +- .../src/assets/icons/icon-activity.svg | 1 + .../src/assets/icons/icon-add.svg | 1 + .../src/assets/icons/icon-adressbook.svg | 1 + .../src/assets/icons/icon-alarm-clock.svg | 1 + .../src/assets/icons/icon-alert-alt.svg | 1 + .../src/assets/icons/icon-alert.svg | 1 + .../src/assets/icons/icon-alt.svg | 1 + .../src/assets/icons/icon-anchor.svg | 1 + .../src/assets/icons/icon-app.svg | 1 + .../assets/icons/icon-application-error.svg | 1 + .../icons/icon-application-window-alt.svg | 1 + .../assets/icons/icon-application-window.svg | 1 + .../src/assets/icons/icon-arrivals.svg | 1 + .../src/assets/icons/icon-arrow-down.svg | 1 + .../src/assets/icons/icon-arrow-left.svg | 1 + .../src/assets/icons/icon-arrow-right.svg | 1 + .../src/assets/icons/icon-arrow-up.svg | 1 + .../src/assets/icons/icon-art-easel.svg | 1 + .../src/assets/icons/icon-article.svg | 1 + .../src/assets/icons/icon-attachment.svg | 1 + .../src/assets/icons/icon-auction-hammer.svg | 1 + .../src/assets/icons/icon-autofill.svg | 1 + .../src/assets/icons/icon-award.svg | 1 + .../src/assets/icons/icon-axis-rotation-2.svg | 1 + .../src/assets/icons/icon-axis-rotation-3.svg | 1 + .../src/assets/icons/icon-axis-rotation.svg | 1 + .../src/assets/icons/icon-baby-stroller.svg | 1 + .../src/assets/icons/icon-backspace.svg | 1 + .../src/assets/icons/icon-badge-add.svg | 1 + .../src/assets/icons/icon-badge-count.svg | 1 + .../src/assets/icons/icon-badge-remove.svg | 1 + .../assets/icons/icon-badge-restricted.svg | 1 + .../src/assets/icons/icon-ball.svg | 1 + .../src/assets/icons/icon-band-aid.svg | 1 + .../src/assets/icons/icon-bar-chart.svg | 1 + .../src/assets/icons/icon-barcode.svg | 1 + .../src/assets/icons/icon-bars.svg | 1 + .../src/assets/icons/icon-battery-full.svg | 1 + .../src/assets/icons/icon-battery-low.svg | 1 + .../src/assets/icons/icon-beer-glass.svg | 1 + .../src/assets/icons/icon-bell-off.svg | 1 + .../src/assets/icons/icon-bell.svg | 1 + .../src/assets/icons/icon-bill-dollar.svg | 1 + .../src/assets/icons/icon-bill-euro.svg | 1 + .../src/assets/icons/icon-bill-pound.svg | 1 + .../src/assets/icons/icon-bill-yen.svg | 1 + .../src/assets/icons/icon-bill.svg | 1 + .../src/assets/icons/icon-billboard.svg | 1 + .../src/assets/icons/icon-bills-dollar.svg | 1 + .../src/assets/icons/icon-bills-euro.svg | 1 + .../src/assets/icons/icon-bills-pound.svg | 1 + .../src/assets/icons/icon-bills-yen.svg | 1 + .../src/assets/icons/icon-bills.svg | 1 + .../src/assets/icons/icon-binarycode.svg | 1 + .../src/assets/icons/icon-binoculars.svg | 1 + .../src/assets/icons/icon-bird.svg | 1 + .../src/assets/icons/icon-birthday-cake.svg | 1 + .../src/assets/icons/icon-block.svg | 1 + .../src/assets/icons/icon-blueprint.svg | 1 + .../src/assets/icons/icon-bluetooth.svg | 1 + .../src/assets/icons/icon-boat-shipping.svg | 1 + .../src/assets/icons/icon-bomb.svg | 1 + .../src/assets/icons/icon-bones.svg | 1 + .../src/assets/icons/icon-book-alt-2.svg | 1 + .../src/assets/icons/icon-book-alt.svg | 1 + .../src/assets/icons/icon-book.svg | 1 + .../src/assets/icons/icon-bookmark.svg | 1 + .../src/assets/icons/icon-books.svg | 1 + .../src/assets/icons/icon-box-alt.svg | 1 + .../src/assets/icons/icon-box-open.svg | 1 + .../src/assets/icons/icon-box.svg | 1 + .../src/assets/icons/icon-brackets.svg | 1 + .../src/assets/icons/icon-brick.svg | 1 + .../src/assets/icons/icon-briefcase.svg | 1 + .../src/assets/icons/icon-browser-window.svg | 1 + .../src/assets/icons/icon-brush-alt-2.svg | 1 + .../src/assets/icons/icon-brush-alt.svg | 1 + .../src/assets/icons/icon-brush.svg | 1 + .../src/assets/icons/icon-bug.svg | 1 + .../src/assets/icons/icon-bulleted-list.svg | 1 + .../src/assets/icons/icon-burn.svg | 1 + .../src/assets/icons/icon-bus.svg | 1 + .../src/assets/icons/icon-calculator.svg | 1 + .../src/assets/icons/icon-calendar-alt.svg | 1 + .../src/assets/icons/icon-calendar.svg | 1 + .../src/assets/icons/icon-camcorder.svg | 1 + .../src/assets/icons/icon-camera-roll.svg | 1 + .../src/assets/icons/icon-candy.svg | 1 + .../src/assets/icons/icon-caps-lock.svg | 1 + .../src/assets/icons/icon-car.svg | 1 + .../src/assets/icons/icon-cash-register.svg | 1 + .../src/assets/icons/icon-categories.svg | 1 + .../src/assets/icons/icon-certificate.svg | 1 + .../src/assets/icons/icon-chart-curve.svg | 1 + .../src/assets/icons/icon-chart.svg | 1 + .../src/assets/icons/icon-chat-active.svg | 1 + .../src/assets/icons/icon-chat.svg | 1 + .../src/assets/icons/icon-check.svg | 1 + .../icons/icon-checkbox-dotted-active.svg | 1 + .../src/assets/icons/icon-checkbox-dotted.svg | 1 + .../src/assets/icons/icon-checkbox-empty.svg | 1 + .../src/assets/icons/icon-checkbox.svg | 1 + .../src/assets/icons/icon-chess.svg | 1 + .../src/assets/icons/icon-chip-alt.svg | 1 + .../src/assets/icons/icon-chip.svg | 1 + .../src/assets/icons/icon-cinema.svg | 1 + .../icons/icon-circle-dotted-active.svg | 1 + .../src/assets/icons/icon-circle-dotted.svg | 1 + .../src/assets/icons/icon-circuits.svg | 1 + .../src/assets/icons/icon-circus.svg | 1 + .../src/assets/icons/icon-client.svg | 1 + .../src/assets/icons/icon-clothes-hanger.svg | 1 + .../src/assets/icons/icon-cloud-drive.svg | 1 + .../src/assets/icons/icon-cloud-upload.svg | 1 + .../src/assets/icons/icon-cloud.svg | 1 + .../src/assets/icons/icon-cloudy.svg | 1 + .../src/assets/icons/icon-clubs.svg | 1 + .../src/assets/icons/icon-cocktail.svg | 1 + .../src/assets/icons/icon-code.svg | 1 + .../src/assets/icons/icon-coffee.svg | 1 + .../src/assets/icons/icon-coin-dollar.svg | 1 + .../src/assets/icons/icon-coin-euro.svg | 1 + .../src/assets/icons/icon-coin-pound.svg | 1 + .../src/assets/icons/icon-coin-yen.svg | 1 + .../src/assets/icons/icon-coin.svg | 1 + .../src/assets/icons/icon-coins-alt.svg | 1 + .../assets/icons/icon-coins-dollar-alt.svg | 1 + .../src/assets/icons/icon-coins-dollar.svg | 1 + .../src/assets/icons/icon-coins-euro-alt.svg | 1 + .../src/assets/icons/icon-coins-euro.svg | 1 + .../src/assets/icons/icon-coins-pound-alt.svg | 1 + .../src/assets/icons/icon-coins-pound.svg | 1 + .../src/assets/icons/icon-coins-yen-alt.svg | 1 + .../src/assets/icons/icon-coins-yen.svg | 1 + .../src/assets/icons/icon-coins.svg | 1 + .../src/assets/icons/icon-color-bucket.svg | 1 + .../src/assets/icons/icon-colorpicker.svg | 1 + .../src/assets/icons/icon-columns.svg | 1 + .../src/assets/icons/icon-comb.svg | 1 + .../icons/icon-combination-lock-open.svg | 1 + .../assets/icons/icon-combination-lock.svg | 1 + .../src/assets/icons/icon-command.svg | 1 + .../src/assets/icons/icon-company.svg | 1 + .../src/assets/icons/icon-compress.svg | 1 + .../src/assets/icons/icon-connection.svg | 1 + .../src/assets/icons/icon-console.svg | 1 + .../src/assets/icons/icon-contrast.svg | 1 + .../assets/icons/icon-conversation-alt.svg | 1 + .../src/assets/icons/icon-conversation.svg | 1 + .../src/assets/icons/icon-coverflow.svg | 1 + .../src/assets/icons/icon-credit-card-alt.svg | 1 + .../src/assets/icons/icon-credit-card.svg | 1 + .../src/assets/icons/icon-crop.svg | 1 + .../src/assets/icons/icon-crosshair.svg | 1 + .../src/assets/icons/icon-crown-alt.svg | 1 + .../src/assets/icons/icon-crown.svg | 1 + .../src/assets/icons/icon-cupcake.svg | 1 + .../src/assets/icons/icon-curve.svg | 1 + .../src/assets/icons/icon-cut.svg | 1 + .../src/assets/icons/icon-dashboard.svg | 1 + .../src/assets/icons/icon-defrag.svg | 1 + .../src/assets/icons/icon-delete-key.svg | 1 + .../src/assets/icons/icon-delete.svg | 1 + .../src/assets/icons/icon-departure.svg | 1 + .../src/assets/icons/icon-desk.svg | 1 + .../src/assets/icons/icon-desktop.svg | 1 + .../src/assets/icons/icon-diagnostics.svg | 1 + .../assets/icons/icon-diagonal-arrow-alt.svg | 1 + .../src/assets/icons/icon-diagonal-arrow.svg | 1 + .../src/assets/icons/icon-diamond.svg | 1 + .../src/assets/icons/icon-diamonds.svg | 1 + .../src/assets/icons/icon-dice.svg | 1 + .../src/assets/icons/icon-diploma-alt.svg | 1 + .../src/assets/icons/icon-diploma.svg | 1 + .../src/assets/icons/icon-directions-alt.svg | 1 + .../src/assets/icons/icon-directions.svg | 1 + .../src/assets/icons/icon-disc.svg | 1 + .../src/assets/icons/icon-disk-image.svg | 1 + .../src/assets/icons/icon-display.svg | 1 + .../src/assets/icons/icon-dna.svg | 1 + .../src/assets/icons/icon-dock-connector.svg | 1 + .../icons/icon-document-dashed-line.svg | 1 + .../src/assets/icons/icon-document.svg | 1 + .../src/assets/icons/icon-documents.svg | 1 + .../src/assets/icons/icon-dollar-bag.svg | 1 + .../src/assets/icons/icon-donate.svg | 1 + .../src/assets/icons/icon-door-open-alt.svg | 1 + .../src/assets/icons/icon-door-open.svg | 1 + .../src/assets/icons/icon-download-alt.svg | 1 + .../src/assets/icons/icon-download.svg | 1 + .../src/assets/icons/icon-drop.svg | 1 + .../src/assets/icons/icon-eco.svg | 1 + .../src/assets/icons/icon-economy.svg | 1 + .../src/assets/icons/icon-edit.svg | 1 + .../src/assets/icons/icon-eject.svg | 1 + .../src/assets/icons/icon-employee.svg | 1 + .../assets/icons/icon-energy-saving-bulb.svg | 1 + .../src/assets/icons/icon-enter.svg | 1 + .../src/assets/icons/icon-equalizer.svg | 1 + .../src/assets/icons/icon-escape.svg | 1 + .../src/assets/icons/icon-ethernet.svg | 1 + .../src/assets/icons/icon-euro-bag.svg | 1 + .../src/assets/icons/icon-exit-fullscreen.svg | 1 + .../src/assets/icons/icon-eye.svg | 1 + .../src/assets/icons/icon-facebook-like.svg | 1 + .../src/assets/icons/icon-factory.svg | 1 + .../src/assets/icons/icon-favorite.svg | 1 + .../src/assets/icons/icon-female-symbol.svg | 1 + .../src/assets/icons/icon-file-cabinet.svg | 1 + .../src/assets/icons/icon-files.svg | 1 + .../src/assets/icons/icon-filter-arrows.svg | 1 + .../src/assets/icons/icon-filter.svg | 1 + .../src/assets/icons/icon-fingerprint.svg | 1 + .../src/assets/icons/icon-fire.svg | 1 + .../src/assets/icons/icon-firewall.svg | 1 + .../src/assets/icons/icon-firewire.svg | 1 + .../src/assets/icons/icon-flag-alt.svg | 1 + .../src/assets/icons/icon-flag.svg | 1 + .../src/assets/icons/icon-flash.svg | 1 + .../src/assets/icons/icon-flashlight.svg | 1 + .../src/assets/icons/icon-flowerpot.svg | 1 + .../src/assets/icons/icon-folder-open.svg | 1 + .../src/assets/icons/icon-folder-outline.svg | 1 + .../src/assets/icons/icon-folder.svg | 1 + .../src/assets/icons/icon-folders.svg | 1 + .../src/assets/icons/icon-font.svg | 1 + .../src/assets/icons/icon-food.svg | 1 + .../src/assets/icons/icon-footprints.svg | 1 + .../src/assets/icons/icon-forking.svg | 1 + .../src/assets/icons/icon-frame-alt.svg | 1 + .../src/assets/icons/icon-frame.svg | 1 + .../src/assets/icons/icon-fullscreen-alt.svg | 1 + .../src/assets/icons/icon-fullscreen.svg | 1 + .../src/assets/icons/icon-game.svg | 1 + .../src/assets/icons/icon-geometry.svg | 1 + .../src/assets/icons/icon-gift.svg | 1 + .../src/assets/icons/icon-glasses.svg | 1 + .../src/assets/icons/icon-globe-alt.svg | 1 + .../src/assets/icons/icon-globe-asia.svg | 1 + .../assets/icons/icon-globe-europe-africa.svg | 1 + .../icons/icon-globe-inverted-america.svg | 1 + .../assets/icons/icon-globe-inverted-asia.svg | 1 + .../icon-globe-inverted-europe-africa.svg | 1 + .../src/assets/icons/icon-globe.svg | 1 + .../src/assets/icons/icon-gps.svg | 1 + .../src/assets/icons/icon-graduate.svg | 1 + .../src/assets/icons/icon-grid.svg | 1 + .../src/assets/icons/icon-hammer.svg | 1 + .../src/assets/icons/icon-hand-active-alt.svg | 1 + .../src/assets/icons/icon-hand-active.svg | 1 + .../assets/icons/icon-hand-pointer-alt.svg | 1 + .../src/assets/icons/icon-hand-pointer.svg | 1 + .../src/assets/icons/icon-handprint.svg | 1 + .../src/assets/icons/icon-handshake.svg | 1 + .../src/assets/icons/icon-handtool-alt.svg | 1 + .../src/assets/icons/icon-handtool.svg | 1 + .../src/assets/icons/icon-hard-drive-alt.svg | 1 + .../src/assets/icons/icon-hard-drive.svg | 1 + .../src/assets/icons/icon-hat.svg | 1 + .../src/assets/icons/icon-hd.svg | 1 + .../src/assets/icons/icon-headphones.svg | 1 + .../src/assets/icons/icon-headset.svg | 1 + .../src/assets/icons/icon-hearts.svg | 1 + .../src/assets/icons/icon-height.svg | 1 + .../src/assets/icons/icon-help-alt.svg | 1 + .../src/assets/icons/icon-help.svg | 1 + .../src/assets/icons/icon-home.svg | 1 + .../src/assets/icons/icon-hourglass.svg | 1 + .../src/assets/icons/icon-imac.svg | 1 + .../src/assets/icons/icon-inactive-line.svg | 1 + .../src/assets/icons/icon-inbox-full.svg | 1 + .../src/assets/icons/icon-inbox.svg | 1 + .../src/assets/icons/icon-indent.svg | 1 + .../src/assets/icons/icon-infinity.svg | 1 + .../src/assets/icons/icon-info.svg | 1 + .../src/assets/icons/icon-invoice.svg | 1 + .../src/assets/icons/icon-ipad.svg | 1 + .../src/assets/icons/icon-iphone.svg | 1 + .../assets/icons/icon-item-arrangement.svg | 1 + .../src/assets/icons/icon-junk.svg | 1 + .../src/assets/icons/icon-key.svg | 1 + .../src/assets/icons/icon-keyboard.svg | 1 + .../src/assets/icons/icon-keychain.svg | 1 + .../src/assets/icons/icon-keyhole.svg | 1 + .../src/assets/icons/icon-lab.svg | 1 + .../src/assets/icons/icon-laptop.svg | 1 + .../src/assets/icons/icon-layers-alt.svg | 1 + .../src/assets/icons/icon-layers.svg | 1 + .../src/assets/icons/icon-layout.svg | 1 + .../assets/icons/icon-left-double-arrow.svg | 1 + .../src/assets/icons/icon-legal.svg | 1 + .../src/assets/icons/icon-lense.svg | 1 + .../src/assets/icons/icon-library.svg | 1 + .../src/assets/icons/icon-light-down.svg | 1 + .../src/assets/icons/icon-light-up.svg | 1 + .../assets/icons/icon-lightbulb-active.svg | 1 + .../src/assets/icons/icon-lightbulb.svg | 1 + .../src/assets/icons/icon-lightning.svg | 1 + .../src/assets/icons/icon-link.svg | 1 + .../src/assets/icons/icon-linux-tux.svg | 1 + .../src/assets/icons/icon-list.svg | 1 + .../src/assets/icons/icon-load.svg | 1 + .../src/assets/icons/icon-loading.svg | 1 + .../src/assets/icons/icon-locate.svg | 1 + .../assets/icons/icon-location-near-me.svg | 1 + .../src/assets/icons/icon-location-nearby.svg | 1 + .../src/assets/icons/icon-lock.svg | 1 + .../src/assets/icons/icon-log-out.svg | 1 + .../src/assets/icons/icon-logout.svg | 1 + .../src/assets/icons/icon-loupe.svg | 1 + .../src/assets/icons/icon-magnet.svg | 1 + .../src/assets/icons/icon-mailbox.svg | 1 + .../src/assets/icons/icon-male-and-female.svg | 1 + .../src/assets/icons/icon-male-symbol.svg | 1 + .../src/assets/icons/icon-map-alt.svg | 1 + .../src/assets/icons/icon-map-location.svg | 1 + .../src/assets/icons/icon-map-marker.svg | 1 + .../src/assets/icons/icon-map.svg | 1 + .../src/assets/icons/icon-medal.svg | 1 + .../assets/icons/icon-medical-emergency.svg | 1 + .../src/assets/icons/icon-medicine.svg | 1 + .../src/assets/icons/icon-meeting.svg | 1 + .../src/assets/icons/icon-megaphone.svg | 1 + .../src/assets/icons/icon-merge.svg | 1 + .../src/assets/icons/icon-message-open.svg | 1 + .../assets/icons/icon-message-unopened.svg | 1 + .../src/assets/icons/icon-message.svg | 1 + .../src/assets/icons/icon-microscope.svg | 1 + .../src/assets/icons/icon-mindmap.svg | 1 + .../src/assets/icons/icon-mobile.svg | 1 + .../assets/icons/icon-molecular-network.svg | 1 + .../src/assets/icons/icon-molecular.svg | 1 + .../src/assets/icons/icon-mountain.svg | 1 + .../src/assets/icons/icon-mouse-cursor.svg | 1 + .../src/assets/icons/icon-mouse.svg | 1 + .../src/assets/icons/icon-movie-alt.svg | 1 + .../src/assets/icons/icon-movie.svg | 1 + .../icons/icon-multiple-credit-cards.svg | 1 + .../assets/icons/icon-multiple-windows.svg | 1 + .../src/assets/icons/icon-music.svg | 1 + .../src/assets/icons/icon-name-badge.svg | 1 + .../assets/icons/icon-navigation-bottom.svg | 1 + .../src/assets/icons/icon-navigation-down.svg | 1 + .../assets/icons/icon-navigation-first.svg | 1 + .../icons/icon-navigation-horizontal.svg | 1 + .../src/assets/icons/icon-navigation-last.svg | 1 + .../src/assets/icons/icon-navigation-left.svg | 1 + .../assets/icons/icon-navigation-right.svg | 1 + .../src/assets/icons/icon-navigation-road.svg | 1 + .../src/assets/icons/icon-navigation-top.svg | 1 + .../src/assets/icons/icon-navigation-up.svg | 1 + .../assets/icons/icon-navigation-vertical.svg | 1 + .../src/assets/icons/icon-navigation.svg | 1 + .../assets/icons/icon-navigational-arrow.svg | 1 + .../src/assets/icons/icon-network-alt.svg | 1 + .../src/assets/icons/icon-newspaper-alt.svg | 1 + .../src/assets/icons/icon-newspaper.svg | 1 + .../src/assets/icons/icon-next-media.svg | 1 + .../src/assets/icons/icon-next.svg | 1 + .../src/assets/icons/icon-nodes.svg | 1 + .../src/assets/icons/icon-notepad-alt.svg | 1 + .../src/assets/icons/icon-notepad.svg | 1 + .../src/assets/icons/icon-old-key.svg | 1 + .../src/assets/icons/icon-old-phone.svg | 1 + .../src/assets/icons/icon-operator.svg | 1 + .../src/assets/icons/icon-ordered-list.svg | 1 + .../src/assets/icons/icon-os-x.svg | 1 + .../src/assets/icons/icon-out.svg | 1 + .../src/assets/icons/icon-outbox.svg | 1 + .../src/assets/icons/icon-outdent.svg | 1 + .../src/assets/icons/icon-page-add.svg | 1 + .../src/assets/icons/icon-page-down.svg | 1 + .../src/assets/icons/icon-page-remove.svg | 1 + .../src/assets/icons/icon-page-restricted.svg | 1 + .../src/assets/icons/icon-page-up.svg | 1 + .../src/assets/icons/icon-paint-roller.svg | 1 + .../src/assets/icons/icon-palette.svg | 1 + .../src/assets/icons/icon-panel-show.svg | 1 + .../src/assets/icons/icon-pannel-close.svg | 1 + .../src/assets/icons/icon-pants.svg | 1 + .../src/assets/icons/icon-paper-bag.svg | 1 + .../src/assets/icons/icon-paper-plane-alt.svg | 1 + .../src/assets/icons/icon-paper-plane.svg | 1 + .../src/assets/icons/icon-parachute-drop.svg | 1 + .../assets/icons/icon-parental-control.svg | 1 + .../src/assets/icons/icon-partly-cloudy.svg | 1 + .../src/assets/icons/icon-paste-in.svg | 1 + .../src/assets/icons/icon-path.svg | 1 + .../src/assets/icons/icon-pause.svg | 1 + .../src/assets/icons/icon-pc.svg | 1 + .../src/assets/icons/icon-people-alt-2.svg | 1 + .../src/assets/icons/icon-people-alt.svg | 1 + .../src/assets/icons/icon-people-female.svg | 1 + .../src/assets/icons/icon-people.svg | 1 + .../src/assets/icons/icon-phone-ring.svg | 1 + .../src/assets/icons/icon-phone.svg | 1 + .../src/assets/icons/icon-photo-album.svg | 1 + .../src/assets/icons/icon-picture.svg | 1 + .../src/assets/icons/icon-pictures-alt-2.svg | 1 + .../src/assets/icons/icon-pictures-alt.svg | 1 + .../src/assets/icons/icon-pictures.svg | 1 + .../src/assets/icons/icon-pie-chart.svg | 1 + .../src/assets/icons/icon-piggy-bank.svg | 1 + .../src/assets/icons/icon-pin-location.svg | 1 + .../src/assets/icons/icon-piracy.svg | 1 + .../src/assets/icons/icon-plane.svg | 1 + .../src/assets/icons/icon-planet.svg | 1 + .../src/assets/icons/icon-play.svg | 1 + .../src/assets/icons/icon-playing-cards.svg | 1 + .../src/assets/icons/icon-playlist.svg | 1 + .../src/assets/icons/icon-plugin.svg | 1 + .../src/assets/icons/icon-podcast.svg | 1 + .../src/assets/icons/icon-poker-chip.svg | 1 + .../src/assets/icons/icon-poll.svg | 1 + .../src/assets/icons/icon-post-it.svg | 1 + .../src/assets/icons/icon-pound-bag.svg | 1 + .../src/assets/icons/icon-power-outlet.svg | 1 + .../src/assets/icons/icon-power.svg | 1 + .../src/assets/icons/icon-presentation.svg | 1 + .../src/assets/icons/icon-previous-media.svg | 1 + .../src/assets/icons/icon-previous.svg | 1 + .../src/assets/icons/icon-price-dollar.svg | 1 + .../src/assets/icons/icon-price-euro.svg | 1 + .../src/assets/icons/icon-price-pound.svg | 1 + .../src/assets/icons/icon-price-yen.svg | 1 + .../src/assets/icons/icon-print.svg | 1 + .../src/assets/icons/icon-printer-alt.svg | 1 + .../src/assets/icons/icon-projector.svg | 1 + .../src/assets/icons/icon-pulse.svg | 1 + .../src/assets/icons/icon-pushpin.svg | 1 + .../src/assets/icons/icon-qr-code.svg | 1 + .../src/assets/icons/icon-quote.svg | 1 + .../src/assets/icons/icon-radio-alt.svg | 1 + .../src/assets/icons/icon-radio-receiver.svg | 1 + .../src/assets/icons/icon-radio.svg | 1 + .../src/assets/icons/icon-rain.svg | 1 + .../src/assets/icons/icon-rate.svg | 1 + .../src/assets/icons/icon-re-post.svg | 1 + .../src/assets/icons/icon-readonly.svg | 1 + .../src/assets/icons/icon-receipt-alt.svg | 1 + .../src/assets/icons/icon-receipt-dollar.svg | 1 + .../src/assets/icons/icon-receipt-euro.svg | 1 + .../src/assets/icons/icon-receipt-pound.svg | 1 + .../src/assets/icons/icon-receipt-yen.svg | 1 + .../src/assets/icons/icon-reception.svg | 1 + .../src/assets/icons/icon-record.svg | 1 + .../src/assets/icons/icon-redo.svg | 1 + .../src/assets/icons/icon-refresh.svg | 1 + .../src/assets/icons/icon-remote.svg | 1 + .../src/assets/icons/icon-remove.svg | 1 + .../src/assets/icons/icon-repeat-one.svg | 1 + .../src/assets/icons/icon-repeat.svg | 1 + .../src/assets/icons/icon-reply-arrow.svg | 1 + .../src/assets/icons/icon-resize.svg | 1 + .../src/assets/icons/icon-return-to-top.svg | 1 + .../assets/icons/icon-right-double-arrow.svg | 1 + .../src/assets/icons/icon-road.svg | 1 + .../src/assets/icons/icon-roadsign.svg | 1 + .../src/assets/icons/icon-rocket.svg | 1 + .../src/assets/icons/icon-rss.svg | 1 + .../src/assets/icons/icon-ruler-alt.svg | 1 + .../src/assets/icons/icon-ruler.svg | 1 + .../src/assets/icons/icon-safe.svg | 1 + .../src/assets/icons/icon-safedial.svg | 1 + .../src/assets/icons/icon-sandbox-toys.svg | 1 + .../src/assets/icons/icon-satellite-dish.svg | 1 + .../src/assets/icons/icon-save.svg | 1 + .../src/assets/icons/icon-scan.svg | 1 + .../src/assets/icons/icon-school.svg | 1 + .../src/assets/icons/icon-screensharing.svg | 1 + .../src/assets/icons/icon-script-alt.svg | 1 + .../src/assets/icons/icon-script.svg | 1 + .../src/assets/icons/icon-scull.svg | 1 + .../src/assets/icons/icon-search.svg | 1 + .../src/assets/icons/icon-security-camera.svg | 1 + .../src/assets/icons/icon-sensor.svg | 1 + .../src/assets/icons/icon-server-alt.svg | 1 + .../src/assets/icons/icon-server.svg | 1 + .../src/assets/icons/icon-settings-alt-2.svg | 1 + .../src/assets/icons/icon-settings-alt.svg | 1 + .../src/assets/icons/icon-settings.svg | 1 + .../src/assets/icons/icon-share-alt-2.svg | 1 + .../src/assets/icons/icon-share-alt.svg | 1 + .../src/assets/icons/icon-share.svg | 1 + .../src/assets/icons/icon-sharing-iphone.svg | 1 + .../src/assets/icons/icon-shield.svg | 1 + .../src/assets/icons/icon-shift.svg | 1 + .../src/assets/icons/icon-shipping-box.svg | 1 + .../src/assets/icons/icon-shipping.svg | 1 + .../src/assets/icons/icon-shoe.svg | 1 + .../icons/icon-shopping-basket-alt-2.svg | 1 + .../assets/icons/icon-shopping-basket-alt.svg | 1 + .../src/assets/icons/icon-shopping-basket.svg | 1 + .../src/assets/icons/icon-shorts.svg | 1 + .../src/assets/icons/icon-shuffle.svg | 1 + .../src/assets/icons/icon-sience.svg | 1 + .../src/assets/icons/icon-simcard.svg | 1 + .../src/assets/icons/icon-single-note.svg | 1 + .../src/assets/icons/icon-sitemap.svg | 1 + .../src/assets/icons/icon-sleep.svg | 1 + .../src/assets/icons/icon-slideshow.svg | 1 + .../src/assets/icons/icon-smiley-inverted.svg | 1 + .../src/assets/icons/icon-smiley.svg | 1 + .../src/assets/icons/icon-snow.svg | 1 + .../src/assets/icons/icon-sound-low.svg | 1 + .../src/assets/icons/icon-sound-medium.svg | 1 + .../src/assets/icons/icon-sound-off.svg | 1 + .../src/assets/icons/icon-sound-waves.svg | 1 + .../src/assets/icons/icon-sound.svg | 1 + .../src/assets/icons/icon-spades.svg | 1 + .../src/assets/icons/icon-speaker.svg | 1 + .../src/assets/icons/icon-speed-gauge.svg | 1 + .../src/assets/icons/icon-split-alt.svg | 1 + .../src/assets/icons/icon-split.svg | 1 + .../src/assets/icons/icon-sprout.svg | 1 + .../src/assets/icons/icon-squiggly-line.svg | 1 + .../src/assets/icons/icon-ssd.svg | 1 + .../src/assets/icons/icon-stacked-disks.svg | 1 + .../src/assets/icons/icon-stamp.svg | 1 + .../src/assets/icons/icon-stop-alt.svg | 1 + .../src/assets/icons/icon-stop-hand.svg | 1 + .../src/assets/icons/icon-stop.svg | 1 + .../src/assets/icons/icon-store.svg | 1 + .../src/assets/icons/icon-stream.svg | 1 + .../src/assets/icons/icon-sunny.svg | 1 + .../src/assets/icons/icon-sweatshirt.svg | 1 + .../src/assets/icons/icon-sync.svg | 1 + .../src/assets/icons/icon-t-shirt.svg | 1 + .../src/assets/icons/icon-tab-key.svg | 1 + .../src/assets/icons/icon-tab.svg | 1 + .../src/assets/icons/icon-tactics.svg | 1 + .../src/assets/icons/icon-tag.svg | 1 + .../src/assets/icons/icon-tags.svg | 1 + .../src/assets/icons/icon-takeaway-cup.svg | 1 + .../src/assets/icons/icon-target.svg | 1 + .../assets/icons/icon-temperatrure-alt.svg | 1 + .../src/assets/icons/icon-temperature.svg | 1 + .../src/assets/icons/icon-terminal.svg | 1 + .../src/assets/icons/icon-theater.svg | 1 + .../src/assets/icons/icon-theif.svg | 1 + .../src/assets/icons/icon-thought-bubble.svg | 1 + .../src/assets/icons/icon-thumb-down.svg | 1 + .../src/assets/icons/icon-thumb-up.svg | 1 + .../src/assets/icons/icon-thumbnail-list.svg | 1 + .../assets/icons/icon-thumbnails-small.svg | 1 + .../src/assets/icons/icon-thumbnails.svg | 1 + .../src/assets/icons/icon-ticket.svg | 1 + .../src/assets/icons/icon-time.svg | 1 + .../src/assets/icons/icon-timer.svg | 1 + .../src/assets/icons/icon-tools.svg | 1 + .../src/assets/icons/icon-top.svg | 1 + .../src/assets/icons/icon-traffic-alt.svg | 1 + .../src/assets/icons/icon-trafic.svg | 1 + .../src/assets/icons/icon-train.svg | 1 + .../src/assets/icons/icon-trash-alt-2.svg | 1 + .../src/assets/icons/icon-trash-alt.svg | 1 + .../src/assets/icons/icon-trash.svg | 1 + .../src/assets/icons/icon-tree.svg | 1 + .../src/assets/icons/icon-trophy.svg | 1 + .../src/assets/icons/icon-truck.svg | 1 + .../src/assets/icons/icon-tv-old.svg | 1 + .../src/assets/icons/icon-tv.svg | 1 + .../src/assets/icons/icon-umb-content.svg | 1 + .../src/assets/icons/icon-umb-contour.svg | 1 + .../src/assets/icons/icon-umb-deploy.svg | 1 + .../src/assets/icons/icon-umb-developer.svg | 1 + .../src/assets/icons/icon-umb-media.svg | 1 + .../src/assets/icons/icon-umb-members.svg | 1 + .../src/assets/icons/icon-umb-settings.svg | 1 + .../src/assets/icons/icon-umb-users.svg | 1 + .../src/assets/icons/icon-umbrella.svg | 1 + .../src/assets/icons/icon-undo.svg | 1 + .../src/assets/icons/icon-universal.svg | 1 + .../src/assets/icons/icon-unlocked.svg | 1 + .../src/assets/icons/icon-untitled.svg | 1 + .../src/assets/icons/icon-usb-connector.svg | 1 + .../src/assets/icons/icon-usb.svg | 1 + .../src/assets/icons/icon-user-female.svg | 1 + .../assets/icons/icon-user-females-alt.svg | 1 + .../src/assets/icons/icon-user-females.svg | 1 + .../src/assets/icons/icon-user-glasses.svg | 1 + .../src/assets/icons/icon-user.svg | 1 + .../src/assets/icons/icon-users-alt.svg | 1 + .../src/assets/icons/icon-users.svg | 1 + .../src/assets/icons/icon-utilities.svg | 1 + .../src/assets/icons/icon-vcard.svg | 1 + .../src/assets/icons/icon-video.svg | 1 + .../src/assets/icons/icon-voice.svg | 1 + .../src/assets/icons/icon-wall-plug.svg | 1 + .../src/assets/icons/icon-wallet.svg | 1 + .../src/assets/icons/icon-wand.svg | 1 + .../src/assets/icons/icon-war.svg | 1 + .../src/assets/icons/icon-weight.svg | 1 + .../src/assets/icons/icon-width.svg | 1 + .../src/assets/icons/icon-wifi.svg | 1 + .../src/assets/icons/icon-window-popin.svg | 1 + .../src/assets/icons/icon-window-sizes.svg | 1 + .../src/assets/icons/icon-windows.svg | 1 + .../src/assets/icons/icon-wine-glass.svg | 1 + .../src/assets/icons/icon-wrench.svg | 1 + .../src/assets/icons/icon-wrong.svg | 1 + .../src/assets/icons/icon-yen-bag.svg | 1 + .../src/assets/icons/icon-zip.svg | 1 + .../src/assets/icons/icon-zom-out.svg | 1 + .../src/assets/icons/icon-zoom-in.svg | 1 + .../application/umbappheader.directive.js | 28 +- .../application/umbsearch.directive.js | 3 +- .../components/buttons/umbbutton.directive.js | 4 +- .../buttons/umbbuttonellipsis.directive.js | 93 + .../components/buttons/umbtoggle.directive.js | 32 +- .../components/content/edit.controller.js | 8 +- .../umbvariantcontenteditors.directive.js | 47 +- .../components/forms/umbcheckbox.directive.js | 11 +- .../forms/umbfocuslock.directive.js | 82 + .../forms/umbradiobutton.directive.js | 15 +- .../forms/umbsearchfilter.directive.js | 84 + .../components/grid/grid.rte.directive.js | 15 +- .../imaging/umbimagecrop.directive.js | 389 ++-- .../media/umbmedianodeinfo.directive.js | 4 +- .../member/umbmembernodeinfo.directive.js | 13 + .../overlays/umboverlay.directive.js | 25 +- .../components/tree/umbtree.directive.js | 22 +- .../components/tree/umbtreeitem.directive.js | 4 +- .../components/umbchildselector.directive.js | 30 +- .../components/umbconfirmaction.directive.js | 32 +- .../components/umbdatetimepicker.directive.js | 2 +- .../components/umbgroupsbuilder.directive.js | 25 +- .../components/umbicon.directive.js | 86 + .../components/umbmediagrid.directive.js | 38 +- .../components/umbminilistview.directive.js | 5 +- .../components/umbtooltip.directive.js | 62 +- .../upload/umbfileupload.directive.js | 11 + .../upload/umbpropertyfileupload.directive.js | 23 +- .../validation/valformmanager.directive.js | 2 +- .../src/common/mocks/resources/media.mocks.js | 10 +- .../common/mocks/umbraco.servervariables.js | 3 +- .../src/common/resources/content.resource.js | 8 +- .../src/common/resources/media.resource.js | 4 +- .../common/resources/membergroup.resource.js | 4 +- .../common/resources/membertype.resource.js | 11 +- .../src/common/resources/users.resource.js | 33 + .../src/common/services/assets.service.js | 14 +- .../services/contenteditinghelper.service.js | 5 +- .../src/common/services/editor.service.js | 17 - .../src/common/services/focuslock.service.js | 26 + .../src/common/services/formhelper.service.js | 61 +- .../src/common/services/iconhelper.service.js | 155 +- .../common/services/mediahelper.service.js | 9 +- .../src/common/services/navigation.service.js | 7 +- .../src/common/services/overlay.service.js | 15 +- .../src/common/services/search.service.js | 39 +- .../src/common/services/tinymce.service.js | 5 + .../src/common/services/tree.service.js | 8 +- .../services/umbrequesthelper.service.js | 8 +- .../common/services/usershelper.service.js | 43 +- .../src/common/services/util.service.js | 6 +- .../src/installer/steps/database.html | 219 +-- src/Umbraco.Web.UI.Client/src/less/belle.less | 3 + .../src/less/buttons.less | 5 +- .../src/less/colors.less | 4 +- .../buttons/umb-button-ellipsis.less | 76 + .../components/buttons/umb-button-group.less | 2 +- .../less/components/buttons/umb-button.less | 5 + .../less/components/buttons/umb-toggle.less | 50 +- .../src/less/components/editor.less | 22 +- .../editor/umb-variant-switcher.less | 41 +- .../src/less/components/overlays.less | 2 +- .../less/components/tree/umb-tree-item.less | 5 +- .../src/less/components/tree/umb-tree.less | 34 +- .../src/less/components/umb-badge.less | 10 + .../src/less/components/umb-code-snippet.less | 1 + .../less/components/umb-confirm-action.less | 134 +- .../less/components/umb-date-time-picker.less | 25 +- .../umb-editor-navigation-item.less | 6 +- .../src/less/components/umb-form-check.less | 25 +- .../src/less/components/umb-grid.less | 14 +- .../less/components/umb-group-builder.less | 34 +- .../src/less/components/umb-icon.less | 9 + .../src/less/components/umb-iconpicker.less | 52 +- .../src/less/components/umb-list.less | 2 +- .../src/less/components/umb-logviewer.less | 15 +- .../src/less/components/umb-media-grid.less | 16 + .../less/components/umb-mini-list-view.less | 4 + .../less/components/umb-multiple-textbox.less | 19 +- .../less/components/umb-nested-content.less | 2 +- .../src/less/components/umb-packages.less | 19 +- .../src/less/components/umb-pagination.less | 8 +- .../less/components/umb-property-actions.less | 2 +- .../components/umb-property-file-upload.less | 12 + .../src/less/components/umb-stylesheet.less | 1 + .../src/less/components/umb-table.less | 22 +- .../src/less/components/umb-tags-editor.less | 53 + .../components/users/umb-user-preview.less | 15 +- src/Umbraco.Web.UI.Client/src/less/forms.less | 8 +- .../src/less/helveticons.less | 1302 +++++++------- .../src/less/listview.less | 5 +- src/Umbraco.Web.UI.Client/src/less/main.less | 2 +- .../src/less/modals.less | 50 +- .../src/less/pages/welcome-dashboard.less | 27 +- src/Umbraco.Web.UI.Client/src/less/panel.less | 7 +- .../src/less/properties.less | 9 +- .../src/less/property-editors.less | 58 +- .../src/less/variables.less | 6 +- .../common/drawers/help/help.controller.js | 8 +- .../src/views/common/drawers/help/help.html | 10 +- .../compositions/compositions.controller.js | 50 +- .../compositions/compositions.html | 54 +- .../datatypeconfigurationpicker.controller.js | 13 +- .../datatypepicker/datatypepicker.html | 23 +- .../iconpicker/iconpicker.controller.js | 19 +- .../iconpicker/iconpicker.html | 10 +- .../insertfield/insertfield.html | 2 +- .../itempicker/itempicker.html | 2 +- .../macroparameterpicker.html | 23 +- .../mediapicker/mediapicker.controller.js | 115 +- .../mediapicker/mediapicker.html | 189 +- .../overlays/mediacropdetails.controller.js | 59 + .../overlays/mediacropdetails.html | 78 + .../propertysettings.controller.js | 4 +- .../querybuilder/querybuilder.html | 16 +- .../sectionpicker/sectionpicker.controller.js | 8 +- .../treepicker/treepicker.controller.js | 182 +- .../treepicker/treepicker.html | 10 +- .../usergrouppicker.controller.js | 8 +- .../userpicker/userpicker.controller.js | 58 +- .../userpicker/userpicker.html | 4 +- .../itempicker/itempicker.controller.js | 6 +- .../overlays/itempicker/itempicker.html | 19 +- .../logviewersearch/logviewersearch.html | 6 +- .../src/views/common/overlays/user/user.html | 2 +- .../application/umb-app-header.html | 8 - .../application/umb-navigation.html | 2 +- .../components/application/umb-sections.html | 9 +- .../application/umbtour/umb-tour-step.html | 3 +- .../buttons/umb-button-ellipsis.html | 12 + .../components/buttons/umb-button-group.html | 19 +- .../views/components/buttons/umb-button.html | 14 +- .../views/components/buttons/umb-toggle.html | 8 +- .../src/views/components/content/edit.html | 4 +- .../editor/umb-editor-content-header.html | 15 +- .../components/editor/umb-editor-header.html | 2 +- .../components/editor/umb-editor-menu.html | 1 + .../editor/umb-editor-navigation.html | 17 +- .../views/components/forms/umb-checkbox.html | 35 +- .../components/forms/umb-radiobutton.html | 30 +- .../components/forms/umb-search-filter.html | 28 + .../components/imaging/umb-image-crop.html | 4 +- .../components/media/umb-media-node-info.html | 1 - .../member/umb-member-node-info.html | 4 +- .../components/overlays/umb-overlay.html | 9 +- .../umb-property-actions.html | 20 +- .../views/components/tabs/umb-tabs-nav.html | 12 +- .../components/tags/umb-tags-editor.html | 10 +- .../views/components/tree/umb-tree-item.html | 21 +- .../components/tree/umb-tree-search-box.html | 4 +- .../src/views/components/tree/umb-tree.html | 29 +- .../views/components/umb-child-selector.html | 2 +- .../views/components/umb-confirm-action.html | 31 +- .../components/umb-date-time-picker.html | 6 +- .../views/components/umb-groups-builder.html | 16 +- .../src/views/components/umb-icon.html | 4 + .../views/components/umb-layout-selector.html | 17 +- .../components/umb-list-view-settings.html | 12 +- .../src/views/components/umb-media-grid.html | 134 +- .../views/components/umb-mini-list-view.html | 10 +- .../src/views/components/umb-pagination.html | 24 +- .../components/upload/umb-file-dropzone.html | 156 +- .../upload/umb-property-file-upload.html | 14 +- .../components/users/umb-user-preview.html | 11 +- .../content/content.notify.controller.js | 2 +- .../content/content.rights.controller.js | 10 +- .../views/content/content.sort.controller.js | 5 +- .../content/overlays/publish.controller.js | 144 +- .../src/views/content/overlays/publish.html | 15 +- .../overlays/publishdescendants.controller.js | 44 +- .../content/overlays/publishdescendants.html | 15 +- .../views/content/overlays/save.controller.js | 62 +- .../content/overlays/schedule.controller.js | 72 +- .../src/views/content/overlays/schedule.html | 47 +- .../overlays/sendtopublish.controller.js | 26 +- .../content/overlays/unpublish.controller.js | 50 +- .../src/views/content/protect.html | 20 +- .../src/views/content/sort.html | 12 +- .../content/redirecturls.controller.js | 1 + .../views/dashboard/content/redirecturls.html | 24 +- .../dashboard/dashboard.tabs.controller.js | 9 +- .../views/dashboard/default/ourumbraco.jpg | Bin 25651 -> 0 bytes .../views/dashboard/default/ourumbraco.png | Bin 0 -> 186465 bytes .../default/startupdashboardintro.html | 19 +- .../src/views/dashboard/default/umbracotv.jpg | Bin 49817 -> 0 bytes .../src/views/dashboard/default/umbracotv.png | Bin 0 -> 314485 bytes .../settings/examinemanagementresults.html | 1 + .../src/views/dataTypes/delete.html | 4 +- .../src/views/dictionary/create.html | 8 +- .../dictionary.create.controller.js | 1 - .../dictionary/dictionary.list.controller.js | 2 +- .../src/views/dictionary/edit.html | 2 +- .../src/views/dictionary/list.html | 17 +- .../src/views/documentTypes/create.html | 2 + .../src/views/documentTypes/delete.html | 3 +- .../views/documentTypes/edit.controller.js | 24 +- .../permissions/permissions.controller.js | 25 +- .../src/views/languages/edit.controller.js | 2 +- .../views/logViewer/overview.controller.js | 62 +- .../src/views/logViewer/overview.html | 1 + .../src/views/logViewer/search.controller.js | 66 +- .../src/views/logViewer/search.html | 72 +- .../src/views/media/media.edit.controller.js | 9 +- .../src/views/mediaTypes/delete.html | 3 +- .../src/views/mediaTypes/edit.controller.js | 35 +- .../permissions/permissions.controller.js | 23 +- .../member/apps/content/content.controller.js | 8 + .../views/member/apps/content/content.html | 2 +- .../views/member/member.edit.controller.js | 219 ++- .../src/views/memberTypes/delete.html | 3 +- .../src/views/memberTypes/edit.controller.js | 75 +- .../src/views/packages/edit.html | 8 +- .../src/views/packages/views/repo.html | 98 +- .../src/views/partialViews/create.html | 18 +- .../views/prevalueeditors/imagepicker.html | 19 +- .../prevalueeditors/mediafolderpicker.html | 18 +- .../views/prevalueeditors/mediapicker.html | 11 +- .../views/prevalueeditors/multivalues.html | 4 +- .../src/views/prevalueeditors/treepicker.html | 11 +- .../src/views/prevalueeditors/treesource.html | 39 +- .../prevalueeditors/treesourcetypepicker.html | 9 +- .../boolean/boolean.controller.js | 36 +- .../propertyeditors/boolean/boolean.html | 4 +- .../contentpicker/contentpicker.controller.js | 70 +- .../contentpicker/contentpicker.html | 2 +- .../datepicker/datepicker.controller.js | 4 +- .../datepicker/datepicker.html | 19 +- .../dropdownFlexible.controller.js | 12 +- .../grid/dialogs/editconfig.controller.js | 60 +- .../grid/dialogs/editconfig.html | 14 +- .../grid/dialogs/layoutconfig.controller.js | 49 +- .../grid/dialogs/layoutconfig.html | 247 ++- .../grid/dialogs/rowconfig.controller.js | 68 +- .../grid/dialogs/rowconfig.html | 183 +- .../dialogs/rowdeleteconfirm.controller.js | 16 - .../grid/dialogs/rowdeleteconfirm.html | 46 - .../grid/editors/media.controller.js | 62 +- .../propertyeditors/grid/editors/media.html | 18 +- .../propertyeditors/grid/grid.controller.js | 18 +- .../src/views/propertyeditors/grid/grid.html | 47 +- .../grid/grid.prevalues.controller.js | 100 +- .../propertyeditors/grid/grid.prevalues.html | 33 +- .../grid/overlays/rowdeleteconfirm.html | 16 + .../listview/icon.prevalues.html | 2 +- .../listview/includeproperties.prevalues.html | 19 +- .../listview/layouts.prevalues.controller.js | 3 +- .../listview/layouts.prevalues.html | 71 +- .../list/list.listviewlayout.controller.js | 18 +- .../listview/listview.controller.js | 29 +- .../propertyeditors/listview/listview.html | 20 +- .../listview/overlays/listviewpublish.html | 4 +- .../overlays/listviewunpublish.controller.js | 2 +- .../listview/overlays/listviewunpublish.html | 4 +- .../mediapicker/mediapicker.html | 1 + .../membergrouppicker/membergrouppicker.html | 10 +- .../membergroups/membergroups.html | 8 +- .../memberpicker/memberpicker.controller.js | 3 +- .../memberpicker/memberpicker.html | 11 +- .../multipletextbox.controller.js | 39 +- .../multipletextbox/multipletextbox.html | 25 +- .../multiurlpicker/multiurlpicker.html | 29 +- .../nestedcontent/nestedcontent.controller.js | 79 +- .../nestedcontent.propertyeditor.html | 20 +- .../rte/rte.prevalues.controller.js | 8 +- .../propertyeditors/rte/rte.prevalues.html | 19 +- .../views/propertyeditors/slider/slider.html | 4 +- .../userpicker/userpicker.controller.js | 92 + .../userpicker/userpicker.html | 21 + .../views/relationTypes/edit.controller.js | 2 +- .../richtextrule/richtextrule.html | 7 +- .../views/rules/rules.controller.js | 1 - .../views/stylesheets/views/rules/rules.html | 10 +- .../src/views/templates/edit.controller.js | 4 +- .../src/views/templates/edit.html | 30 +- .../src/views/users/group.controller.js | 8 +- .../src/views/users/user.controller.js | 6 +- .../users/views/groups/groups.controller.js | 2 +- .../users/views/users/users.controller.js | 24 +- .../content-picker-controller.spec.js | 9 +- .../Umbraco.Web.UI.NetCore.csproj | 6 + .../umbraco/config/lang/cs.xml | 1587 +++++++++++++++-- .../umbraco/config/lang/da.xml | 5 +- .../umbraco/config/lang/de.xml | 4 - .../umbraco/config/lang/en.xml | 64 +- .../umbraco/config/lang/en_us.xml | 13 + .../umbraco/config/lang/fr.xml | 619 ++++++- .../umbraco/config/lang/nb.xml | 1 + .../umbraco/config/lang/nl.xml | 2 +- .../umbraco/config/lang/tr.xml | 2 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 10 +- .../Views/Partials/Grid/Editors/Media.cshtml | 29 - src/Umbraco.Web/HtmlHelperRenderExtensions.cs | 6 + src/Umbraco.Web/Umbraco.Web.csproj | 3 + 966 files changed, 9352 insertions(+), 4199 deletions(-) create mode 100644 src/Umbraco.Core/Constants-SvgSanitizer.cs create mode 100644 src/Umbraco.Core/Models/IconModel.cs create mode 100644 src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts create mode 100644 src/Umbraco.Web.BackOffice/Controllers/IconController.cs create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-activity.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-add.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-adressbook.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-alarm-clock.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-anchor.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-app.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-error.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrivals.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-down.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-left.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-right.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-up.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-art-easel.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-article.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-attachment.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-auction-hammer.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-autofill.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-award.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-3.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-baby-stroller.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-backspace.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-add.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-count.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-remove.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-restricted.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ball.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-band-aid.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bar-chart.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-barcode.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bars.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-full.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-low.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-beer-glass.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell-off.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-dollar.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-euro.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-pound.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-yen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-billboard.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-dollar.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-euro.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-pound.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-yen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-binarycode.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-binoculars.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bird.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-birthday-cake.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-block.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-blueprint.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bluetooth.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-boat-shipping.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bomb.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bones.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-book.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bookmark.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-books.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-open.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-box.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-brackets.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-brick.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-briefcase.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-browser-window.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bug.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bulleted-list.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-burn.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bus.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-calculator.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-camcorder.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-camera-roll.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-candy.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-caps-lock.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-car.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cash-register.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-categories.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-certificate.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart-curve.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat-active.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-check.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted-active.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-empty.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-chess.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cinema.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted-active.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-circuits.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-circus.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-client.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-clothes-hanger.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-drive.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-upload.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloudy.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-clubs.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cocktail.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-code.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coffee.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-dollar.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-euro.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-pound.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-yen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-color-bucket.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-colorpicker.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-columns.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-comb.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock-open.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-command.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-company.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-compress.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-connection.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-console.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-contrast.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coverflow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-crop.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-crosshair.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cupcake.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-curve.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cut.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-dashboard.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-defrag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete-key.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-departure.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-desk.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-desktop.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagnostics.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamond.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamonds.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-dice.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-disc.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-disk-image.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-display.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-dna.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-dock-connector.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-document-dashed-line.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-document.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-documents.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-dollar-bag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-donate.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-download-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-download.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-drop.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-eco.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-economy.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-edit.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-eject.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-employee.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-energy-saving-bulb.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-enter.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-equalizer.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-escape.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ethernet.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-euro-bag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-exit-fullscreen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-eye.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-facebook-like.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-factory.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-favorite.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-female-symbol.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-file-cabinet.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-files.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter-arrows.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-fingerprint.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-fire.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewall.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewire.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-flash.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-flashlight.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-flowerpot.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-open.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-outline.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-folders.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-font.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-food.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-footprints.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-forking.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-game.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-geometry.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-gift.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-glasses.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-asia.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-europe-africa.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-america.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-asia.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-europe-africa.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-gps.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-graduate.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-grid.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hammer.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-handprint.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-handshake.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hat.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hd.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-headphones.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-headset.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hearts.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-height.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-help-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-help.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-home.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hourglass.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-imac.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-inactive-line.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox-full.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-indent.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-infinity.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-info.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-invoice.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ipad.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-iphone.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-item-arrangement.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-junk.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-key.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyboard.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-keychain.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyhole.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-lab.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-laptop.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-layout.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-left-double-arrow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-legal.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-lense.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-library.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-down.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-up.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb-active.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightning.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-link.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-linux-tux.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-list.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-load.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-loading.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-locate.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-near-me.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-nearby.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-lock.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-log-out.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-logout.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-loupe.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-magnet.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-mailbox.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-and-female.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-symbol.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-location.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-marker.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-map.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-medal.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-medical-emergency.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-medicine.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-meeting.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-megaphone.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-merge.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-open.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-unopened.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-message.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-microscope.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-mindmap.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-mobile.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular-network.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-mountain.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse-cursor.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-credit-cards.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-windows.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-music.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-name-badge.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-bottom.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-down.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-first.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-horizontal.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-last.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-left.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-right.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-road.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-top.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-up.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-vertical.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigational-arrow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-network-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-next-media.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-next.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-nodes.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-key.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-phone.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-operator.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ordered-list.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-os-x.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-out.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-outbox.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-outdent.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-add.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-down.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-remove.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-restricted.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-up.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-paint-roller.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-palette.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-panel-show.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pannel-close.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pants.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-bag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-parachute-drop.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-parental-control.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-partly-cloudy.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-paste-in.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-path.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pause.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pc.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-female.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-people.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone-ring.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-photo-album.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-picture.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pie-chart.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-piggy-bank.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pin-location.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-piracy.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-plane.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-planet.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-play.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-playing-cards.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-playlist.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-plugin.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-podcast.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-poker-chip.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-poll.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-post-it.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pound-bag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-power-outlet.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-power.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-presentation.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous-media.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-dollar.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-euro.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-pound.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-yen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-print.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-printer-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-projector.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pulse.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pushpin.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-qr-code.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-quote.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-receiver.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-rain.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-rate.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-re-post.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-readonly.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-dollar.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-euro.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-pound.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-yen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-reception.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-record.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-redo.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-refresh.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-remote.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-remove.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat-one.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-reply-arrow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-resize.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-return-to-top.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-right-double-arrow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-road.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-roadsign.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-rocket.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-rss.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-safe.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-safedial.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sandbox-toys.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-satellite-dish.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-save.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-scan.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-school.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-screensharing.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-script-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-script.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-scull.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-search.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-security-camera.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sensor.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-server-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-server.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-share.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sharing-iphone.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shield.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shift.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping-box.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shoe.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shorts.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shuffle.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sience.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-simcard.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-single-note.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sitemap.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sleep.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-slideshow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley-inverted.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-snow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-low.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-medium.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-off.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-waves.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-spades.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-speaker.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-speed-gauge.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-split-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-split.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sprout.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-squiggly-line.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ssd.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-stacked-disks.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-stamp.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-hand.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-store.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-stream.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sunny.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sweatshirt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sync.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-t-shirt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab-key.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tactics.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tags.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-takeaway-cup.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-target.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperatrure-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperature.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-terminal.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-theater.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-theif.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-thought-bubble.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-down.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-up.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnail-list.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails-small.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ticket.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-time.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-timer.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tools.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-top.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-traffic-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-trafic.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-train.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tree.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-trophy.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-truck.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv-old.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-content.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-contour.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-deploy.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-developer.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-media.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-members.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-settings.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-users.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umbrella.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-undo.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-universal.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-unlocked.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-untitled.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb-connector.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-female.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-glasses.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-user.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-users-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-users.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-utilities.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-vcard.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-video.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-voice.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-wall-plug.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-wallet.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-wand.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-war.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-weight.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-width.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-wifi.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-popin.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-sizes.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-windows.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-wine-glass.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrench.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrong.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-yen-bag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-zip.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-zom-out.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-zoom-in.svg create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbuttonellipsis.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbfocuslock.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbsearchfilter.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/umbicon.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/services/focuslock.service.js create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-ellipsis.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-icon.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-tags-editor.less create mode 100644 src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-button-ellipsis.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/forms/umb-search-filter.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/umb-icon.html delete mode 100644 src/Umbraco.Web.UI.Client/src/views/dashboard/default/ourumbraco.jpg create mode 100644 src/Umbraco.Web.UI.Client/src/views/dashboard/default/ourumbraco.png delete mode 100644 src/Umbraco.Web.UI.Client/src/views/dashboard/default/umbracotv.jpg create mode 100644 src/Umbraco.Web.UI.Client/src/views/dashboard/default/umbracotv.png delete mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowdeleteconfirm.controller.js delete mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowdeleteconfirm.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/overlays/rowdeleteconfirm.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.html delete mode 100644 src/Umbraco.Web.UI/Views/Partials/Grid/Editors/Media.cshtml diff --git a/build/NuSpecs/UmbracoCms.Web.nuspec b/build/NuSpecs/UmbracoCms.Web.nuspec index 47aab4cdb8..1aeead52a5 100644 --- a/build/NuSpecs/UmbracoCms.Web.nuspec +++ b/build/NuSpecs/UmbracoCms.Web.nuspec @@ -33,6 +33,7 @@ + diff --git a/src/Umbraco.Configuration/Legacy/GlobalSettings.cs b/src/Umbraco.Configuration/Legacy/GlobalSettings.cs index d93297ca90..fabe95f5bd 100644 --- a/src/Umbraco.Configuration/Legacy/GlobalSettings.cs +++ b/src/Umbraco.Configuration/Legacy/GlobalSettings.cs @@ -146,6 +146,9 @@ namespace Umbraco.Core.Configuration.Legacy } } + + + /// /// Gets or sets the configuration status. This will return the version number of the currently installed umbraco instance. /// @@ -315,6 +318,15 @@ namespace Umbraco.Core.Configuration.Legacy private string _databaseFactoryServerVersion; public string DatabaseFactoryServerVersion => GetterWithDefaultValue(Constants.AppSettings.Debug.DatabaseFactoryServerVersion, string.Empty, ref _databaseFactoryServerVersion); + + + private string _iconsPath; + /// + /// Gets the path to folder containing the icons used in the umbraco backoffice (/umbraco/assets/icons by default). + /// + /// The icons path. + public string IconsPath => GetterWithDefaultValue(Constants.AppSettings.IconsPath, $"{UmbracoPath}/assets/icons", ref _iconsPath); + private string _mainDomLock; public string MainDomLock => GetterWithDefaultValue(Constants.AppSettings.MainDomLock, string.Empty, ref _mainDomLock); diff --git a/src/Umbraco.Configuration/Models/GlobalSettings.cs b/src/Umbraco.Configuration/Models/GlobalSettings.cs index d1f3f12017..02b73d1196 100644 --- a/src/Umbraco.Configuration/Models/GlobalSettings.cs +++ b/src/Umbraco.Configuration/Models/GlobalSettings.cs @@ -47,6 +47,8 @@ namespace Umbraco.Configuration.Models public bool UseHttps => _configuration.GetValue(Prefix + "UseHttps", false); public int VersionCheckPeriod => _configuration.GetValue(Prefix + "VersionCheckPeriod", 7); public string UmbracoPath => _configuration.GetValue(Prefix + "UmbracoPath", "~/umbraco"); + public string IconsPath => _configuration.GetValue(Prefix + "IconsPath", $"{UmbracoPath}/assets/icons"); + public string UmbracoCssPath => _configuration.GetValue(Prefix + "UmbracoCssPath", "~/css"); public string UmbracoScriptsPath => diff --git a/src/Umbraco.Core/Configuration/IGlobalSettings.cs b/src/Umbraco.Core/Configuration/IGlobalSettings.cs index bf963bcec7..26d833613f 100644 --- a/src/Umbraco.Core/Configuration/IGlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/IGlobalSettings.cs @@ -20,6 +20,16 @@ /// The reserved paths. string ReservedPaths { get; } + /// + /// Gets the path to umbraco's icons directory (/umbraco/assets/icons by default). + /// + string IconsPath { get; } + + /// + /// Gets or sets the configuration status. This will return the version number of the currently installed umbraco instance. + /// + string ConfigurationStatus { get; set; } + /// /// Gets the time out in minutes. /// diff --git a/src/Umbraco.Core/Constants-AppSettings.cs b/src/Umbraco.Core/Constants-AppSettings.cs index 94370930de..36d471b950 100644 --- a/src/Umbraco.Core/Constants-AppSettings.cs +++ b/src/Umbraco.Core/Constants-AppSettings.cs @@ -41,15 +41,20 @@ namespace Umbraco.Core public const string ConfigurationStatus = "Umbraco.Core.ConfigurationStatus"; /// - /// Gets the path to umbraco's root directory (/umbraco by default). + /// The path to umbraco's root directory (/umbraco by default). /// public const string UmbracoPath = "Umbraco.Core.Path"; + /// + /// Gets the path to umbraco's icons directory (/umbraco/assets/icons by default). + /// + public const string IconsPath = "Umbraco.Icons.Path"; + /// /// The reserved urls from web.config. /// public const string ReservedUrls = "Umbraco.Core.ReservedUrls"; - + /// /// The path of the stylesheet folder. /// diff --git a/src/Umbraco.Core/Constants-SvgSanitizer.cs b/src/Umbraco.Core/Constants-SvgSanitizer.cs new file mode 100644 index 0000000000..447ea66668 --- /dev/null +++ b/src/Umbraco.Core/Constants-SvgSanitizer.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; + +namespace Umbraco.Core +{ + public static partial class Constants + { + /// + /// Defines the alias identifiers for Umbraco's core application sections. + /// + public static class SvgSanitizer + { + /// + /// Allowlist for SVG attributes. + /// + public static readonly IList Attributes = new [] { "accent-height", "accumulate", "additive", "alignment-baseline", "allowReorder", "alphabetic", "amplitude", "arabic-form", "ascent", "attributeName", "attributeType", "autoReverse", "azimuth", "baseFrequency", "baseline-shift", "baseProfile", "bbox", "begin", "bias", "by", "calcMode", "cap-height", "class", "clip", "clipPathUnits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "contentScriptType", "contentStyleType", "cursor", "cx", "cy", "d", "decelerate", "descent", "diffuseConstant", "direction", "display", "divisor", "dominant-baseline", "dur", "dx", "dy", "edgeMode", "elevation", "enable-background", "end", "exponent", "externalResourcesRequired", "Section", "fill", "fill-opacity", "fill-rule", "filter", "filterRes", "filterUnits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "format", "from", "fr", "fx", "fy", "g1", "g2", "glyph-name", "glyph-orientation-horizontal", "glyph-orientation-vertical", "glyphRef", "gradientTransform", "gradientUnits", "hanging", "height", "href", "hreflang", "horiz-adv-x", "horiz-origin-x", "ISection", "id", "ideographic", "image-rendering", "in", "in2", "intercept", "k", "k1", "k2", "k3", "k4", "kernelMatrix", "kernelUnitLength", "kerning", "keyPoints", "keySplines", "keyTimes", "lang", "lengthAdjust", "letter-spacing", "lighting-color", "limitingConeAngle", "local", "MSection", "marker-end", "marker-mid", "marker-start", "markerHeight", "markerUnits", "markerWidth", "mask", "maskContentUnits", "maskUnits", "mathematical", "max", "media", "method", "min", "mode", "NSection", "name", "numOctaves", "offset", "opacity", "operator", "order", "orient", "orientation", "origin", "overflow", "overline-position", "overline-thickness", "panose-1", "paint-order", "path", "pathLength", "patternContentUnits", "patternTransform", "patternUnits", "ping", "pointer-events", "points", "pointsAtX", "pointsAtY", "pointsAtZ", "preserveAlpha", "preserveAspectRatio", "primitiveUnits", "r", "radius", "referrerPolicy", "refX", "refY", "rel", "rendering-intent", "repeatCount", "repeatDur", "requiredExtensions", "requiredFeatures", "restart", "result", "rotate", "rx", "ry", "scale", "seed", "shape-rendering", "slope", "spacing", "specularConstant", "specularExponent", "speed", "spreadMethod", "startOffset", "stdDeviation", "stemh", "stemv", "stitchTiles", "stop-color", "stop-opacity", "strikethrough-position", "strikethrough-thickness", "string", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "surfaceScale", "systemLanguage", "tabindex", "tableValues", "target", "targetX", "targetY", "text-anchor", "text-decoration", "text-rendering", "textLength", "to", "transform", "type", "u1", "u2", "underline-position", "underline-thickness", "unicode", "unicode-bidi", "unicode-range", "units-per-em", "v-alphabetic", "v-hanging", "v-ideographic", "v-mathematical", "values", "vector-effect", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "viewBox", "viewTarget", "visibility", "width", "widths", "word-spacing", "writing-mode", "x", "x-height", "x1", "x2", "xChannelSelector", "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show", "xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "y", "y1", "y2", "yChannelSelector", "z", "zoomAndPan" }; + + /// + /// Allowlist for SVG tabs. + /// + public static readonly IList Tags = new [] { "a", "altGlyph", "altGlyphDef", "altGlyphItem", "animate", "animateColor", "animateMotion", "animateTransform", "circle", "clipPath", "color-profile", "cursor", "defs", "desc", "discard", "ellipse", "feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence", "filter", "font", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignObject", "g", "glyph", "glyphRef", "hatch", "hatchpath", "hkern", "image", "line", "linearGradient", "marker", "mask", "mesh", "meshgradient", "meshpatch", "meshrow", "metadata", "missing-glyph", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "set", "solidcolor", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tref", "tspan", "unknown", "use", "view", "vkern" }; + } + } +} diff --git a/src/Umbraco.Core/Constants-SystemDirectories.cs b/src/Umbraco.Core/Constants-SystemDirectories.cs index e33247be63..53e14bb6ec 100644 --- a/src/Umbraco.Core/Constants-SystemDirectories.cs +++ b/src/Umbraco.Core/Constants-SystemDirectories.cs @@ -31,6 +31,8 @@ public const string Packages = Data + "/packages"; public const string Preview = Data + "/preview"; + + public const string LogFiles= "~/Logs"; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/PropertyTypeBasic.cs b/src/Umbraco.Core/Models/ContentEditing/PropertyTypeBasic.cs index 5ff1744ea2..4252a29567 100644 --- a/src/Umbraco.Core/Models/ContentEditing/PropertyTypeBasic.cs +++ b/src/Umbraco.Core/Models/ContentEditing/PropertyTypeBasic.cs @@ -48,6 +48,14 @@ namespace Umbraco.Web.Models.ContentEditing [ReadOnly(true)] public Guid DataTypeKey { get; set; } + [DataMember(Name = "dataTypeName")] + [ReadOnly(true)] + public string DataTypeName { get; set; } + + [DataMember(Name = "dataTypeIcon")] + [ReadOnly(true)] + public string DataTypeIcon { get; set; } + //SD: Is this really needed ? [DataMember(Name = "groupId")] public int GroupId { get; set; } diff --git a/src/Umbraco.Core/Models/IconModel.cs b/src/Umbraco.Core/Models/IconModel.cs new file mode 100644 index 0000000000..5c79ad6219 --- /dev/null +++ b/src/Umbraco.Core/Models/IconModel.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Web.Models +{ + public class IconModel + { + public string Name { get; set; } + public string SvgString { get; set; } + } +} diff --git a/src/Umbraco.Core/Persistence/Repositories/IMemberGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IMemberGroupRepository.cs index 9c75c051bd..d63b1bb9db 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IMemberGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IMemberGroupRepository.cs @@ -1,10 +1,18 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Umbraco.Core.Models; namespace Umbraco.Core.Persistence.Repositories { public interface IMemberGroupRepository : IReadWriteQueryRepository { + /// + /// Gets a member group by it's uniqueId + /// + /// + /// + IMemberGroup Get(Guid uniqueId); + /// /// Gets a member group by it's name /// diff --git a/src/Umbraco.Core/PropertyEditors/EmailAddressConfiguration.cs b/src/Umbraco.Core/PropertyEditors/EmailAddressConfiguration.cs index 4039a0e3a2..fa8eb830b0 100644 --- a/src/Umbraco.Core/PropertyEditors/EmailAddressConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/EmailAddressConfiguration.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.PropertyEditors; +using System; +using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { @@ -7,7 +8,8 @@ namespace Umbraco.Web.PropertyEditors ///
public class EmailAddressConfiguration { - [ConfigurationField("IsRequired", "Required?", "boolean")] + [ConfigurationField("IsRequired", "Required?", "hidden", Description = "Deprecated; Make this required by selecting mandatory when adding to the document type")] + [Obsolete("No longer used, use `Mandatory` for the property instead. Will be removed in the next major version")] public bool IsRequired { get; set; } } } diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs index a584ea2a9c..2ec0438328 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs @@ -4,35 +4,43 @@ using Umbraco.Core.Models.PublishedContent; namespace Umbraco.Core.PropertyEditors { /// - /// Provides a default overridable implementation for that does nothing. + /// Provides a default implementation for . /// + /// public abstract class PropertyValueConverterBase : IPropertyValueConverter { + /// public virtual bool IsConverter(IPublishedPropertyType propertyType) => false; + /// public virtual bool? IsValue(object value, PropertyValueLevel level) { switch (level) { case PropertyValueLevel.Source: - return value != null && (!(value is string) || string.IsNullOrWhiteSpace((string) value) == false); + // the default implementation uses the old magic null & string comparisons, + // other implementations may be more clever, and/or test the final converted object values + return value != null && (!(value is string stringValue) || !string.IsNullOrWhiteSpace(stringValue)); + case PropertyValueLevel.Inter: + return null; + case PropertyValueLevel.Object: + return null; default: throw new NotSupportedException($"Invalid level: {level}."); } } + [Obsolete("This method is not part of the IPropertyValueConverter contract, therefore not used and will be removed in future versions; use IsValue instead.")] public virtual bool HasValue(IPublishedProperty property, string culture, string segment) { - // the default implementation uses the old magic null & string comparisons, - // other implementations may be more clever, and/or test the final converted object values var value = property.GetSourceValue(culture, segment); - return value != null && (!(value is string) || string.IsNullOrWhiteSpace((string) value) == false); + return value != null && (!(value is string stringValue) || !string.IsNullOrWhiteSpace(stringValue)); } /// public virtual Type GetPropertyValueType(IPublishedPropertyType propertyType) - => typeof (object); + => typeof(object); /// public virtual PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) diff --git a/src/Umbraco.Core/PropertyEditors/TrueFalseConfiguration.cs b/src/Umbraco.Core/PropertyEditors/TrueFalseConfiguration.cs index c6b3953e8c..03973cfc90 100644 --- a/src/Umbraco.Core/PropertyEditors/TrueFalseConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/TrueFalseConfiguration.cs @@ -7,10 +7,16 @@ namespace Umbraco.Web.PropertyEditors /// public class TrueFalseConfiguration { - [ConfigurationField("default", "Default Value", "boolean")] - public string Default { get; set; } // TODO: well, true or false?! + [ConfigurationField("default", "Initial State", "boolean", Description = "The initial state for the toggle, when it is displayed for the first time in the backoffice, eg. for a new content item.")] + public bool Default { get; set; } - [ConfigurationField("labelOn", "Write a label text", "textstring")] - public string Label { get; set; } + [ConfigurationField("showLabels", "Show toggle labels", "boolean", Description = "Show labels next to toggle button.")] + public bool ShowLabels { get; set; } + + [ConfigurationField("labelOn", "Label On", "textstring", Description = "Label text when enabled.")] + public string LabelOn { get; set; } + + [ConfigurationField("labelOff", "Label Off", "textstring", Description = "Label text when disabled.")] + public string LabelOff { get; set; } } } diff --git a/src/Umbraco.Core/Scheduling/TempFileCleanup.cs b/src/Umbraco.Core/Scheduling/TempFileCleanup.cs index 90bf4ee9eb..6ac1ff61fe 100644 --- a/src/Umbraco.Core/Scheduling/TempFileCleanup.cs +++ b/src/Umbraco.Core/Scheduling/TempFileCleanup.cs @@ -51,6 +51,7 @@ namespace Umbraco.Web.Scheduling if (!dir.Exists) { _logger.Debug("The cleanup folder doesn't exist {Folder}", dir.FullName); + return; } var files = dir.GetFiles("*.*", SearchOption.AllDirectories); @@ -60,6 +61,7 @@ namespace Umbraco.Web.Scheduling { try { + file.IsReadOnly = false; file.Delete(); } catch (Exception ex) diff --git a/src/Umbraco.Core/Services/IMemberGroupService.cs b/src/Umbraco.Core/Services/IMemberGroupService.cs index 6a554aad31..9261dcfdf6 100644 --- a/src/Umbraco.Core/Services/IMemberGroupService.cs +++ b/src/Umbraco.Core/Services/IMemberGroupService.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Umbraco.Core.Models; namespace Umbraco.Core.Services @@ -7,6 +8,7 @@ namespace Umbraco.Core.Services { IEnumerable GetAll(); IMemberGroup GetById(int id); + IMemberGroup GetById(Guid id); IEnumerable GetByIds(IEnumerable ids); IMemberGroup GetByName(string name); void Save(IMemberGroup memberGroup, bool raiseEvents = true); diff --git a/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs b/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs index c4e7f264fb..24800fa98a 100644 --- a/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs +++ b/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs @@ -113,6 +113,9 @@ namespace Umbraco.Examine var allLangs = _languageService.GetAllLanguages().Select(x => x.IsoCode.ToLowerInvariant()).ToList(); + // the chars [*-_] in the query will mess everything up so let's remove those + query = Regex.Replace(query, "[\\*\\-_]", ""); + //check if text is surrounded by single or double quotes, if so, then exact match var surroundedByQuotes = Regex.IsMatch(query, "^\".*?\"$") || Regex.IsMatch(query, "^\'.*?\'$"); diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs index dfcc401ea3..f2e028e6de 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs @@ -7,6 +7,7 @@ using Serilog.Core; using Serilog.Events; using Serilog.Formatting; using Serilog.Formatting.Compact; +using Umbraco.Core.IO; using Umbraco.Core.Hosting; using Umbraco.Core.Logging.Serilog.Enrichers; @@ -22,7 +23,7 @@ namespace Umbraco.Core.Logging.Serilog /// It is highly recommended that you keep/use this default in your own logging config customizations /// /// A Serilog LoggerConfiguration - /// + /// /// public static LoggerConfiguration MinimalConfiguration( this LoggerConfiguration logConfig, @@ -33,15 +34,15 @@ namespace Umbraco.Core.Logging.Serilog //Set this environment variable - so that it can be used in external config file //add key="serilog:write-to:RollingFile.pathFormat" value="%BASEDIR%\logs\log.txt" /> + Environment.SetEnvironmentVariable("BASEDIR", hostingEnvironment.MapPathContentRoot("/").TrimEnd("\\"), EnvironmentVariableTarget.Process); Environment.SetEnvironmentVariable("UMBLOGDIR", loggingConfiguration.LogDirectory, EnvironmentVariableTarget.Process); - Environment.SetEnvironmentVariable("BASEDIR", hostingEnvironment.ApplicationPhysicalPath, EnvironmentVariableTarget.Process); - Environment.SetEnvironmentVariable("MACHINENAME", Environment.MachineName, EnvironmentVariableTarget.Process); + Environment.SetEnvironmentVariable("MACHINENAME", Environment.MachineName, EnvironmentVariableTarget.Process); logConfig.MinimumLevel.Verbose() //Set to highest level of logging (as any sinks may want to restrict it to Errors only) .Enrich.WithProcessId() .Enrich.WithProcessName() .Enrich.WithThreadId() - .Enrich.WithProperty(AppDomainId, AppDomain.CurrentDomain.Id) + .Enrich.WithProperty(AppDomainId, AppDomain.CurrentDomain.Id) .Enrich.WithProperty("AppDomainAppId", hostingEnvironment.ApplicationId.ReplaceNonAlphanumericChars(string.Empty)) .Enrich.WithProperty("MachineName", Environment.MachineName) .Enrich.With() @@ -57,11 +58,14 @@ namespace Umbraco.Core.Logging.Serilog /// /// The log level you wish the JSON file to collect - default is Verbose (highest) /// The number of days to keep log files. Default is set to null which means all logs are kept - public static LoggerConfiguration OutputDefaultTextFile(this LoggerConfiguration logConfig, ILoggingConfiguration loggingConfiguration, LogEventLevel minimumLevel = LogEventLevel.Verbose, int? retainedFileCount = null) + public static LoggerConfiguration OutputDefaultTextFile( + this LoggerConfiguration logConfig, + IHostingEnvironment hostingEnvironment, + ILoggingConfiguration loggingConfiguration, LogEventLevel minimumLevel = LogEventLevel.Verbose, int? retainedFileCount = null) { //Main .txt logfile - in similar format to older Log4Net output //Ends with ..txt as Date is inserted before file extension substring - logConfig.WriteTo.File(Path.Combine(loggingConfiguration.LogDirectory, $@"UmbracoTraceLog.{Environment.MachineName}..txt"), + logConfig.WriteTo.File(Path.Combine(hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.LogFiles), $"UmbracoTraceLog.{Environment.MachineName}..txt"), shared: true, rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: minimumLevel, @@ -115,11 +119,15 @@ namespace Umbraco.Core.Logging.Serilog /// /// The log level you wish the JSON file to collect - default is Verbose (highest) /// The number of days to keep log files. Default is set to null which means all logs are kept - public static LoggerConfiguration OutputDefaultJsonFile(this LoggerConfiguration logConfig, ILoggingConfiguration loggingConfiguration, LogEventLevel minimumLevel = LogEventLevel.Verbose, int? retainedFileCount = null) + public static LoggerConfiguration OutputDefaultJsonFile( + this LoggerConfiguration logConfig, + IHostingEnvironment hostingEnvironment, + ILoggingConfiguration loggingConfiguration, LogEventLevel minimumLevel = LogEventLevel.Verbose, int? retainedFileCount = null) { //.clef format (Compact log event format, that can be imported into local SEQ & will make searching/filtering logs easier) //Ends with ..txt as Date is inserted before file extension substring - logConfig.WriteTo.File(new CompactJsonFormatter(), Path.Combine(loggingConfiguration.LogDirectory, $@"UmbracoTraceLog.{Environment.MachineName}..json"), + logConfig.WriteTo.File(new CompactJsonFormatter(), + Path.Combine(hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.LogFiles) ,$"UmbracoTraceLog.{Environment.MachineName}..json"), shared: true, rollingInterval: RollingInterval.Day, //Create a new JSON file every day retainedFileCountLimit: retainedFileCount, //Setting to null means we keep all files - default is 31 days diff --git a/src/Umbraco.Infrastructure/Logging/Viewer/SerilogJsonLogViewer.cs b/src/Umbraco.Infrastructure/Logging/Viewer/SerilogJsonLogViewer.cs index 366a0fb9de..5bf079c1b4 100644 --- a/src/Umbraco.Infrastructure/Logging/Viewer/SerilogJsonLogViewer.cs +++ b/src/Umbraco.Infrastructure/Logging/Viewer/SerilogJsonLogViewer.cs @@ -5,8 +5,6 @@ using System.Linq; using Newtonsoft.Json; using Serilog.Events; using Serilog.Formatting.Compact.Reader; -using Umbraco.Core.Hosting; -using Umbraco.Core.IO; namespace Umbraco.Core.Logging.Viewer { diff --git a/src/Umbraco.Infrastructure/Models/ContentEditing/EntityBasic.cs b/src/Umbraco.Infrastructure/Models/ContentEditing/EntityBasic.cs index 512bc1517d..4776983687 100644 --- a/src/Umbraco.Infrastructure/Models/ContentEditing/EntityBasic.cs +++ b/src/Umbraco.Infrastructure/Models/ContentEditing/EntityBasic.cs @@ -61,8 +61,7 @@ namespace Umbraco.Web.Models.ContentEditing /// The path of the entity /// [DataMember(Name = "path")] - public string Path { get; set; } - + public string Path { get; set; } /// /// A collection of extra data that is available for this specific entity/entity type /// diff --git a/src/Umbraco.Infrastructure/Models/ContentEditing/MediaItemDisplay.cs b/src/Umbraco.Infrastructure/Models/ContentEditing/MediaItemDisplay.cs index 0118645b60..a5d538c6ac 100644 --- a/src/Umbraco.Infrastructure/Models/ContentEditing/MediaItemDisplay.cs +++ b/src/Umbraco.Infrastructure/Models/ContentEditing/MediaItemDisplay.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Models.ContentEditing; namespace Umbraco.Web.Models.ContentEditing { /// - /// A model representing a content item to be displayed in the back office + /// A model representing a media item to be displayed in the back office /// [DataContract(Name = "content", Namespace = "")] public class MediaItemDisplay : ListViewAwareContentItemDisplayBase diff --git a/src/Umbraco.Infrastructure/Models/ContentEditing/MemberDisplay.cs b/src/Umbraco.Infrastructure/Models/ContentEditing/MemberDisplay.cs index 2f53f6f73b..8c97925403 100644 --- a/src/Umbraco.Infrastructure/Models/ContentEditing/MemberDisplay.cs +++ b/src/Umbraco.Infrastructure/Models/ContentEditing/MemberDisplay.cs @@ -18,6 +18,9 @@ namespace Umbraco.Web.Models.ContentEditing ContentApps = new List(); } + [DataMember(Name = "contentType")] + public ContentTypeBasic ContentType { get; set; } + [DataMember(Name = "username")] public string Username { get; set; } diff --git a/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs b/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs index 9341b2f756..75a64c7b1e 100644 --- a/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs +++ b/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs @@ -356,7 +356,7 @@ namespace Umbraco.Web.Models.Mapping target.Properties = context.MapEnumerable(source.Properties); } - // Umbraco.Code.MapAll -Editor -View -Config -ContentTypeId -ContentTypeName -Locked + // Umbraco.Code.MapAll -Editor -View -Config -ContentTypeId -ContentTypeName -Locked -DataTypeIcon -DataTypeName private static void Map(PropertyTypeBasic source, PropertyTypeDisplay target, MapperContext context) { target.Alias = source.Alias; @@ -373,7 +373,7 @@ namespace Umbraco.Web.Models.Mapping target.Validation = source.Validation; } - // Umbraco.Code.MapAll -Editor -View -Config -ContentTypeId -ContentTypeName -Locked + // Umbraco.Code.MapAll -Editor -View -Config -ContentTypeId -ContentTypeName -Locked -DataTypeIcon -DataTypeName private static void Map(MemberPropertyTypeBasic source, MemberPropertyTypeDisplay target, MapperContext context) { target.Alias = source.Alias; diff --git a/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs b/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs index ba7b5cddf2..3663095739 100644 --- a/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs +++ b/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs @@ -40,6 +40,7 @@ namespace Umbraco.Web.Models.Mapping target.Trashed = source.Trashed; target.Udi = Udi.Create(ObjectTypes.GetUdiType(source.NodeObjectType), source.Key); + if (source is IContentEntitySlim contentSlim) { source.AdditionalData["ContentTypeAlias"] = contentSlim.ContentTypeAlias; @@ -52,6 +53,8 @@ namespace Umbraco.Web.Models.Mapping if (source is IMediaEntitySlim mediaSlim) { + //pass UpdateDate for MediaPicker ListView ordering + source.AdditionalData["UpdateDate"] = mediaSlim.UpdateDate; source.AdditionalData["MediaPath"] = mediaSlim.MediaPath; } @@ -181,7 +184,8 @@ namespace Umbraco.Web.Models.Mapping target.Name = source.Values.ContainsKey($"nodeName_{culture}") ? source.Values[$"nodeName_{culture}"] : target.Name; } - if (source.Values.TryGetValue(UmbracoExamineFieldNames.UmbracoFileFieldName, out var umbracoFile)) + if (source.Values.TryGetValue(UmbracoExamineFieldNames.UmbracoFileFieldName, out var umbracoFile) && + umbracoFile.IsNullOrWhiteSpace() == false) { if (umbracoFile != null) { diff --git a/src/Umbraco.Infrastructure/Models/Mapping/PropertyTypeGroupMapper.cs b/src/Umbraco.Infrastructure/Models/Mapping/PropertyTypeGroupMapper.cs index 6cee1d9246..32ea6fce3f 100644 --- a/src/Umbraco.Infrastructure/Models/Mapping/PropertyTypeGroupMapper.cs +++ b/src/Umbraco.Infrastructure/Models/Mapping/PropertyTypeGroupMapper.cs @@ -241,6 +241,8 @@ namespace Umbraco.Web.Models.Mapping Inherited = inherited, DataTypeId = p.DataTypeId, DataTypeKey = p.DataTypeKey, + DataTypeName = dataType.Name, + DataTypeIcon = propertyEditor.Icon, SortOrder = p.SortOrder, ContentTypeId = contentType.Id, ContentTypeName = contentType.Name, diff --git a/src/Umbraco.Infrastructure/Persistence/Querying/ExpressionVisitorBase.cs b/src/Umbraco.Infrastructure/Persistence/Querying/ExpressionVisitorBase.cs index ab4f59591f..91844430a9 100644 --- a/src/Umbraco.Infrastructure/Persistence/Querying/ExpressionVisitorBase.cs +++ b/src/Umbraco.Infrastructure/Persistence/Querying/ExpressionVisitorBase.cs @@ -744,7 +744,9 @@ namespace Umbraco.Core.Persistence.Querying var c = exp[0]; return (c == '"' || c == '`' || c == '\'') && exp[exp.Length - 1] == c - ? exp.Substring(1, exp.Length - 2) + ? exp.Length == 1 + ? string.Empty + : exp.Substring(1, exp.Length - 2) : exp; } } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs index 3d006914a2..61ced57149 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs @@ -368,7 +368,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (isContent || isMedia || isMember) sql - .AndSelect(x => Alias(x.Id, "versionId")) + .AndSelect(x => Alias(x.Id, "versionId"), x=>x.VersionDate) .AndSelect(x => x.Alias, x => x.Icon, x => x.Thumbnail, x => x.IsContainer, x => x.Variations); if (isContent) @@ -489,7 +489,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (isContent || isMedia || isMember) sql - .AndBy(x => x.Id) + .AndBy(x => x.Id, x => x.VersionDate) .AndBy(x => x.Alias, x => x.Icon, x => x.Thumbnail, x => x.IsContainer, x => x.Variations); if (defaultSort) @@ -593,6 +593,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement public string Text { get; set; } public Guid NodeObjectType { get; set; } public DateTime CreateDate { get; set; } + public DateTime VersionDate { get; set; } public int Children { get; set; } public int VersionId { get; set; } public string Alias { get; set; } @@ -626,6 +627,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { entity.Trashed = dto.Trashed; entity.CreateDate = dto.CreateDate; + entity.UpdateDate = dto.VersionDate; entity.CreatorId = dto.UserId ?? Constants.Security.UnknownUserId; entity.Id = dto.NodeId; entity.Key = dto.UniqueId; diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberGroupRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberGroupRepository.cs index c138550de5..edd6dc0ebb 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberGroupRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberGroupRepository.cs @@ -69,7 +69,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected override string GetBaseWhereClause() { - return "umbracoNode.id = @id"; + return $"{Constants.DatabaseSchema.Tables.Node}.id = @id"; } protected override IEnumerable GetDeleteClauses() @@ -115,6 +115,16 @@ namespace Umbraco.Core.Persistence.Repositories.Implement entity.ResetDirtyProperties(); } + public IMemberGroup Get(Guid uniqueId) + { + var sql = GetBaseQuery(false); + sql.Where("umbracoNode.uniqueId = @uniqueId", new { uniqueId }); + + var dto = Database.Fetch(SqlSyntax.SelectTop(sql, 1)).FirstOrDefault(); + + return dto == null ? null : MemberGroupFactory.BuildEntity(dto); + } + public IMemberGroup GetByName(string name) { return IsolatedCache.GetCacheItem( diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs index e191ac08bf..5ba32a4d2f 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs @@ -548,9 +548,9 @@ ORDER BY colName"; { userDto.EmailConfirmedDate = null; userDto.SecurityStampToken = entity.SecurityStamp = Guid.NewGuid().ToString(); - + changedCols.Add("emailConfirmedDate"); - changedCols.Add("securityStampToken"); + changedCols.Add("securityStampToken"); } //only update the changed cols @@ -694,7 +694,13 @@ ORDER BY colName"; else sql.WhereNotIn(x => x.Id, inSql); - return ConvertFromDtos(Database.Fetch(sql)); + + var dtos = Database.Fetch(sql); + + //adds missing bits like content and media start nodes + PerformGetReferencedDtos(dtos); + + return ConvertFromDtos(dtos); } /// diff --git a/src/Umbraco.Infrastructure/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs b/src/Umbraco.Infrastructure/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs index 779e4362ae..ec4cfca498 100644 --- a/src/Umbraco.Infrastructure/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs +++ b/src/Umbraco.Infrastructure/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs @@ -32,6 +32,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax V2014 = 6, V2016 = 7, V2017 = 8, + V2019 = 9, Other = 99 } @@ -40,7 +41,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax Unknown = 0, Desktop = 1, Standard = 2, - Enterprise = 3, + Enterprise = 3,// Also developer edition Express = 4, Azure = 5 } @@ -81,6 +82,8 @@ namespace Umbraco.Core.Persistence.SqlSyntax { case "??": return VersionName.Invalid; + case "15": + return VersionName.V2019; case "14": return VersionName.V2017; case "13": diff --git a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs index 837fe6cba3..e243ea45ef 100644 --- a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs @@ -182,6 +182,7 @@ namespace Umbraco.Core.Persistence case SqlServerSyntaxProvider.VersionName.V2014: case SqlServerSyntaxProvider.VersionName.V2016: case SqlServerSyntaxProvider.VersionName.V2017: + case SqlServerSyntaxProvider.VersionName.V2019: _databaseType = DatabaseType.SqlServer2012; break; // else leave unchanged diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs index 3d82dc2809..0bfa5899c9 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs @@ -13,7 +13,7 @@ namespace Umbraco.Web.PropertyEditors [DataEditor( Constants.PropertyEditors.Aliases.Boolean, EditorType.PropertyValue | EditorType.MacroParameter, - "Checkbox", + "Toggle", "boolean", ValueType = ValueTypes.Integer, Group = Constants.PropertyEditors.Groups.Common, diff --git a/src/Umbraco.Infrastructure/PropertyEditors/UserPickerConfiguration.cs b/src/Umbraco.Infrastructure/PropertyEditors/UserPickerConfiguration.cs index 4d497867a1..bf3cd197a3 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/UserPickerConfiguration.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/UserPickerConfiguration.cs @@ -7,7 +7,8 @@ namespace Umbraco.Web.PropertyEditors { public override IDictionary DefaultConfiguration => new Dictionary { - {"entityType", "User"} + { "entityType", "User" }, + { "multiPicker", "0" } }; } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/UserPickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/UserPickerPropertyEditor.cs index 429527f3eb..194924adf1 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/UserPickerPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/UserPickerPropertyEditor.cs @@ -8,8 +8,8 @@ namespace Umbraco.Web.PropertyEditors { [DataEditor( Constants.PropertyEditors.Aliases.UserPicker, - "User picker", - "entitypicker", + "User Picker", + "userpicker", ValueType = ValueTypes.Integer, Group = Constants.PropertyEditors.Groups.People, Icon = Constants.Icons.User)] diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs index 19cca866df..87e5ebec15 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs @@ -31,6 +31,8 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters public override object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview) { + if (source == null) return null; + var attemptConvertInt = source.TryConvertTo(); if (attemptConvertInt.Success) return attemptConvertInt.Result; diff --git a/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs b/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs index 4585433be6..4cd85bc408 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs @@ -3006,6 +3006,8 @@ namespace Umbraco.Core.Services.Implement _documentBlueprintRepository.Save(content); + Audit(AuditType.Save, Constants.Security.SuperUserId, content.Id, $"Saved content template: {content.Name}"); + scope.Events.Dispatch(SavedBlueprint, this, new SaveEventArgs(content), "SavedBlueprint"); scope.Complete(); diff --git a/src/Umbraco.Infrastructure/Services/Implement/MemberGroupService.cs b/src/Umbraco.Infrastructure/Services/Implement/MemberGroupService.cs index c879a00ccb..308080bbf4 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/MemberGroupService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/MemberGroupService.cs @@ -70,6 +70,14 @@ namespace Umbraco.Core.Services.Implement } } + public IMemberGroup GetById(Guid id) + { + using (var scope = ScopeProvider.CreateScope(autoComplete: true)) + { + return _memberGroupRepository.Get(id); + } + } + public IMemberGroup GetByName(string name) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) diff --git a/src/Umbraco.Infrastructure/Services/Implement/RelationService.cs b/src/Umbraco.Infrastructure/Services/Implement/RelationService.cs index 4b53709de9..c629466edf 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/RelationService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/RelationService.cs @@ -15,13 +15,15 @@ namespace Umbraco.Core.Services.Implement private readonly IEntityService _entityService; private readonly IRelationRepository _relationRepository; private readonly IRelationTypeRepository _relationTypeRepository; + private readonly IAuditRepository _auditRepository; public RelationService(IScopeProvider uowProvider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IEntityService entityService, - IRelationRepository relationRepository, IRelationTypeRepository relationTypeRepository) + IRelationRepository relationRepository, IRelationTypeRepository relationTypeRepository, IAuditRepository auditRepository) : base(uowProvider, logger, eventMessagesFactory) { _relationRepository = relationRepository; _relationTypeRepository = relationTypeRepository; + _auditRepository = auditRepository; _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); } @@ -476,6 +478,7 @@ namespace Umbraco.Core.Services.Implement } _relationTypeRepository.Save(relationType); + Audit(AuditType.Save, Constants.Security.SuperUserId, relationType.Id, $"Saved relation type: {relationType.Name}"); scope.Complete(); saveEventArgs.CanCancel = false; scope.Events.Dispatch(SavedRelationType, this, saveEventArgs); @@ -565,6 +568,11 @@ namespace Umbraco.Core.Services.Implement } return relations; } + + private void Audit(AuditType type, int userId, int objectId, string message = null) + { + _auditRepository.Save(new AuditItem(objectId, type, userId, ObjectTypes.GetName(UmbracoObjectTypes.RelationType), message)); + } #endregion #region Events Handlers diff --git a/src/Umbraco.Infrastructure/WebAssets/JsInitialize.js b/src/Umbraco.Infrastructure/WebAssets/JsInitialize.js index 2ca6f66510..ea9e4620c8 100644 --- a/src/Umbraco.Infrastructure/WebAssets/JsInitialize.js +++ b/src/Umbraco.Infrastructure/WebAssets/JsInitialize.js @@ -28,6 +28,7 @@ 'lib/chart.js/Chart.min.js', 'lib/angular-chart.js/angular-chart.min.js', + 'lib/wicg-inert/dist/inert.min.js', 'lib/umbraco/Extensions.js', diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts index e28c75e922..ba903d1c63 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts @@ -10,6 +10,7 @@ context('Document Types', () => { const name = "Test document type"; cy.umbracoEnsureDocumentTypeNameNotExists(name); + cy.umbracoEnsureTemplateNameNotExists(name); cy.umbracoSection('settings'); cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); @@ -44,6 +45,7 @@ context('Document Types', () => { //Assert cy.umbracoSuccessNotification().should('be.visible'); + cy.umbracoEnsureTemplateNameNotExists(name); //Clean up cy.umbracoEnsureDocumentTypeNameNotExists(name); diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts index f4c976de08..563ff77658 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts @@ -1,23 +1,34 @@ /// +import { PartialViewMacroBuilder } from "umbraco-cypress-testhelpers"; + context('Partial View Macro Files', () => { beforeEach(() => { cy.umbracoLogin(Cypress.env('username'), Cypress.env('password')); }); - it('Create new partial view macro', () => { - const name = "TestPartialViewMacro"; - const fileName = name + ".cshtml"; - - cy.umbracoEnsurePartialViewMacroFileNameNotExists(fileName); - cy.umbracoEnsureMacroNameNotExists(name); - + function openPartialViewMacroCreatePanel() { cy.umbracoSection('settings'); cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); cy.umbracoTreeItem("settings", ["Partial View Macro Files"]).rightclick(); - cy.umbracoContextMenuAction("action-create").click(); + } + + function cleanup(name, extension = ".cshtml") { + const fileName = name + extension; + + cy.umbracoEnsureMacroNameNotExists(name); + cy.umbracoEnsurePartialViewMacroFileNameNotExists(fileName); + } + + it('Create new partial view macro', () => { + const name = "TestPartialViewMacro"; + + cleanup(name); + + openPartialViewMacroCreatePanel(); + cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-label").click(); //Type name @@ -28,10 +39,117 @@ context('Partial View Macro Files', () => { //Assert cy.umbracoSuccessNotification().should('be.visible'); + cy.umbracoMacroExists(name).then(exists => { expect(exists).to.be.true; }); //Clean up - cy.umbracoEnsurePartialViewMacroFileNameNotExists(fileName); - cy.umbracoEnsureMacroNameNotExists(name); - }); + cleanup(name); + }); + + it('Create new partial view macro without macro', () => { + const name = "TestPartialMacrolessMacro"; + + cleanup(name); + + openPartialViewMacroCreatePanel(); + + cy.get('.menu-label').eq(1).click(); + + // Type name + cy.umbracoEditorHeaderName(name); + + // Save + cy.get('.btn-success').click(); + + // Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.umbracoMacroExists(name).then(exists => { expect(exists).to.be.false; }); + + // Clean + cleanup(name); + }); + + it('Create new partial view macro from snippet', () => { + const name = "TestPartialFromSnippet"; + + cleanup(name); + + openPartialViewMacroCreatePanel(); + + cy.get('.menu-label').eq(2).click(); + + // Select snippet + cy.get('.menu-label').eq(1).click(); + + // Type name + cy.umbracoEditorHeaderName(name); + + // Save + cy.get('.btn-success').click(); + + // Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.umbracoMacroExists(name).then(exists => { expect(exists).to.be.true; }); + + // Clean + cleanup(name); + }); + + it('Delete partial view macro', () => { + const name = "TestDeletePartialViewMacro"; + const fullName = name + ".cshtml" + + cleanup(name); + + const partialViewMacro = new PartialViewMacroBuilder() + .withName(name) + .withContent("@inherits Umbraco.Web.Macros.PartialViewMacroPage") + .build(); + + cy.savePartialViewMacro(partialViewMacro); + + // Navigate to settings + cy.umbracoSection('settings'); + cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); + + // Delete partialViewMacro + cy.umbracoTreeItem("settings", ["Partial View Macro Files", fullName]).rightclick(); + cy.umbracoContextMenuAction("action-delete").click(); + cy.umbracoButtonByLabelKey("general_ok").click(); + + // Assert + cy.contains(fullName).should('not.exist'); + + // Clean + cleanup(name); + }); + + it('Edit partial view macro', () => { + const name = "TestPartialViewMacroEditable"; + const fullName = name + ".cshtml"; + + cleanup(name); + + const partialViewMacro = new PartialViewMacroBuilder() + .withName(name) + .withContent("@inherits Umbraco.Web.Macros.PartialViewMacroPage") + .build(); + + cy.savePartialViewMacro(partialViewMacro); + + // Navigate to settings + cy.umbracoSection('settings'); + cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); + cy.umbracoTreeItem("settings", ["Partial View Macro Files", fullName]).click(); + + // Type an edit + cy.get('.ace_text-input').type(" // test", {force:true} ); + // Save + cy.get('.btn-success').click(); + + // Assert + cy.umbracoSuccessNotification().should('be.visible'); + + cleanup(name); + }); }); diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts index b644c6642b..068338f8fa 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts @@ -1,35 +1,145 @@ /// +import { PartialViewBuilder } from "umbraco-cypress-testhelpers"; + context('Partial Views', () => { - beforeEach(() => { - cy.umbracoLogin(Cypress.env('username'), Cypress.env('password')); - }); + beforeEach(() => { + cy.umbracoLogin(Cypress.env('username'), Cypress.env('password')); + }); - it('Create new empty partial view', () => { - const name = "TestPartialView"; - const fileName = name + ".cshtml"; + function navigateToSettings() { + cy.umbracoSection('settings'); + cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); + } - cy.umbracoEnsurePartialViewNameNotExists(fileName); + function openPartialViewsCreatePanel() { + navigateToSettings(); + cy.umbracoTreeItem("settings", ["Partial Views"]).rightclick(); + } - cy.umbracoSection('settings'); - cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); + it('Create new empty partial view', () => { + const name = "TestPartialView"; + const fileName = name + ".cshtml"; - cy.umbracoTreeItem("settings", ["Partial Views"]).rightclick(); + cy.umbracoEnsurePartialViewNameNotExists(fileName); - cy.umbracoContextMenuAction("action-create").click(); - cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-mediaType").click(); + openPartialViewsCreatePanel(); - //Type name - cy.umbracoEditorHeaderName(name); + cy.umbracoContextMenuAction("action-create").click(); + cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-mediaType").click(); - //Save - cy.get('.btn-success').click(); + //Type name + cy.umbracoEditorHeaderName(name); - //Assert - cy.umbracoSuccessNotification().should('be.visible'); + //Save + cy.get('.btn-success').click(); + + //Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.umbracoPartialViewExists(fileName).then(exists => { expect(exists).to.be.true; }); + + //Clean up + cy.umbracoEnsurePartialViewNameNotExists(fileName); + }); + + it('Create partial view from snippet', () => { + const name = "TestPartialViewFromSnippet"; + const fileName = name + ".cshtml"; + + cy.umbracoEnsurePartialViewNameNotExists(fileName); + + openPartialViewsCreatePanel(); + + cy.umbracoContextMenuAction("action-create").click(); + cy.get('.menu-label').eq(1).click(); + // Select snippet + cy.get('.menu-label').eq(2).click(); + + // Type name + cy.umbracoEditorHeaderName(name); + + // Save + cy.get('.btn-success').click(); + + // Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.umbracoPartialViewExists(fileName).then(exists => { expect(exists).to.be.true; }); + + // Clean up + cy.umbracoEnsurePartialViewNameNotExists(fileName); + }); + + it('Partial view with no name', () => { + openPartialViewsCreatePanel(); + + cy.umbracoContextMenuAction("action-create").click(); + cy.get('.menu-label').first().click(); + + // The test would fail intermittently, most likely because the editor didn't have time to load + // This should ensure that the editor is loaded and the test should no longer fail unexpectedly. + cy.get('.ace_content', {timeout: 5000}).should('exist'); + + // Click save + cy.get('.btn-success').click(); + + // Asserts + cy.umbracoErrorNotification().should('be.visible'); + }); + + it('Delete partial view', () => { + const name = "TestDeletePartialView"; + const fileName = name + ".cshtml"; + + cy.umbracoEnsurePartialViewNameNotExists(fileName); + + // Build and save partial view + const partialView = new PartialViewBuilder() + .withName(name) + .withContent("@inherits Umbraco.Web.Mvc.UmbracoViewPage") + .build(); + + cy.savePartialView(partialView); + + navigateToSettings(); + + // Delete partial view + cy.umbracoTreeItem("settings", ["Partial Views", fileName]).rightclick(); + cy.umbracoContextMenuAction("action-delete").click(); + cy.umbracoButtonByLabelKey("general_ok").click(); + + // Assert + cy.contains(fileName).should('not.exist'); + cy.umbracoPartialViewExists(fileName).then(exists => { expect(exists).to.be.false; }); + + // Clean + cy.umbracoEnsurePartialViewNameNotExists(fileName); + }); + + it('Edit partial view', () => { + const name = 'EditPartialView'; + const fileName = name + ".cshtml"; + + cy.umbracoEnsurePartialViewNameNotExists(fileName); + + const partialView = new PartialViewBuilder() + .withName(name) + .withContent("@inherits Umbraco.Web.Mvc.UmbracoViewPage\n") + .build(); + + cy.savePartialView(partialView); + + navigateToSettings(); + // Open partial view + cy.umbracoTreeItem("settings", ["Partial Views", fileName]).click(); + // Edit + cy.get('.ace_text-input').type("var num = 5;", {force:true} ); + cy.get('.btn-success').click(); + + // Assert + cy.umbracoSuccessNotification().should('be.visible'); + // Clean + cy.umbracoEnsurePartialViewNameNotExists(fileName); + }); - //Clean up - cy.umbracoEnsurePartialViewNameNotExists(fileName); - }); }); diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/scripts.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/scripts.ts index 8cffd3e59b..cce8a45da6 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/scripts.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/scripts.ts @@ -14,7 +14,7 @@ context('Scripts', () => { cy.umbracoSection('settings'); cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); - cy.umbracoTreeItem("settings", ["Stylesheets"]).rightclick(); + cy.umbracoTreeItem("settings", ["Scripts"]).rightclick(); cy.umbracoContextMenuAction("action-create").click(); cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-mediaType").click(); diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts index 6871db7ffe..aff1c38093 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts @@ -1,57 +1,168 @@ /// -import {DocumentTypeBuilder, TemplateBuilder} from "umbraco-cypress-testhelpers"; +import { TemplateBuilder } from 'umbraco-cypress-testhelpers'; context('Templates', () => { - beforeEach(() => { - cy.umbracoLogin(Cypress.env('username'), Cypress.env('password')); - }); - - it('Create template', () => { - const name = "Test template"; - - cy.umbracoEnsureTemplateNameNotExists(name); + beforeEach(() => { + cy.umbracoLogin(Cypress.env('username'), Cypress.env('password')); + }); + function navigateToSettings() { cy.umbracoSection('settings'); cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); + } + function createTemplate() { + navigateToSettings(); cy.umbracoTreeItem("settings", ["Templates"]).rightclick(); - cy.umbracoContextMenuAction("action-create").click(); + } + + + it('Create template', () => { + const name = "Test template test"; + cy.umbracoEnsureTemplateNameNotExists(name); + + createTemplate(); //Type name cy.umbracoEditorHeaderName(name); + /* Make an edit, if you don't the file will be create twice, + only happens in testing though, probably because the test is too fast + Certifiably mega wonk regardless */ + cy.get('.ace_text-input').type("var num = 5;", {force:true} ); //Save - cy.get("form[name='contentForm']").submit(); + cy.get('.btn-success').click(); //Assert cy.umbracoSuccessNotification().should('be.visible'); //Clean up cy.umbracoEnsureTemplateNameNotExists(name); - }); + }); - it('Delete template', () => { - const name = "Test template"; + it('Unsaved changes stay', () => { + const name = "Templates Unsaved Changes Stay test"; + const edit = "var num = 5;"; cy.umbracoEnsureTemplateNameNotExists(name); const template = new TemplateBuilder() .withName(name) + .withContent('@inherits Umbraco.Web.Mvc.UmbracoViewPage\n') .build(); cy.saveTemplate(template); - cy.umbracoSection('settings'); - cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); + navigateToSettings(); - cy.umbracoTreeItem("settings", ["Templates", name]).rightclick(); - cy.umbracoContextMenuAction("action-delete").click(); + // Open partial view + cy.umbracoTreeItem("settings", ["Templates", name]).click(); + // Edit + cy.get('.ace_text-input').type(edit, {force:true} ); - cy.umbracoButtonByLabelKey("general_ok").click(); + // Navigate away + cy.umbracoSection('content'); + // Click stay button + cy.get('umb-button[label="Stay"] button:enabled').click(); - cy.contains(name).should('not.exist'); + // Assert + // That the same document is open + cy.get('#headerName').should('have.value', name); + cy.get('.ace_content').contains(edit); cy.umbracoEnsureTemplateNameNotExists(name); }); + + it('Discard unsaved changes', () => { + const name = "Discard changes test"; + const edit = "var num = 5;"; + + cy.umbracoEnsureTemplateNameNotExists(name); + + const template = new TemplateBuilder() + .withName(name) + .withContent('@inherits Umbraco.Web.Mvc.UmbracoViewPage\n') + .build(); + + cy.saveTemplate(template); + + navigateToSettings(); + + // Open partial view + cy.umbracoTreeItem("settings", ["Templates", name]).click(); + // Edit + cy.get('.ace_text-input').type(edit, {force:true} ); + + // Navigate away + cy.umbracoSection('content'); + // Click discard + cy.get('umb-button[label="Discard changes"] button:enabled').click(); + // Navigate back + cy.umbracoSection('settings'); + + // Asserts + cy.get('.ace_content').should('not.contain', edit); + // cy.umbracoPartialViewExists(fileName).then(exists => { expect(exists).to.be.false; }); TODO: Switch to template + cy.umbracoEnsureTemplateNameNotExists(name); + }); + + it('Insert macro', () => { + const name = 'InsertMacroTest'; + + cy.umbracoEnsureTemplateNameNotExists(name); + cy.umbracoEnsureMacroNameNotExists(name); + + const template = new TemplateBuilder() + .withName(name) + .withContent('') + .build(); + + cy.saveTemplate(template); + + cy.saveMacro(name); + + navigateToSettings(); + cy.umbracoTreeItem("settings", ["Templates", name]).click(); + // Insert macro + cy.umbracoButtonByLabelKey('general_insert').click(); + cy.get('.umb-insert-code-box__title').contains('Macro').click(); + cy.get('.umb-card-grid-item').contains(name).click(); + + // Assert + cy.get('.ace_content').contains('@Umbraco.RenderMacro("' + name + '")').should('exist'); + + // Clean + cy.umbracoEnsureTemplateNameNotExists(name); + cy.umbracoEnsureMacroNameNotExists(name); + }); + + it('Insert value', () => { + const name = 'Insert Value Test'; + + cy.umbracoEnsureTemplateNameNotExists(name); + + const partialView = new TemplateBuilder() + .withName(name) + .withContent('') + .build(); + + cy.saveTemplate(partialView); + + navigateToSettings(); + cy.umbracoTreeItem("settings", ["Templates", name]).click(); + + // Insert value + cy.umbracoButtonByLabelKey('general_insert').click(); + cy.get('.umb-insert-code-box__title').contains('Value').click(); + cy.get('select').select('umbracoBytes'); + cy.umbracoButtonByLabelKey('general_submit').click(); + + // assert + cy.get('.ace_content').contains('@Model.Value("umbracoBytes")').should('exist'); + + // Clean + cy.umbracoEnsureTemplateNameNotExists(name); + }); + }); diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts new file mode 100644 index 0000000000..ed891a2eea --- /dev/null +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts @@ -0,0 +1,49 @@ +/// +context('Backoffice Tour', () => { + + beforeEach(() => { + cy.umbracoLogin(Cypress.env('username'), Cypress.env('password')); + }); + + it('Backoffice introduction tour should run', () => { + //arrange + cy.umbracoGlobalHelp().should("be.visible"); + + //act + cy.umbracoGlobalHelp().click() + //assert + cy.get('[data-element="help-tours"]').should("be.visible"); + //act + cy.get('[data-element="help-tours"]').click(); + //assert + cy.get('[data-element="tour-umbIntroIntroduction"] .umb-button').should("be.visible"); + //act + cy.get('[data-element="tour-umbIntroIntroduction"] .umb-button').click(); + //assert + cy.get('.umb-tour-step', { timeout: 60000 }).should('be.visible'); + cy.get('.umb-tour-step__footer').should('be.visible'); + cy.get('.umb-tour-step__counter').should('be.visible'); + + for(let i=1;i<7;i++){ + cy.get('.umb-tour-step__counter').contains(i + '/12'); + cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); + } + cy.umbracoGlobalUser().click() + cy.get('.umb-tour-step__counter').contains('8/12'); + cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); + cy.get('.umb-tour-step__counter').contains('9/12'); + cy.get('.umb-overlay-drawer__align-right .umb-button').should('be.visible').click(); + cy.get('.umb-tour-step__counter').contains('10/12'); + cy.umbracoGlobalHelp().click() + + for(let i=11;i<13;i++){ + cy.get('.umb-tour-step__counter').contains(i + '/12'); + cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); + } + cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); + + //assert + cy.umbracoGlobalHelp().should("be.visible"); + cy.get('[data-element="help-tours"] .umb-progress-circle').contains('17%'); + }); +}); diff --git a/src/Umbraco.Tests.AcceptanceTest/package.json b/src/Umbraco.Tests.AcceptanceTest/package.json index 3b4177ce3f..867b7f5cf3 100644 --- a/src/Umbraco.Tests.AcceptanceTest/package.json +++ b/src/Umbraco.Tests.AcceptanceTest/package.json @@ -5,9 +5,9 @@ }, "devDependencies": { "cross-env": "^7.0.2", + "cypress": "^4.12.1", "ncp": "^2.0.0", - "cypress": "^4.9.0", - "umbraco-cypress-testhelpers": "1.0.0-beta-44" + "umbraco-cypress-testhelpers": "^1.0.0-beta-48" }, "dependencies": { "typescript": "^3.9.2" diff --git a/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs b/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs index 4a88d4a571..b1fe45f1f7 100644 --- a/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs @@ -220,8 +220,12 @@ namespace Umbraco.Tests.Common.Builders private class TestGlobalSettings : IGlobalSettings { + private string _iconsPath; public string ReservedUrls { get; set; } public string ReservedPaths { get; set; } + + public string IconsPath{ get; set; } + public string Path { get; set; } public string ConfigurationStatus { get; set; } public int TimeOutInMinutes { get; set; } diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs index dbd71870d4..3c1b0bcc31 100644 --- a/src/Umbraco.Tests/Services/UserServiceTests.cs +++ b/src/Umbraco.Tests/Services/UserServiceTests.cs @@ -7,6 +7,7 @@ using System.Threading; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Exceptions; +using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Tests.TestHelpers.Entities; @@ -968,16 +969,72 @@ namespace Umbraco.Tests.Services Assert.That(updatedItem.AllowedSections.Count(), Is.EqualTo(originalUser.AllowedSections.Count())); } + [Test] + public void Can_Get_Assigned_StartNodes_For_User() + { + var startContentItems = BuildContentItems(3); + + var testUserGroup = CreateTestUserGroup(); + + var userGroupId = testUserGroup.Id; + + CreateTestUsers(startContentItems.Select(x => x.Id).ToArray(), testUserGroup, 3); + + var usersInGroup = ServiceContext.UserService.GetAllInGroup(userGroupId); + + foreach (var user in usersInGroup) + Assert.AreEqual(user.StartContentIds.Length, startContentItems.Length); + } + + private Content[] BuildContentItems(int numberToCreate) + { + var contentType = MockedContentTypes.CreateSimpleContentType(); + + ServiceContext.ContentTypeService.Save(contentType); + + var startContentItems = new List(); + + for (var i = 0; i < numberToCreate; i++) + startContentItems.Add(MockedContent.CreateSimpleContent(contentType)); + + ServiceContext.ContentService.Save(startContentItems); + + return startContentItems.ToArray(); + } + private IUser CreateTestUser(out IUserGroup userGroup) { userGroup = CreateTestUserGroup(); var user = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com"); + user.AddGroup(userGroup.ToReadOnlyGroup()); + ServiceContext.UserService.Save(user); + return user; } + private List CreateTestUsers(int[] startContentIds, IUserGroup userGroup, int numberToCreate) + { + var users = new List(); + + for (var i = 0; i < numberToCreate; i++) + { + var user = ServiceContext.UserService.CreateUserWithIdentity($"test{i}", $"test{i}@test.com"); + user.AddGroup(userGroup.ToReadOnlyGroup()); + + var updateable = (User)user; + updateable.StartContentIds = startContentIds; + + ServiceContext.UserService.Save(user); + + users.Add(user); + } + + return users; + } + private UserGroup CreateTestUserGroup(string alias = "testGroup", string name = "Test Group") { var userGroup = new UserGroup(ShortStringHelper) diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 44f6be8e7d..7356018c58 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -190,7 +190,7 @@ namespace Umbraco.Tests.TestHelpers Mock.Of(x => x.ApplicationPhysicalPath == ioHelper.MapPath("~"))), ioHelper); }); - var relationService = GetLazyService(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c))); + var relationService = GetLazyService(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c), GetRepo(c))); var tagService = GetLazyService(factory, c => new TagService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var redirectUrlService = GetLazyService(factory, c => new RedirectUrlService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var consentService = GetLazyService(factory, c => new ConsentService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs index f3d11dea78..34494e1492 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs @@ -180,6 +180,10 @@ namespace Umbraco.Web.BackOffice.Controllers "mediaApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( controller => controller.GetRootMedia()) }, + { + "iconApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( + controller => controller.GetIcon("")) + }, { "imagesApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( controller => controller.GetBigThumbnail("")) diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs index 444667b591..146f2c32b7 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; using System.Net.Mime; using System.Text; using System.Threading.Tasks; @@ -13,30 +11,25 @@ using System.Xml.Linq; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Umbraco.Core; -using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Dictionary; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Models.Editors; using Umbraco.Core.Packaging; -using Umbraco.Core.Persistence; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Web.Models; using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; using Umbraco.Core.Mapping; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.Attributes; using Umbraco.Web.Common.Exceptions; using Umbraco.Web.Editors; -using Umbraco.Web.Routing; using Umbraco.Web.Security; using ContentType = Umbraco.Core.Models.ContentType; @@ -140,6 +133,12 @@ namespace Umbraco.Web.BackOffice.Controllers return _contentTypeService.HasContentNodes(id); } + /// + /// Gets the document type a given id + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] public DocumentTypeDisplay GetById(int id) { var ct = _contentTypeService.Get(id); @@ -152,6 +151,46 @@ namespace Umbraco.Web.BackOffice.Controllers return dto; } + /// + /// Gets the document type a given guid + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + public DocumentTypeDisplay GetById(Guid id) + { + var contentType = _contentTypeService.Get(id); + if (contentType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + var dto = _umbracoMapper.Map(contentType); + return dto; + } + + /// + /// Gets the document type a given udi + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + public DocumentTypeDisplay GetById(Udi id) + { + var guidUdi = id as GuidUdi; + if (guidUdi == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + var contentType = _contentTypeService.Get(guidUdi.Guid); + if (contentType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + var dto = _umbracoMapper.Map(contentType); + return dto; + } + /// /// Deletes a document type with a given ID /// diff --git a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs index 7d362e52b6..26cccb9141 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; -using System.Net; using System.Linq; using System.Net.Http; using Microsoft.AspNetCore.Mvc; +using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; @@ -129,7 +129,7 @@ namespace Umbraco.Web.BackOffice.Controllers } } - /// + /// /// Gets a dictionary item by id /// /// @@ -141,10 +141,58 @@ namespace Umbraco.Web.BackOffice.Controllers /// /// Returns a not found response when dictionary item does not exist /// + [DetermineAmbiguousActionByPassingParameters] public ActionResult GetById(int id) { var dictionary = _localizationService.GetDictionaryItemById(id); + if (dictionary == null) + return NotFound(); + return _umbracoMapper.Map(dictionary); + } + + /// + /// Gets a dictionary item by guid + /// + /// + /// The id. + /// + /// + /// The . + /// + /// + /// Returns a not found response when dictionary item does not exist + /// + [DetermineAmbiguousActionByPassingParameters] + public ActionResult GetById(Guid id) + { + var dictionary = _localizationService.GetDictionaryItemById(id); + if (dictionary == null) + return NotFound(); + + return _umbracoMapper.Map(dictionary); + } + + /// + /// Gets a dictionary item by udi + /// + /// + /// The id. + /// + /// + /// The . + /// + /// + /// Returns a not found response when dictionary item does not exist + /// + [DetermineAmbiguousActionByPassingParameters] + public ActionResult GetById(Udi id) + { + var guidUdi = id as GuidUdi; + if (guidUdi == null) + return NotFound(); + + var dictionary = _localizationService.GetDictionaryItemById(guidUdi.Guid); if (dictionary == null) return NotFound(); @@ -222,19 +270,30 @@ namespace Umbraco.Web.BackOffice.Controllers /// public IEnumerable GetList() { - var list = new List(); + var items = _localizationService.GetDictionaryItemDescendants(null).ToArray(); + var list = new List(items.Length); - const int level = 0; - - foreach (var dictionaryItem in _localizationService.GetRootDictionaryItems().OrderBy(ItemSort())) + // recursive method to build a tree structure from the flat structure returned above + void BuildTree(int level = 0, Guid? parentId = null) { - var item = _umbracoMapper.Map(dictionaryItem); - item.Level = 0; - list.Add(item); + var children = items.Where(t => t.ParentId == parentId).ToArray(); + if(children.Any() == false) + { + return; + } - GetChildItemsForList(dictionaryItem, level + 1, list); + foreach(var child in children.OrderBy(ItemSort())) + { + var display = _umbracoMapper.Map(child); + display.Level = level; + list.Add(display); + + BuildTree(level + 1, child.Key); + } } + BuildTree(); + return list; } diff --git a/src/Umbraco.Web.BackOffice/Controllers/IconController.cs b/src/Umbraco.Web.BackOffice/Controllers/IconController.cs new file mode 100644 index 0000000000..2aa2761134 --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Controllers/IconController.cs @@ -0,0 +1,108 @@ +using System.Collections.Generic; +using System.Linq; +using Umbraco.Web.Models; +using System.IO; +using Umbraco.Core; +using Ganss.XSS; +using Umbraco.Core.Configuration; +using Umbraco.Core.Hosting; +using Umbraco.Web.BackOffice.Controllers; +using Umbraco.Web.Common.Attributes; + +namespace Umbraco.Web.Editors +{ + [PluginController("UmbracoApi")] + public class IconController : UmbracoAuthorizedApiController + { + private readonly IHostingEnvironment _hostingEnvironment; + private readonly IGlobalSettings _globalSettings; + + public IconController( + IHostingEnvironment hostingEnvironment, + IGlobalSettings globalSettings) + { + _hostingEnvironment = hostingEnvironment; + _globalSettings = globalSettings; + } + + /// + /// Gets an IconModel containing the icon name and SvgString according to an icon name found at the global icons path + /// + /// + /// + public IconModel GetIcon(string iconName) + { + return string.IsNullOrWhiteSpace(iconName) + ? null + : CreateIconModel(iconName.StripFileExtension(), + _hostingEnvironment.MapPathWebRoot($"{_globalSettings.IconsPath}/{iconName}.svg")); + } + + /// + /// Gets an IconModel using values from a FileInfo model + /// + /// + /// + public IconModel GetIcon(FileInfo fileInfo) + { + return fileInfo == null || string.IsNullOrWhiteSpace(fileInfo.Name) + ? null + : CreateIconModel(fileInfo.Name.StripFileExtension(), fileInfo.FullName); + } + + /// + /// Gets a list of all svg icons found at at the global icons path. + /// + /// + public List GetAllIcons() + { + var icons = new List(); + var directory = new DirectoryInfo(_hostingEnvironment.MapPathWebRoot($"{_globalSettings.IconsPath}/")); + var iconNames = directory.GetFiles("*.svg"); + + iconNames.OrderBy(f => f.Name).ToList().ForEach(iconInfo => + { + var icon = GetIcon(iconInfo); + + if (icon != null) + { + icons.Add(icon); + } + }); + + return icons; + } + + /// + /// Gets an IconModel containing the icon name and SvgString + /// + /// + /// + /// + private IconModel CreateIconModel(string iconName, string iconPath) + { + var sanitizer = new HtmlSanitizer(); + sanitizer.AllowedAttributes.UnionWith(Core.Constants.SvgSanitizer.Attributes); + sanitizer.AllowedCssProperties.UnionWith(Core.Constants.SvgSanitizer.Attributes); + sanitizer.AllowedTags.UnionWith(Core.Constants.SvgSanitizer.Tags); + + try + { + var svgContent = System.IO.File.ReadAllText(iconPath); + var sanitizedString = sanitizer.Sanitize(svgContent); + + var svg = new IconModel + { + Name = iconName, + SvgString = sanitizedString + }; + + return svg; + } + catch + { + return null; + } + } + } +} diff --git a/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs b/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs index 6ce6d3a1c6..b264fd987b 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs @@ -21,7 +21,8 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IContentSettings _contentSettings; private readonly IImageUrlGenerator _imageUrlGenerator; - public ImagesController(IMediaFileSystem mediaFileSystem, IContentSettings contentSettings, IImageUrlGenerator imageUrlGenerator) + public ImagesController(IMediaFileSystem mediaFileSystem, IContentSettings contentSettings, + IImageUrlGenerator imageUrlGenerator) { _mediaFileSystem = mediaFileSystem; _contentSettings = contentSettings; @@ -65,7 +66,6 @@ namespace Umbraco.Web.BackOffice.Controllers try { imageLastModified = _mediaFileSystem.GetLastModified(imagePath); - } catch (Exception) { @@ -76,7 +76,14 @@ namespace Umbraco.Web.BackOffice.Controllers } var rnd = imageLastModified.HasValue ? $"&rnd={imageLastModified:yyyyMMddHHmmss}" : null; - var imageUrl = _imageUrlGenerator.GetImageUrl(new ImageUrlGenerationOptions(imagePath) { UpScale = false, Width = width, AnimationProcessMode = "first", ImageCropMode = ImageCropMode.Max, CacheBusterValue = rnd }); + var imageUrl = _imageUrlGenerator.GetImageUrl(new ImageUrlGenerationOptions(imagePath) + { + UpScale = false, + Width = width, + AnimationProcessMode = "first", + ImageCropMode = ImageCropMode.Max, + CacheBusterValue = rnd + }); return new RedirectResult(imageUrl, false); } @@ -92,20 +99,30 @@ namespace Umbraco.Web.BackOffice.Controllers /// /// /// + /// + /// + /// /// /// /// If there is no media, image property or image file is found then this will return not found. /// public string GetProcessedImageUrl(string imagePath, - int? width = null, - int? height = null, - int? focalPointLeft = null, - int? focalPointTop = null, - string animationProcessMode = "first", + int? width = null, + int? height = null, + decimal? focalPointLeft = null, + decimal? focalPointTop = null, + string animationProcessMode = "first", ImageCropMode mode = ImageCropMode.Max, - bool upscale = false, - string cacheBusterValue = "") -{ + bool upscale = false, + string cacheBusterValue = "", + decimal? cropX1 = null, + decimal? cropX2 = null, + decimal? cropY1 = null, + decimal? cropY2 = null + ) + { + + var options = new ImageUrlGenerationOptions(imagePath) { AnimationProcessMode = animationProcessMode, @@ -114,13 +131,35 @@ namespace Umbraco.Web.BackOffice.Controllers ImageCropMode = mode, UpScale = upscale, Width = width, + Crop = (cropX1.HasValue && cropX2.HasValue && cropY1.HasValue && cropY2.HasValue) ? new ImageUrlGenerationOptions.CropCoordinates(cropX1.Value, cropY1.Value, cropX2.Value, cropY2.Value) : null, + FocalPoint = new ImageUrlGenerationOptions.FocalPointPosition(focalPointTop.GetValueOrDefault(0.5m), focalPointLeft.GetValueOrDefault(0.5m)), }; if (focalPointLeft.HasValue && focalPointTop.HasValue) { - options.FocalPoint = new ImageUrlGenerationOptions.FocalPointPosition(focalPointTop.Value, focalPointLeft.Value); + options.FocalPoint = + new ImageUrlGenerationOptions.FocalPointPosition(focalPointTop.Value, focalPointLeft.Value); } return _imageUrlGenerator.GetImageUrl(options); } + + public class FocalPointPositionModel + { + public decimal Left { get; set; } + public decimal Top { get; set; } + } + + /// + /// The bounds of the crop within the original image, in whatever units the registered + /// IImageUrlGenerator uses, typically a percentage between 0 and 100. + /// + public class CropCoordinatesModel + { + + public decimal X1 { get; set; } + public decimal Y1 { get; set; } + public decimal X2 { get; set;} + public decimal Y2 { get; set;} + } } } diff --git a/src/Umbraco.Web.BackOffice/Controllers/LogController.cs b/src/Umbraco.Web.BackOffice/Controllers/LogController.cs index 297c39a450..e99ea890d7 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/LogController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/LogController.cs @@ -98,6 +98,13 @@ namespace Umbraco.Web.BackOffice.Controllers }; } + public IEnumerable GetLog(AuditType logType, DateTime? sinceDate = null) + { + var result = _auditService.GetLogs(Enum.Parse(logType.ToString()), sinceDate); + var mapped = _umbracoMapper.MapEnumerable(result); + return mapped; + } + private IEnumerable MapAvatarsAndNames(IEnumerable items) { var mappedItems = items.ToList(); diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs index 6bb68248b1..ba19f7c2b4 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs @@ -160,15 +160,15 @@ namespace Umbraco.Web.BackOffice.Controllers [DetermineAmbiguousActionByPassingParameters] public MediaItemDisplay GetById(int id) { - var foundContent = GetObjectFromRequest(() => _mediaService.GetById(id)); + var foundMedia = GetObjectFromRequest(() => _mediaService.GetById(id)); - if (foundContent == null) + if (foundMedia == null) { HandleContentNotFound(id); //HandleContentNotFound will throw an exception return null; } - return _umbracoMapper.Map(foundContent); + return _umbracoMapper.Map(foundMedia); } /// @@ -181,15 +181,15 @@ namespace Umbraco.Web.BackOffice.Controllers [DetermineAmbiguousActionByPassingParameters] public MediaItemDisplay GetById(Guid id) { - var foundContent = GetObjectFromRequest(() => _mediaService.GetById(id)); + var foundMedia = GetObjectFromRequest(() => _mediaService.GetById(id)); - if (foundContent == null) + if (foundMedia == null) { HandleContentNotFound(id); //HandleContentNotFound will throw an exception return null; } - return _umbracoMapper.Map(foundContent); + return _umbracoMapper.Map(foundMedia); } /// @@ -800,10 +800,13 @@ namespace Umbraco.Web.BackOffice.Controllers var total = long.MaxValue; while (page * pageSize < total) { - var children = _mediaService.GetPagedChildren(mediaId, page, pageSize, out total, + var children = _mediaService.GetPagedChildren(mediaId, page++, pageSize, out total, _sqlContext.Query().Where(x => x.Name == nameToFind)); - foreach (var c in children) - return c; //return first one if any are found + var match = children.FirstOrDefault(c => c.ContentType.Alias == contentTypeAlias); + if (match != null) + { + return match; + } } return null; } diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs index d030d03cf9..617d3f1538 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs @@ -71,6 +71,12 @@ namespace Umbraco.Web.BackOffice.Controllers public int GetCount() => _contentTypeService.Count(); + /// + /// Gets the media type a given id + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)] public MediaTypeDisplay GetById(int id) { @@ -84,6 +90,48 @@ namespace Umbraco.Web.BackOffice.Controllers return dto; } + /// + /// Gets the media type a given guid + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)] + public MediaTypeDisplay GetById(Guid id) + { + var mediaType = _mediaTypeService.Get(id); + if (mediaType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + var dto = _umbracoMapper.Map(mediaType); + return dto; + } + + /// + /// Gets the media type a given udi + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)] + public MediaTypeDisplay GetById(Udi id) + { + var guidUdi = id as GuidUdi; + if (guidUdi == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + var mediaType = _mediaTypeService.Get(guidUdi.Guid); + if (mediaType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + var dto = _umbracoMapper.Map(mediaType); + return dto; + } + /// /// Deletes a media type with a given ID /// diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs index 153990937d..d3d06132d3 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Net; using Microsoft.AspNetCore.Mvc; +using Umbraco.Core; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Services; @@ -37,6 +38,12 @@ namespace Umbraco.Web.BackOffice.Controllers localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); } + /// + /// Gets the member group json for the member group id + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] public MemberGroupDisplay GetById(int id) { var memberGroup = _memberGroupService.GetById(id); @@ -49,6 +56,45 @@ namespace Umbraco.Web.BackOffice.Controllers return dto; } + + /// + /// Gets the member group json for the member group guid + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + public MemberGroupDisplay GetById(Guid id) + { + var memberGroup = _memberGroupService.GetById(id); + if (memberGroup == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + return _umbracoMapper.Map(memberGroup); + } + + /// + /// Gets the member group json for the member group udi + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + public MemberGroupDisplay GetById(Udi id) + { + var guidUdi = id as GuidUdi; + if (guidUdi == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + var memberGroup = _memberGroupService.GetById(guidUdi.Guid); + if (memberGroup == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + return _umbracoMapper.Map(memberGroup); + } + public IEnumerable GetByIds([FromQuery]int[] ids) { return _memberGroupService.GetByIds(ids) diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs index 240a2e0f5b..8ef8749c2d 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs @@ -64,7 +64,13 @@ namespace Umbraco.Web.Editors localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); } + /// + /// Gets the member type a given id + /// + /// + /// [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)] + [DetermineAmbiguousActionByPassingParameters] public MemberTypeDisplay GetById(int id) { var ct = _memberTypeService.Get(id); @@ -78,7 +84,49 @@ namespace Umbraco.Web.Editors } /// - /// Deletes a document type with a given ID + /// Gets the member type a given guid + /// + /// + /// + [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)] + [DetermineAmbiguousActionByPassingParameters] + public MemberTypeDisplay GetById(Guid id) + { + var memberType = _memberTypeService.Get(id); + if (memberType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + var dto = _umbracoMapper.Map(memberType); + return dto; + } + + /// + /// Gets the member type a given udi + /// + /// + /// + [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)] + [DetermineAmbiguousActionByPassingParameters] + public MemberTypeDisplay GetById(Udi id) + { + var guidUdi = id as GuidUdi; + if (guidUdi == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + var memberType = _memberTypeService.Get(guidUdi.Guid); + if (memberType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + var dto = _umbracoMapper.Map(memberType); + return dto; + } + + /// + /// Deletes a document type with a given id /// /// /// diff --git a/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs index ef7fe94e77..0991dca09f 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs @@ -49,6 +49,7 @@ namespace Umbraco.Web.BackOffice.Controllers /// /// The relation type ID. /// Returns the . + [DetermineAmbiguousActionByPassingParameters] public RelationTypeDisplay GetById(int id) { var relationType = _relationService.GetRelationTypeById(id); @@ -63,6 +64,42 @@ namespace Umbraco.Web.BackOffice.Controllers return display; } + /// + /// Gets a relation type by guid + /// + /// The relation type ID. + /// Returns the . + [DetermineAmbiguousActionByPassingParameters] + public RelationTypeDisplay GetById(Guid id) + { + var relationType = _relationService.GetRelationTypeById(id); + if (relationType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + return _umbracoMapper.Map(relationType); + } + + /// + /// Gets a relation type by udi + /// + /// The relation type ID. + /// Returns the . + [DetermineAmbiguousActionByPassingParameters] + public RelationTypeDisplay GetById(Udi id) + { + var guidUdi = id as GuidUdi; + if (guidUdi == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + var relationType = _relationService.GetRelationTypeById(guidUdi.Guid); + if (relationType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + return _umbracoMapper.Map(relationType); + } + public PagedResult GetPagedResults(int id, int pageNumber = 1, int pageSize = 100) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs b/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs index b99ebce7a7..f80c3015e9 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Net; using Microsoft.AspNetCore.Mvc; +using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Mapping; using Umbraco.Core.Models; @@ -55,10 +56,11 @@ namespace Umbraco.Web.BackOffice.Controllers } /// - /// Gets the content json for the content id + /// Gets the template json for the template id /// /// /// + [DetermineAmbiguousActionByPassingParameters] public TemplateDisplay GetById(int id) { var template = _fileService.GetTemplate(id); @@ -68,6 +70,43 @@ namespace Umbraco.Web.BackOffice.Controllers return _umbracoMapper.Map(template); } + + /// + /// Gets the template json for the template guid + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + public TemplateDisplay GetById(Guid id) + { + var template = _fileService.GetTemplate(id); + if (template == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + return _umbracoMapper.Map(template); + } + + /// + /// Gets the template json for the template udi + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + public TemplateDisplay GetById(Udi id) + { + var guidUdi = id as GuidUdi; + if (guidUdi == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + var template = _fileService.GetTemplate(guidUdi.Guid); + if (template == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + return _umbracoMapper.Map(template); + } + /// /// Deletes a template with a given ID /// diff --git a/src/Umbraco.Web.BackOffice/Controllers/TemplateQueryController.cs b/src/Umbraco.Web.BackOffice/Controllers/TemplateQueryController.cs index e0808682d5..b1dd2e94e5 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/TemplateQueryController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/TemplateQueryController.cs @@ -95,7 +95,11 @@ namespace Umbraco.Web.BackOffice.Controllers QueryExpression = queryExpression.ToString(), ResultCount = results.Count, ExecutionTime = timer.ElapsedMilliseconds, - SampleResults = results.Take(20).Select(x => new TemplateQueryResult { Icon = "icon-file", Name = x.Name }) + SampleResults = results.Take(20).Select(x => new TemplateQueryResult + { + Icon = "icon-document", + Name = x.Name + }) }; } diff --git a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs index fff609322c..75f7a6e512 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs @@ -34,6 +34,7 @@ using Umbraco.Core.Hosting; using Umbraco.Core.Media; using Umbraco.Extensions; using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.ModelBinders; using Umbraco.Web.BackOffice.Security; using Umbraco.Web.Common.ActionResults; using Umbraco.Web.Common.Attributes; @@ -235,6 +236,33 @@ namespace Umbraco.Web.BackOffice.Controllers return result; } + /// + /// Get users by integer ids + /// + /// + /// + [TypeFilter(typeof(OutgoingEditorModelEventAttribute))] + [AdminUsersAuthorize] + public IEnumerable GetByIds([FromJsonPath]int[] ids) + { + if (ids == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + if (ids.Length == 0) + return Enumerable.Empty(); + + var users = _userService.GetUsersById(ids); + if (users == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + var result = _umbracoMapper.MapEnumerable(users); + return result; + } + /// /// Returns a paged users collection /// diff --git a/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs b/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs index cf001b17db..aba2d4a12c 100644 --- a/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs +++ b/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs @@ -39,6 +39,7 @@ namespace Umbraco.Web.Models.Mapping private void Map(IMember source, MemberDisplay target, MapperContext context) { target.ContentApps = _commonMapper.GetContentApps(source); + target.ContentType = _commonMapper.GetContentType(source, context); target.ContentTypeId = source.ContentType.Id; target.ContentTypeAlias = source.ContentType.Alias; target.ContentTypeName = source.ContentType.Name; diff --git a/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj b/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj index 0e98bc8cd7..2547117531 100644 --- a/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj +++ b/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj @@ -15,6 +15,7 @@ + diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js b/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js index dbc0b7fc57..fb03cbd1b1 100644 --- a/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js @@ -29,12 +29,15 @@ function dependencies() { "./node_modules/ace-builds/src-min-noconflict/snippets/text.js", "./node_modules/ace-builds/src-min-noconflict/snippets/javascript.js", "./node_modules/ace-builds/src-min-noconflict/snippets/css.js", + "./node_modules/ace-builds/src-min-noconflict/snippets/json.js", "./node_modules/ace-builds/src-min-noconflict/theme-chrome.js", "./node_modules/ace-builds/src-min-noconflict/mode-razor.js", "./node_modules/ace-builds/src-min-noconflict/mode-javascript.js", "./node_modules/ace-builds/src-min-noconflict/mode-css.js", "./node_modules/ace-builds/src-min-noconflict/worker-javascript.js", - "./node_modules/ace-builds/src-min-noconflict/worker-css.js" + "./node_modules/ace-builds/src-min-noconflict/worker-css.js", + "./node_modules/ace-builds/src-min-noconflict/mode-json.js", + "./node_modules/ace-builds/src-min-noconflict/worker-json.js" ], "base": "./node_modules/ace-builds" }, @@ -45,7 +48,8 @@ function dependencies() { }, { "name": "angular-aria", - "src": ["./node_modules/angular-aria/angular-aria.min.js"], + "src": ["./node_modules/angular-aria/angular-aria.min.js", + "./node_modules/angular-aria/angular-aria.min.js.map"], "base": "./node_modules/angular-aria" }, { @@ -238,6 +242,14 @@ function dependencies() { "name": "underscore", "src": ["node_modules/underscore/underscore-min.js"], "base": "./node_modules/underscore" + }, + { + "name": "wicg-inert", + "src": [ + "./node_modules/wicg-inert/dist/inert.min.js", + "./node_modules/wicg-inert/dist/inert.min.js.map" + ], + "base": "./node_modules/wicg-inert" } ]; diff --git a/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pager.less b/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pager.less index 1476188297..718ade757e 100644 --- a/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pager.less +++ b/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pager.less @@ -13,6 +13,7 @@ display: inline; } .pager li > a, +.pager li > button, .pager li > span { display: inline-block; padding: 5px 14px; @@ -21,23 +22,30 @@ .border-radius(15px); } .pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #f5f5f5; +.pager li > a:focus, +.pager li > button:hover, +.pager li > button:focus { + text-decoration: none; + background-color: #f5f5f5; } .pager .next > a, +.pager .next > button, .pager .next > span { float: right; } .pager .previous > a, +.pager .previous > button, .pager .previous > span { - float: left; + float: left; } .pager .disabled > a, .pager .disabled > a:hover, .pager .disabled > a:focus, +.pager .disabled > button, +.pager .disabled > button:hover, +.pager .disabled > button:focus .pager .disabled > span { - color: @grayLight; - background-color: #fff; - cursor: default; -} \ No newline at end of file + color: @grayLight; + background-color: #fff; + cursor: default; +} diff --git a/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pagination.less b/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pagination.less index 6f6e6ac7de..ae10700eb3 100644 --- a/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pagination.less +++ b/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pagination.less @@ -21,6 +21,7 @@ display: inline; // Remove list-style and block-level defaults } .pagination ul > li > a, +.pagination ul > li > button, .pagination ul > li > span { float: left; // Collapse white-space padding: 4px 12px; @@ -32,29 +33,38 @@ } .pagination ul > li > a:hover, .pagination ul > li > a:focus, +.pagination ul > li > button:hover, +.pagination ul > li > button:focus, .pagination ul > .active > a, +.pagination ul > .active > button, .pagination ul > .active > span { - background-color: @paginationActiveBackground; + background-color: @paginationActiveBackground; } .pagination ul > .active > a, +.pagination ul > .active > button, .pagination ul > .active > span { - color: @grayLight; - cursor: default; + color: @grayLight; + cursor: default; } .pagination ul > .disabled > span, .pagination ul > .disabled > a, .pagination ul > .disabled > a:hover, -.pagination ul > .disabled > a:focus { - color: @grayLight; - background-color: transparent; - cursor: default; +.pagination ul > .disabled > a:focus, +.pagination ul > .disabled > button, +.pagination ul > .disabled > button:hover, +.pagination ul > .disabled > button:focus { + color: @grayLight; + background-color: transparent; + cursor: default; } .pagination ul > li:first-child > a, +.pagination ul > li:first-child > button, .pagination ul > li:first-child > span { border-left-width: 1px; .border-left-radius(@baseBorderRadius); } .pagination ul > li:last-child > a, +.pagination ul > li:last-child > button, .pagination ul > li:last-child > span { .border-right-radius(@baseBorderRadius); } @@ -77,15 +87,18 @@ // Large .pagination-large { ul > li > a, + ul > li > button, ul > li > span { padding: @paddingLarge; font-size: @fontSizeLarge; } ul > li:first-child > a, + ul > li:first-child > button, ul > li:first-child > span { .border-left-radius(@borderRadiusLarge); } ul > li:last-child > a, + ul > li:last-child > button, ul > li:last-child > span { .border-right-radius(@borderRadiusLarge); } @@ -95,10 +108,12 @@ .pagination-mini, .pagination-small { ul > li:first-child > a, + ul > li:first-child > button, ul > li:first-child > span { .border-left-radius(@borderRadiusSmall); } ul > li:last-child > a, + ul > li:last-child > button, ul > li:last-child > span { .border-right-radius(@borderRadiusSmall); } @@ -107,6 +122,7 @@ // Small .pagination-small { ul > li > a, + ul > li > button, ul > li > span { padding: @paddingSmall; font-size: @fontSizeSmall; @@ -115,6 +131,7 @@ // Mini .pagination-mini { ul > li > a, + ul > li > button, ul > li > span { padding: @paddingMini; font-size: @fontSizeMini; diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 454d081fe7..100774f385 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -44,7 +44,8 @@ "spectrum-colorpicker": "1.8.0", "tinymce": "4.9.11", "typeahead.js": "0.11.1", - "underscore": "1.9.1" + "underscore": "1.9.1", + "wicg-inert": "^3.0.2" }, "devDependencies": { "@babel/core": "7.6.4", diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-activity.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-activity.svg new file mode 100644 index 0000000000..84c1202f04 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-activity.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-add.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-add.svg new file mode 100644 index 0000000000..9abe4f9085 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-adressbook.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-adressbook.svg new file mode 100644 index 0000000000..1c6676a711 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-adressbook.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alarm-clock.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alarm-clock.svg new file mode 100644 index 0000000000..4aa9ce1485 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alarm-clock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert-alt.svg new file mode 100644 index 0000000000..dbb78a2188 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert.svg new file mode 100644 index 0000000000..3a75464feb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alt.svg new file mode 100644 index 0000000000..1d4c0eb3e6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-anchor.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-anchor.svg new file mode 100644 index 0000000000..033467b283 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-anchor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-app.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-app.svg new file mode 100644 index 0000000000..02b19fe989 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-app.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-error.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-error.svg new file mode 100644 index 0000000000..cd57ff336f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-error.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window-alt.svg new file mode 100644 index 0000000000..e87dae6ec8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window.svg new file mode 100644 index 0000000000..f99af0f195 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrivals.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrivals.svg new file mode 100644 index 0000000000..bfbe503d6b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrivals.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-down.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-down.svg new file mode 100644 index 0000000000..fcdf4548ec --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-left.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-left.svg new file mode 100644 index 0000000000..2cf42ff7d6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-right.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-right.svg new file mode 100644 index 0000000000..d1349b3b23 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-up.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-up.svg new file mode 100644 index 0000000000..f7ca5f8249 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-art-easel.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-art-easel.svg new file mode 100644 index 0000000000..c4df06598b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-art-easel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-article.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-article.svg new file mode 100644 index 0000000000..28b2e35c71 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-article.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-attachment.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-attachment.svg new file mode 100644 index 0000000000..a3c4f466c3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-attachment.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-auction-hammer.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-auction-hammer.svg new file mode 100644 index 0000000000..50f8b8ef26 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-auction-hammer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-autofill.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-autofill.svg new file mode 100644 index 0000000000..15cbe9fc35 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-autofill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-award.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-award.svg new file mode 100644 index 0000000000..18a82455f8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-award.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-2.svg new file mode 100644 index 0000000000..d8ef136b72 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-3.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-3.svg new file mode 100644 index 0000000000..77a56e9984 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-3.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation.svg new file mode 100644 index 0000000000..5f56a648d1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-baby-stroller.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-baby-stroller.svg new file mode 100644 index 0000000000..d8edc730c1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-baby-stroller.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-backspace.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-backspace.svg new file mode 100644 index 0000000000..6c84aa5cbc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-backspace.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-add.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-add.svg new file mode 100644 index 0000000000..0c6be8a34b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-count.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-count.svg new file mode 100644 index 0000000000..e309c884f9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-count.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-remove.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-remove.svg new file mode 100644 index 0000000000..a6317092b8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-remove.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-restricted.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-restricted.svg new file mode 100644 index 0000000000..c7ad647e22 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-restricted.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ball.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ball.svg new file mode 100644 index 0000000000..5416815534 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ball.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-band-aid.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-band-aid.svg new file mode 100644 index 0000000000..8232ea9b23 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-band-aid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bar-chart.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bar-chart.svg new file mode 100644 index 0000000000..c2fc1a2e2f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bar-chart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-barcode.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-barcode.svg new file mode 100644 index 0000000000..7b7e4e151e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-barcode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bars.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bars.svg new file mode 100644 index 0000000000..2199f4fb11 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bars.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-full.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-full.svg new file mode 100644 index 0000000000..5aff9d10df --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-full.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-low.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-low.svg new file mode 100644 index 0000000000..72909d1d84 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-low.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-beer-glass.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-beer-glass.svg new file mode 100644 index 0000000000..dc9e44cff7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-beer-glass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell-off.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell-off.svg new file mode 100644 index 0000000000..d7c9422857 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell.svg new file mode 100644 index 0000000000..6843f8dbc7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-dollar.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-dollar.svg new file mode 100644 index 0000000000..7ed749b1c8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-euro.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-euro.svg new file mode 100644 index 0000000000..c526f106a0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-euro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-pound.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-pound.svg new file mode 100644 index 0000000000..339006dc08 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-pound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-yen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-yen.svg new file mode 100644 index 0000000000..76b9a1d318 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-yen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill.svg new file mode 100644 index 0000000000..ad75b69591 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-billboard.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-billboard.svg new file mode 100644 index 0000000000..468e0dc8bd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-billboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-dollar.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-dollar.svg new file mode 100644 index 0000000000..dcd3a8f227 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-euro.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-euro.svg new file mode 100644 index 0000000000..3f2fbc38ef --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-euro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-pound.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-pound.svg new file mode 100644 index 0000000000..32a30de1c6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-pound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-yen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-yen.svg new file mode 100644 index 0000000000..ea352b33d5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-yen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills.svg new file mode 100644 index 0000000000..a6d9b7a76e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-binarycode.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-binarycode.svg new file mode 100644 index 0000000000..5a7e9ee9d2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-binarycode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-binoculars.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-binoculars.svg new file mode 100644 index 0000000000..407a88c58d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-binoculars.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bird.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bird.svg new file mode 100644 index 0000000000..182a02be79 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bird.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-birthday-cake.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-birthday-cake.svg new file mode 100644 index 0000000000..205a06715a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-birthday-cake.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-block.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-block.svg new file mode 100644 index 0000000000..ed19756dd9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-block.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-blueprint.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-blueprint.svg new file mode 100644 index 0000000000..4382644745 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-blueprint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bluetooth.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bluetooth.svg new file mode 100644 index 0000000000..2c73fb77a7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bluetooth.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-boat-shipping.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-boat-shipping.svg new file mode 100644 index 0000000000..15a8d6f9ff --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-boat-shipping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bomb.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bomb.svg new file mode 100644 index 0000000000..b39d18938c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bomb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bones.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bones.svg new file mode 100644 index 0000000000..f956d77bf3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bones.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt-2.svg new file mode 100644 index 0000000000..2003b3d233 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt.svg new file mode 100644 index 0000000000..c959cdea3a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book.svg new file mode 100644 index 0000000000..2516a55f83 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bookmark.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bookmark.svg new file mode 100644 index 0000000000..a3268596ac --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bookmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-books.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-books.svg new file mode 100644 index 0000000000..ddb9162770 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-books.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-alt.svg new file mode 100644 index 0000000000..0189daab6d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-open.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-open.svg new file mode 100644 index 0000000000..b2ec5d8bd3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box.svg new file mode 100644 index 0000000000..84fa9ca794 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brackets.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brackets.svg new file mode 100644 index 0000000000..142eb9f746 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brackets.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brick.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brick.svg new file mode 100644 index 0000000000..e06862f8aa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brick.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-briefcase.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-briefcase.svg new file mode 100644 index 0000000000..e6e0705ecf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-briefcase.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-browser-window.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-browser-window.svg new file mode 100644 index 0000000000..8279fb9198 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-browser-window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt-2.svg new file mode 100644 index 0000000000..3599902e1f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt.svg new file mode 100644 index 0000000000..65849ec18e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush.svg new file mode 100644 index 0000000000..a5b889c60d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bug.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bug.svg new file mode 100644 index 0000000000..9b5b667387 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bug.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bulleted-list.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bulleted-list.svg new file mode 100644 index 0000000000..72bdf63388 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bulleted-list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-burn.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-burn.svg new file mode 100644 index 0000000000..4f6ebe6865 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-burn.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bus.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bus.svg new file mode 100644 index 0000000000..95e728138e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calculator.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calculator.svg new file mode 100644 index 0000000000..3dcce7ec35 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calculator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar-alt.svg new file mode 100644 index 0000000000..fb485f5a83 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar.svg new file mode 100644 index 0000000000..b405db5525 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-camcorder.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-camcorder.svg new file mode 100644 index 0000000000..de0b071abb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-camcorder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-camera-roll.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-camera-roll.svg new file mode 100644 index 0000000000..172e0d92b0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-camera-roll.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-candy.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-candy.svg new file mode 100644 index 0000000000..1da869963f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-candy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-caps-lock.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-caps-lock.svg new file mode 100644 index 0000000000..1a466182c9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-caps-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-car.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-car.svg new file mode 100644 index 0000000000..9c72758d41 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-car.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cash-register.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cash-register.svg new file mode 100644 index 0000000000..f4f1779b86 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cash-register.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-categories.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-categories.svg new file mode 100644 index 0000000000..2bd633a8f1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-categories.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-certificate.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-certificate.svg new file mode 100644 index 0000000000..e3e16b5054 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-certificate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart-curve.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart-curve.svg new file mode 100644 index 0000000000..219d05a1f8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart-curve.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart.svg new file mode 100644 index 0000000000..72c6534c38 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat-active.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat-active.svg new file mode 100644 index 0000000000..b899dfc3fe --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat-active.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat.svg new file mode 100644 index 0000000000..21abb255ef --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-check.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-check.svg new file mode 100644 index 0000000000..5bd7161118 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted-active.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted-active.svg new file mode 100644 index 0000000000..f717f8063b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted-active.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted.svg new file mode 100644 index 0000000000..cf650c0085 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-empty.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-empty.svg new file mode 100644 index 0000000000..9a3edf8a28 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-empty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox.svg new file mode 100644 index 0000000000..748b269cd2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chess.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chess.svg new file mode 100644 index 0000000000..8cb5685672 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chess.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip-alt.svg new file mode 100644 index 0000000000..5d459f13b1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip.svg new file mode 100644 index 0000000000..0d622b2506 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cinema.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cinema.svg new file mode 100644 index 0000000000..f3bc729bf1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cinema.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted-active.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted-active.svg new file mode 100644 index 0000000000..f9c60410cb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted-active.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted.svg new file mode 100644 index 0000000000..9cd9fd9252 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circuits.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circuits.svg new file mode 100644 index 0000000000..4feb78fa69 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circuits.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circus.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circus.svg new file mode 100644 index 0000000000..ff712b18ed --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-client.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-client.svg new file mode 100644 index 0000000000..23e23117e9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-client.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-clothes-hanger.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-clothes-hanger.svg new file mode 100644 index 0000000000..f17c449cb0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-clothes-hanger.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-drive.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-drive.svg new file mode 100644 index 0000000000..df5fcf03d7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-drive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-upload.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-upload.svg new file mode 100644 index 0000000000..41e015fa89 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-upload.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud.svg new file mode 100644 index 0000000000..10a95d9562 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloudy.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloudy.svg new file mode 100644 index 0000000000..75aad3d4d2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloudy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-clubs.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-clubs.svg new file mode 100644 index 0000000000..68617041d5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-clubs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cocktail.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cocktail.svg new file mode 100644 index 0000000000..cc13e78a6f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cocktail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-code.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-code.svg new file mode 100644 index 0000000000..2615644cea --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coffee.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coffee.svg new file mode 100644 index 0000000000..d9e23e1259 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coffee.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-dollar.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-dollar.svg new file mode 100644 index 0000000000..6f3e0659da --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-euro.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-euro.svg new file mode 100644 index 0000000000..20527e3526 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-euro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-pound.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-pound.svg new file mode 100644 index 0000000000..9ba0de073b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-pound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-yen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-yen.svg new file mode 100644 index 0000000000..2d7f31caf1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-yen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin.svg new file mode 100644 index 0000000000..ec3b147525 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-alt.svg new file mode 100644 index 0000000000..a2349aaa12 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar-alt.svg new file mode 100644 index 0000000000..8f283ea006 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar.svg new file mode 100644 index 0000000000..0b2b7a2ea6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro-alt.svg new file mode 100644 index 0000000000..c8bbff6628 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro.svg new file mode 100644 index 0000000000..e1b77f5941 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound-alt.svg new file mode 100644 index 0000000000..e91acce12c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound.svg new file mode 100644 index 0000000000..6d1443a6c9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen-alt.svg new file mode 100644 index 0000000000..d477b86158 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen.svg new file mode 100644 index 0000000000..63aa1da6b2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins.svg new file mode 100644 index 0000000000..6af11e0945 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-color-bucket.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-color-bucket.svg new file mode 100644 index 0000000000..08fcb021d9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-color-bucket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-colorpicker.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-colorpicker.svg new file mode 100644 index 0000000000..69d0362805 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-colorpicker.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-columns.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-columns.svg new file mode 100644 index 0000000000..913a681162 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-columns.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-comb.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-comb.svg new file mode 100644 index 0000000000..d15c099fbe --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-comb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock-open.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock-open.svg new file mode 100644 index 0000000000..3cdba5cf20 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock.svg new file mode 100644 index 0000000000..10332f449f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-command.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-command.svg new file mode 100644 index 0000000000..7a4b9094f9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-command.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-company.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-company.svg new file mode 100644 index 0000000000..b22bdb63ad --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-company.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-compress.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-compress.svg new file mode 100644 index 0000000000..48664d5a36 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-compress.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-connection.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-connection.svg new file mode 100644 index 0000000000..0619278e2a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-connection.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-console.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-console.svg new file mode 100644 index 0000000000..8599aeb13a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-console.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-contrast.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-contrast.svg new file mode 100644 index 0000000000..8dbd2d9e74 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-contrast.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation-alt.svg new file mode 100644 index 0000000000..111b651f89 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation.svg new file mode 100644 index 0000000000..d16115fdb0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coverflow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coverflow.svg new file mode 100644 index 0000000000..72a230d15d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coverflow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card-alt.svg new file mode 100644 index 0000000000..c113197cf5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card.svg new file mode 100644 index 0000000000..af896af5f9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crop.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crop.svg new file mode 100644 index 0000000000..570c261e8a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crosshair.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crosshair.svg new file mode 100644 index 0000000000..802be32987 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crosshair.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown-alt.svg new file mode 100644 index 0000000000..20bbacb2eb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown.svg new file mode 100644 index 0000000000..8ad5f1464a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cupcake.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cupcake.svg new file mode 100644 index 0000000000..de3a7c7c81 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cupcake.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-curve.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-curve.svg new file mode 100644 index 0000000000..ac749474d3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-curve.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cut.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cut.svg new file mode 100644 index 0000000000..63d892780c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cut.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dashboard.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dashboard.svg new file mode 100644 index 0000000000..13cd3bfa96 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dashboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-defrag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-defrag.svg new file mode 100644 index 0000000000..e26de351e9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-defrag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete-key.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete-key.svg new file mode 100644 index 0000000000..c738e7c8cf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete-key.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete.svg new file mode 100644 index 0000000000..1d931cc09b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-departure.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-departure.svg new file mode 100644 index 0000000000..243f789b80 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-departure.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-desk.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-desk.svg new file mode 100644 index 0000000000..270e0f1dff --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-desk.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-desktop.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-desktop.svg new file mode 100644 index 0000000000..de5366b44b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-desktop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagnostics.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagnostics.svg new file mode 100644 index 0000000000..66e2b4c653 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagnostics.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow-alt.svg new file mode 100644 index 0000000000..fb4970d319 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow.svg new file mode 100644 index 0000000000..c10853ffcc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamond.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamond.svg new file mode 100644 index 0000000000..e831ae1172 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamond.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamonds.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamonds.svg new file mode 100644 index 0000000000..bf1cd0b8a4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamonds.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dice.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dice.svg new file mode 100644 index 0000000000..bbb86cf68d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dice.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma-alt.svg new file mode 100644 index 0000000000..b4a5fcfeb9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma.svg new file mode 100644 index 0000000000..31b542d112 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions-alt.svg new file mode 100644 index 0000000000..4a07354199 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions.svg new file mode 100644 index 0000000000..a56100bb2a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-disc.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-disc.svg new file mode 100644 index 0000000000..8f694bc43f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-disc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-disk-image.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-disk-image.svg new file mode 100644 index 0000000000..80a69f30d0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-disk-image.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-display.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-display.svg new file mode 100644 index 0000000000..22cf1ef0eb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-display.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dna.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dna.svg new file mode 100644 index 0000000000..a4cc100411 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dna.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dock-connector.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dock-connector.svg new file mode 100644 index 0000000000..82480deaa1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dock-connector.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-document-dashed-line.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-document-dashed-line.svg new file mode 100644 index 0000000000..6117d4c7f4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-document-dashed-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-document.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-document.svg new file mode 100644 index 0000000000..d2da15ad9e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-document.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-documents.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-documents.svg new file mode 100644 index 0000000000..4e56ca7b49 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-documents.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dollar-bag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dollar-bag.svg new file mode 100644 index 0000000000..bc9dcb83cf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dollar-bag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-donate.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-donate.svg new file mode 100644 index 0000000000..c2669c3a5c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-donate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open-alt.svg new file mode 100644 index 0000000000..57552cc455 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open.svg new file mode 100644 index 0000000000..02339e4b8b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-download-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-download-alt.svg new file mode 100644 index 0000000000..3b788ff610 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-download-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-download.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-download.svg new file mode 100644 index 0000000000..a328fe65f7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-download.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-drop.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-drop.svg new file mode 100644 index 0000000000..7523004cad --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-drop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eco.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eco.svg new file mode 100644 index 0000000000..dad4c564c0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eco.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-economy.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-economy.svg new file mode 100644 index 0000000000..4e710b572a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-economy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-edit.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-edit.svg new file mode 100644 index 0000000000..2faeea0891 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eject.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eject.svg new file mode 100644 index 0000000000..5f74a4ccc1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eject.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-employee.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-employee.svg new file mode 100644 index 0000000000..b1c4877b2b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-employee.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-energy-saving-bulb.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-energy-saving-bulb.svg new file mode 100644 index 0000000000..a45bbf5f4f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-energy-saving-bulb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-enter.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-enter.svg new file mode 100644 index 0000000000..4dc8c5af3d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-enter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-equalizer.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-equalizer.svg new file mode 100644 index 0000000000..64b43e8537 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-equalizer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-escape.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-escape.svg new file mode 100644 index 0000000000..edb544f9d3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-escape.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ethernet.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ethernet.svg new file mode 100644 index 0000000000..2b16efe994 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ethernet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-euro-bag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-euro-bag.svg new file mode 100644 index 0000000000..cb19eafeb9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-euro-bag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-exit-fullscreen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-exit-fullscreen.svg new file mode 100644 index 0000000000..820c79522d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-exit-fullscreen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eye.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eye.svg new file mode 100644 index 0000000000..8ea896a1f4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eye.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-facebook-like.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-facebook-like.svg new file mode 100644 index 0000000000..0f27d54a06 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-facebook-like.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-factory.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-factory.svg new file mode 100644 index 0000000000..855727aad5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-factory.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-favorite.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-favorite.svg new file mode 100644 index 0000000000..5fee2201b0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-favorite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-female-symbol.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-female-symbol.svg new file mode 100644 index 0000000000..9e003e51e5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-female-symbol.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-file-cabinet.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-file-cabinet.svg new file mode 100644 index 0000000000..8d34dc684f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-file-cabinet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-files.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-files.svg new file mode 100644 index 0000000000..228b54980d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-files.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter-arrows.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter-arrows.svg new file mode 100644 index 0000000000..2f17186e0c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter-arrows.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter.svg new file mode 100644 index 0000000000..41a89b3eb0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fingerprint.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fingerprint.svg new file mode 100644 index 0000000000..b80eebd81c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fingerprint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fire.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fire.svg new file mode 100644 index 0000000000..b0811f59f0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fire.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewall.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewall.svg new file mode 100644 index 0000000000..b857e4349e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewall.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewire.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewire.svg new file mode 100644 index 0000000000..64807e9110 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewire.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag-alt.svg new file mode 100644 index 0000000000..16d5b65bb6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag.svg new file mode 100644 index 0000000000..3665770b99 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flash.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flash.svg new file mode 100644 index 0000000000..f37a9e3483 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flashlight.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flashlight.svg new file mode 100644 index 0000000000..4610c03a5b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flashlight.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flowerpot.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flowerpot.svg new file mode 100644 index 0000000000..0524daab90 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flowerpot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-open.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-open.svg new file mode 100644 index 0000000000..44de932cfd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-outline.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-outline.svg new file mode 100644 index 0000000000..77059225c7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder.svg new file mode 100644 index 0000000000..ce20ed705e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folders.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folders.svg new file mode 100644 index 0000000000..08875280e9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folders.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-font.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-font.svg new file mode 100644 index 0000000000..91689c5b49 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-font.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-food.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-food.svg new file mode 100644 index 0000000000..d39b58346a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-food.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-footprints.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-footprints.svg new file mode 100644 index 0000000000..118b8dc44f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-footprints.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-forking.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-forking.svg new file mode 100644 index 0000000000..441dead254 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-forking.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame-alt.svg new file mode 100644 index 0000000000..24c8834c55 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame.svg new file mode 100644 index 0000000000..6d48f3165d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen-alt.svg new file mode 100644 index 0000000000..c2145c8171 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen.svg new file mode 100644 index 0000000000..a63101cfe0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-game.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-game.svg new file mode 100644 index 0000000000..78797b5601 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-game.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-geometry.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-geometry.svg new file mode 100644 index 0000000000..c7ed79e0a1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-geometry.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-gift.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-gift.svg new file mode 100644 index 0000000000..4e2030a6f1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-gift.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-glasses.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-glasses.svg new file mode 100644 index 0000000000..72b7c8b05b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-glasses.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-alt.svg new file mode 100644 index 0000000000..b02f41ad97 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-asia.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-asia.svg new file mode 100644 index 0000000000..6a7334d5e8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-asia.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-europe-africa.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-europe-africa.svg new file mode 100644 index 0000000000..4c9b6fac01 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-europe-africa.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-america.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-america.svg new file mode 100644 index 0000000000..a95c1a1975 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-america.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-asia.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-asia.svg new file mode 100644 index 0000000000..c62b1e835a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-asia.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-europe-africa.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-europe-africa.svg new file mode 100644 index 0000000000..af162e7949 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-europe-africa.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe.svg new file mode 100644 index 0000000000..28e4b649be --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-gps.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-gps.svg new file mode 100644 index 0000000000..90572f37f6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-gps.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-graduate.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-graduate.svg new file mode 100644 index 0000000000..81067c4cdb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-graduate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-grid.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-grid.svg new file mode 100644 index 0000000000..2e363c0c47 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-grid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hammer.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hammer.svg new file mode 100644 index 0000000000..dfafc27d3c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hammer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active-alt.svg new file mode 100644 index 0000000000..102ae217cf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active.svg new file mode 100644 index 0000000000..49612abea3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer-alt.svg new file mode 100644 index 0000000000..3e1185fe73 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer.svg new file mode 100644 index 0000000000..a002ace0f3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handprint.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handprint.svg new file mode 100644 index 0000000000..c9c254204b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handprint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handshake.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handshake.svg new file mode 100644 index 0000000000..b83e3bf315 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handshake.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool-alt.svg new file mode 100644 index 0000000000..1464083b74 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool.svg new file mode 100644 index 0000000000..2202ced6d6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive-alt.svg new file mode 100644 index 0000000000..89ce2fea0e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive.svg new file mode 100644 index 0000000000..98a2a993d4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hat.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hat.svg new file mode 100644 index 0000000000..c8a1106446 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hd.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hd.svg new file mode 100644 index 0000000000..77bf64d4fa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hd.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-headphones.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-headphones.svg new file mode 100644 index 0000000000..811c656c7e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-headphones.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-headset.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-headset.svg new file mode 100644 index 0000000000..98db2e30db --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-headset.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hearts.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hearts.svg new file mode 100644 index 0000000000..c2edaafe03 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hearts.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-height.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-height.svg new file mode 100644 index 0000000000..bf6a75975b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-height.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-help-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-help-alt.svg new file mode 100644 index 0000000000..101c65318d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-help-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-help.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-help.svg new file mode 100644 index 0000000000..a1c5fdc7c1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-help.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-home.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-home.svg new file mode 100644 index 0000000000..ebb93f4056 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-home.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hourglass.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hourglass.svg new file mode 100644 index 0000000000..c918b5407b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hourglass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-imac.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-imac.svg new file mode 100644 index 0000000000..76a01b97b8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-imac.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inactive-line.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inactive-line.svg new file mode 100644 index 0000000000..60a16437c2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inactive-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox-full.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox-full.svg new file mode 100644 index 0000000000..c0beabfa29 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox-full.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox.svg new file mode 100644 index 0000000000..0fd7c71b22 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-indent.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-indent.svg new file mode 100644 index 0000000000..329b0f413e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-indent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-infinity.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-infinity.svg new file mode 100644 index 0000000000..c42e3bd49e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-infinity.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-info.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-info.svg new file mode 100644 index 0000000000..f07ac8e7d1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-info.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-invoice.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-invoice.svg new file mode 100644 index 0000000000..dd8457a63a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-invoice.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ipad.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ipad.svg new file mode 100644 index 0000000000..e79195e670 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ipad.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-iphone.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-iphone.svg new file mode 100644 index 0000000000..b235644b03 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-iphone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-item-arrangement.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-item-arrangement.svg new file mode 100644 index 0000000000..fd9939dba3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-item-arrangement.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-junk.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-junk.svg new file mode 100644 index 0000000000..a8f48754d4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-junk.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-key.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-key.svg new file mode 100644 index 0000000000..4a32d0004e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-key.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyboard.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyboard.svg new file mode 100644 index 0000000000..c08d8d9e93 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keychain.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keychain.svg new file mode 100644 index 0000000000..e206a9150e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keychain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyhole.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyhole.svg new file mode 100644 index 0000000000..b97b156002 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyhole.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lab.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lab.svg new file mode 100644 index 0000000000..b750677812 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lab.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-laptop.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-laptop.svg new file mode 100644 index 0000000000..dc120cca29 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-laptop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers-alt.svg new file mode 100644 index 0000000000..e02a1cadbf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers.svg new file mode 100644 index 0000000000..c6965e3e95 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layout.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layout.svg new file mode 100644 index 0000000000..355f314f0f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layout.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-left-double-arrow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-left-double-arrow.svg new file mode 100644 index 0000000000..0958c291da --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-left-double-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-legal.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-legal.svg new file mode 100644 index 0000000000..e4ea59375e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-legal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lense.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lense.svg new file mode 100644 index 0000000000..229a7749bd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lense.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-library.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-library.svg new file mode 100644 index 0000000000..1551dec3c9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-library.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-down.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-down.svg new file mode 100644 index 0000000000..c214226f59 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-up.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-up.svg new file mode 100644 index 0000000000..dbac39d507 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb-active.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb-active.svg new file mode 100644 index 0000000000..522460a54c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb-active.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb.svg new file mode 100644 index 0000000000..2d67f238ee --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightning.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightning.svg new file mode 100644 index 0000000000..4f8b5a1146 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightning.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-link.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-link.svg new file mode 100644 index 0000000000..2bb9b95c01 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-linux-tux.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-linux-tux.svg new file mode 100644 index 0000000000..cd90e979cd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-linux-tux.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-list.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-list.svg new file mode 100644 index 0000000000..78a748f1a1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-load.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-load.svg new file mode 100644 index 0000000000..6f4ac6197c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-load.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-loading.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-loading.svg new file mode 100644 index 0000000000..91372f4e34 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-loading.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-locate.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-locate.svg new file mode 100644 index 0000000000..b6d715d2f0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-locate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-near-me.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-near-me.svg new file mode 100644 index 0000000000..69028bf985 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-near-me.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-nearby.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-nearby.svg new file mode 100644 index 0000000000..884edb711b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-nearby.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lock.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lock.svg new file mode 100644 index 0000000000..8f94c7cb96 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-log-out.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-log-out.svg new file mode 100644 index 0000000000..07c4ae9856 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-log-out.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-logout.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-logout.svg new file mode 100644 index 0000000000..e3eb856a9a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-logout.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-loupe.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-loupe.svg new file mode 100644 index 0000000000..ab5137dc24 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-loupe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-magnet.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-magnet.svg new file mode 100644 index 0000000000..b7c9ed6ab1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-magnet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mailbox.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mailbox.svg new file mode 100644 index 0000000000..e55cdc452c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mailbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-and-female.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-and-female.svg new file mode 100644 index 0000000000..5ddf3b95e1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-and-female.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-symbol.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-symbol.svg new file mode 100644 index 0000000000..eb91f509f5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-symbol.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-alt.svg new file mode 100644 index 0000000000..fcc39f5bb0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-location.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-location.svg new file mode 100644 index 0000000000..ad9efb05ed --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-location.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-marker.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-marker.svg new file mode 100644 index 0000000000..a4f71dc084 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-marker.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map.svg new file mode 100644 index 0000000000..2c9ae42407 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medal.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medal.svg new file mode 100644 index 0000000000..c97ccf0f32 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medical-emergency.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medical-emergency.svg new file mode 100644 index 0000000000..0265c28988 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medical-emergency.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medicine.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medicine.svg new file mode 100644 index 0000000000..1e2cb6aeef --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medicine.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-meeting.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-meeting.svg new file mode 100644 index 0000000000..09af0d97c2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-meeting.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-megaphone.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-megaphone.svg new file mode 100644 index 0000000000..25387c9357 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-megaphone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-merge.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-merge.svg new file mode 100644 index 0000000000..57ac52511a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-merge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-open.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-open.svg new file mode 100644 index 0000000000..98aaeeeb64 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-unopened.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-unopened.svg new file mode 100644 index 0000000000..e29ecbf60d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-unopened.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message.svg new file mode 100644 index 0000000000..75785c1896 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-microscope.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-microscope.svg new file mode 100644 index 0000000000..9985552be3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-microscope.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mindmap.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mindmap.svg new file mode 100644 index 0000000000..043927014b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mindmap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mobile.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mobile.svg new file mode 100644 index 0000000000..92532b8005 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mobile.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular-network.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular-network.svg new file mode 100644 index 0000000000..20d87126aa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular-network.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular.svg new file mode 100644 index 0000000000..904e0976c3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mountain.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mountain.svg new file mode 100644 index 0000000000..a21324f819 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mountain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse-cursor.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse-cursor.svg new file mode 100644 index 0000000000..b64dd7f88b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse-cursor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse.svg new file mode 100644 index 0000000000..f063df5259 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie-alt.svg new file mode 100644 index 0000000000..1878dc9ec0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie.svg new file mode 100644 index 0000000000..d5b3481a83 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-credit-cards.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-credit-cards.svg new file mode 100644 index 0000000000..1330826784 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-credit-cards.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-windows.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-windows.svg new file mode 100644 index 0000000000..c8b3ac5669 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-windows.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-music.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-music.svg new file mode 100644 index 0000000000..87f4ba36a6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-music.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-name-badge.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-name-badge.svg new file mode 100644 index 0000000000..22f66c9234 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-name-badge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-bottom.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-bottom.svg new file mode 100644 index 0000000000..eeb3e79bdc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-bottom.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-down.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-down.svg new file mode 100644 index 0000000000..007e8dd8ff --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-first.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-first.svg new file mode 100644 index 0000000000..85d44722ee --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-first.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-horizontal.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-horizontal.svg new file mode 100644 index 0000000000..4988e723eb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-horizontal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-last.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-last.svg new file mode 100644 index 0000000000..53f70d36fd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-last.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-left.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-left.svg new file mode 100644 index 0000000000..56cdecce10 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-right.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-right.svg new file mode 100644 index 0000000000..251b6934d3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-road.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-road.svg new file mode 100644 index 0000000000..f05567099f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-road.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-top.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-top.svg new file mode 100644 index 0000000000..c932714737 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-top.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-up.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-up.svg new file mode 100644 index 0000000000..612ec9193e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-vertical.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-vertical.svg new file mode 100644 index 0000000000..fbe3906472 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-vertical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation.svg new file mode 100644 index 0000000000..67d9c2a0c2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigational-arrow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigational-arrow.svg new file mode 100644 index 0000000000..bf60bde293 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigational-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-network-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-network-alt.svg new file mode 100644 index 0000000000..e6b2c25036 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-network-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper-alt.svg new file mode 100644 index 0000000000..1bcf422c64 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper.svg new file mode 100644 index 0000000000..d585513f28 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-next-media.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-next-media.svg new file mode 100644 index 0000000000..57d4c8e0e3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-next-media.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-next.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-next.svg new file mode 100644 index 0000000000..b00b37dd17 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-nodes.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-nodes.svg new file mode 100644 index 0000000000..e912e52d15 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-nodes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad-alt.svg new file mode 100644 index 0000000000..bca4d0c462 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad.svg new file mode 100644 index 0000000000..5fc428082e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-key.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-key.svg new file mode 100644 index 0000000000..a4003027a4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-key.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-phone.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-phone.svg new file mode 100644 index 0000000000..8eb7804e74 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-operator.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-operator.svg new file mode 100644 index 0000000000..ad78b8602f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-operator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ordered-list.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ordered-list.svg new file mode 100644 index 0000000000..de140283b8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ordered-list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-os-x.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-os-x.svg new file mode 100644 index 0000000000..170f3aad47 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-os-x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-out.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-out.svg new file mode 100644 index 0000000000..73d2cfe147 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-out.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-outbox.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-outbox.svg new file mode 100644 index 0000000000..3b59c93933 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-outbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-outdent.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-outdent.svg new file mode 100644 index 0000000000..85ff01f440 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-outdent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-add.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-add.svg new file mode 100644 index 0000000000..538defed20 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-down.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-down.svg new file mode 100644 index 0000000000..2fae28dfd9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-remove.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-remove.svg new file mode 100644 index 0000000000..c5009604d4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-remove.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-restricted.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-restricted.svg new file mode 100644 index 0000000000..4a7c8696e2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-restricted.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-up.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-up.svg new file mode 100644 index 0000000000..db6ad88927 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paint-roller.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paint-roller.svg new file mode 100644 index 0000000000..59665d6232 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paint-roller.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-palette.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-palette.svg new file mode 100644 index 0000000000..26c9f7f6b2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-palette.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-panel-show.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-panel-show.svg new file mode 100644 index 0000000000..91c3e9f0ca --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-panel-show.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pannel-close.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pannel-close.svg new file mode 100644 index 0000000000..8006a60541 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pannel-close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pants.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pants.svg new file mode 100644 index 0000000000..9604660ce0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pants.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-bag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-bag.svg new file mode 100644 index 0000000000..e7435caf75 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-bag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane-alt.svg new file mode 100644 index 0000000000..2c4259e954 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane.svg new file mode 100644 index 0000000000..fe60af779b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-parachute-drop.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-parachute-drop.svg new file mode 100644 index 0000000000..cdd4a501d7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-parachute-drop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-parental-control.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-parental-control.svg new file mode 100644 index 0000000000..3a19170b80 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-parental-control.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-partly-cloudy.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-partly-cloudy.svg new file mode 100644 index 0000000000..57af81127e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-partly-cloudy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paste-in.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paste-in.svg new file mode 100644 index 0000000000..eae1a1bd12 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paste-in.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-path.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-path.svg new file mode 100644 index 0000000000..a8f5df6e4c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-path.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pause.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pause.svg new file mode 100644 index 0000000000..7d9dce3838 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pause.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pc.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pc.svg new file mode 100644 index 0000000000..a8c8196797 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt-2.svg new file mode 100644 index 0000000000..4aa84eae75 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt.svg new file mode 100644 index 0000000000..7f129069c7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-female.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-female.svg new file mode 100644 index 0000000000..0cf6088418 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-female.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people.svg new file mode 100644 index 0000000000..ab861f8814 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone-ring.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone-ring.svg new file mode 100644 index 0000000000..1797603bbc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone-ring.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone.svg new file mode 100644 index 0000000000..085e41600e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-photo-album.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-photo-album.svg new file mode 100644 index 0000000000..532615bf2a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-photo-album.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-picture.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-picture.svg new file mode 100644 index 0000000000..9250074063 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-picture.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt-2.svg new file mode 100644 index 0000000000..4bc1120750 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt.svg new file mode 100644 index 0000000000..eee91913ed --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures.svg new file mode 100644 index 0000000000..8844e068b2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pie-chart.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pie-chart.svg new file mode 100644 index 0000000000..1db73f63d3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pie-chart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-piggy-bank.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-piggy-bank.svg new file mode 100644 index 0000000000..45c74819f8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-piggy-bank.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pin-location.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pin-location.svg new file mode 100644 index 0000000000..5907d6e541 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pin-location.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-piracy.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-piracy.svg new file mode 100644 index 0000000000..577d04e517 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-piracy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-plane.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-plane.svg new file mode 100644 index 0000000000..c09d4522e2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-plane.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-planet.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-planet.svg new file mode 100644 index 0000000000..455ce2da3a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-planet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-play.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-play.svg new file mode 100644 index 0000000000..3a041b7e2b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-playing-cards.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-playing-cards.svg new file mode 100644 index 0000000000..132d264d5b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-playing-cards.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-playlist.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-playlist.svg new file mode 100644 index 0000000000..0492601307 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-playlist.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-plugin.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-plugin.svg new file mode 100644 index 0000000000..c88e396dfa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-plugin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-podcast.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-podcast.svg new file mode 100644 index 0000000000..796c263f0a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-podcast.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-poker-chip.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-poker-chip.svg new file mode 100644 index 0000000000..6f3698bd66 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-poker-chip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-poll.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-poll.svg new file mode 100644 index 0000000000..089fa647d1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-poll.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-post-it.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-post-it.svg new file mode 100644 index 0000000000..61a2787df8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-post-it.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pound-bag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pound-bag.svg new file mode 100644 index 0000000000..dfb460d22a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pound-bag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-power-outlet.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-power-outlet.svg new file mode 100644 index 0000000000..41e3e51e20 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-power-outlet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-power.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-power.svg new file mode 100644 index 0000000000..9c4fb4b087 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-power.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-presentation.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-presentation.svg new file mode 100644 index 0000000000..59e720c81e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-presentation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous-media.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous-media.svg new file mode 100644 index 0000000000..656c29d14c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous-media.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous.svg new file mode 100644 index 0000000000..f858829633 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-dollar.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-dollar.svg new file mode 100644 index 0000000000..72d42718a9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-euro.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-euro.svg new file mode 100644 index 0000000000..0c437bc769 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-euro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-pound.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-pound.svg new file mode 100644 index 0000000000..0858462da8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-pound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-yen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-yen.svg new file mode 100644 index 0000000000..96c3917842 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-yen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-print.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-print.svg new file mode 100644 index 0000000000..3bce86bedd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-print.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-printer-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-printer-alt.svg new file mode 100644 index 0000000000..050ec1d81c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-printer-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-projector.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-projector.svg new file mode 100644 index 0000000000..afc95283c3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-projector.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pulse.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pulse.svg new file mode 100644 index 0000000000..8a655631af --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pulse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pushpin.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pushpin.svg new file mode 100644 index 0000000000..586bf4fdc0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pushpin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-qr-code.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-qr-code.svg new file mode 100644 index 0000000000..bdbf3d64fb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-qr-code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-quote.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-quote.svg new file mode 100644 index 0000000000..16746643b6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-quote.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-alt.svg new file mode 100644 index 0000000000..c7dcf65677 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-receiver.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-receiver.svg new file mode 100644 index 0000000000..a3bea41462 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-receiver.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio.svg new file mode 100644 index 0000000000..2cf8718a2e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rain.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rain.svg new file mode 100644 index 0000000000..0007d98d6c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rate.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rate.svg new file mode 100644 index 0000000000..aac2ba0481 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-re-post.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-re-post.svg new file mode 100644 index 0000000000..80b7a9673d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-re-post.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-readonly.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-readonly.svg new file mode 100644 index 0000000000..b0840b5171 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-readonly.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-alt.svg new file mode 100644 index 0000000000..d7b6f5e860 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-dollar.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-dollar.svg new file mode 100644 index 0000000000..6784c6e8df --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-euro.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-euro.svg new file mode 100644 index 0000000000..82e99b2eec --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-euro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-pound.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-pound.svg new file mode 100644 index 0000000000..b28cf9e00d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-pound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-yen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-yen.svg new file mode 100644 index 0000000000..529fd87d4e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-yen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-reception.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-reception.svg new file mode 100644 index 0000000000..01a61f4ae9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-reception.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-record.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-record.svg new file mode 100644 index 0000000000..5a928928d3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-record.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-redo.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-redo.svg new file mode 100644 index 0000000000..b1fcfc01d6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-redo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-refresh.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-refresh.svg new file mode 100644 index 0000000000..b3c932583f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-refresh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-remote.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-remote.svg new file mode 100644 index 0000000000..ff3d1de672 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-remote.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-remove.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-remove.svg new file mode 100644 index 0000000000..97bff0169f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-remove.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat-one.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat-one.svg new file mode 100644 index 0000000000..054185177f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat-one.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat.svg new file mode 100644 index 0000000000..68e7b30f8a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-reply-arrow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-reply-arrow.svg new file mode 100644 index 0000000000..fd708c5173 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-reply-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-resize.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-resize.svg new file mode 100644 index 0000000000..e26e9fb196 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-resize.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-return-to-top.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-return-to-top.svg new file mode 100644 index 0000000000..15e5d82289 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-return-to-top.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-right-double-arrow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-right-double-arrow.svg new file mode 100644 index 0000000000..a8f4a03cb7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-right-double-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-road.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-road.svg new file mode 100644 index 0000000000..e9dedee5bd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-road.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-roadsign.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-roadsign.svg new file mode 100644 index 0000000000..4115c305c4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-roadsign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rocket.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rocket.svg new file mode 100644 index 0000000000..5fab3cf1ba --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rocket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rss.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rss.svg new file mode 100644 index 0000000000..96a210c20c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rss.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler-alt.svg new file mode 100644 index 0000000000..695d110031 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler.svg new file mode 100644 index 0000000000..15eff181d8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-safe.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-safe.svg new file mode 100644 index 0000000000..9bdce49ca5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-safe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-safedial.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-safedial.svg new file mode 100644 index 0000000000..da9a6a6275 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-safedial.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sandbox-toys.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sandbox-toys.svg new file mode 100644 index 0000000000..727e62cc18 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sandbox-toys.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-satellite-dish.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-satellite-dish.svg new file mode 100644 index 0000000000..235d67c316 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-satellite-dish.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-save.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-save.svg new file mode 100644 index 0000000000..c4a56c7268 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-save.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-scan.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-scan.svg new file mode 100644 index 0000000000..de0a84c4b6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-scan.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-school.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-school.svg new file mode 100644 index 0000000000..216a3ff764 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-school.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-screensharing.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-screensharing.svg new file mode 100644 index 0000000000..065d04c278 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-screensharing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-script-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-script-alt.svg new file mode 100644 index 0000000000..4efc77d194 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-script-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-script.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-script.svg new file mode 100644 index 0000000000..224b12e0a4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-script.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-scull.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-scull.svg new file mode 100644 index 0000000000..fc2d5cc4b2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-scull.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-search.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-search.svg new file mode 100644 index 0000000000..1e0715b800 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-security-camera.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-security-camera.svg new file mode 100644 index 0000000000..09bb6613aa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-security-camera.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sensor.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sensor.svg new file mode 100644 index 0000000000..a73de18bb1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sensor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-server-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-server-alt.svg new file mode 100644 index 0000000000..e1d6a449a5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-server-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-server.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-server.svg new file mode 100644 index 0000000000..04636e254a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-server.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt-2.svg new file mode 100644 index 0000000000..da84deb9e5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt.svg new file mode 100644 index 0000000000..ab9eb44951 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings.svg new file mode 100644 index 0000000000..6311ad6122 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt-2.svg new file mode 100644 index 0000000000..6f220aaa6d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt.svg new file mode 100644 index 0000000000..7cff7b3840 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share.svg new file mode 100644 index 0000000000..2e4584a775 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sharing-iphone.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sharing-iphone.svg new file mode 100644 index 0000000000..04d34e0fe3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sharing-iphone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shield.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shield.svg new file mode 100644 index 0000000000..f34195c7d4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shield.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shift.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shift.svg new file mode 100644 index 0000000000..3d6f9aea9d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shift.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping-box.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping-box.svg new file mode 100644 index 0000000000..66e12cea40 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping-box.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping.svg new file mode 100644 index 0000000000..102cb0be70 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shoe.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shoe.svg new file mode 100644 index 0000000000..f784c832a6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shoe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt-2.svg new file mode 100644 index 0000000000..06beb2dc40 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt.svg new file mode 100644 index 0000000000..5cdd20bf19 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket.svg new file mode 100644 index 0000000000..71cdd1de20 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shorts.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shorts.svg new file mode 100644 index 0000000000..e3f8ab2625 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shorts.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shuffle.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shuffle.svg new file mode 100644 index 0000000000..546f0a2965 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shuffle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sience.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sience.svg new file mode 100644 index 0000000000..e692a2ec0c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sience.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-simcard.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-simcard.svg new file mode 100644 index 0000000000..a65fc9ffb5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-simcard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-single-note.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-single-note.svg new file mode 100644 index 0000000000..f98a14c285 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-single-note.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sitemap.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sitemap.svg new file mode 100644 index 0000000000..0cbd6659a4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sitemap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sleep.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sleep.svg new file mode 100644 index 0000000000..c85ac0dc8a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sleep.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-slideshow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-slideshow.svg new file mode 100644 index 0000000000..484e86cd28 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-slideshow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley-inverted.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley-inverted.svg new file mode 100644 index 0000000000..8c2bc19928 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley-inverted.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley.svg new file mode 100644 index 0000000000..5504a545cd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-snow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-snow.svg new file mode 100644 index 0000000000..2ba7134a91 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-snow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-low.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-low.svg new file mode 100644 index 0000000000..1a5abc0193 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-low.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-medium.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-medium.svg new file mode 100644 index 0000000000..d6497c7c88 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-medium.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-off.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-off.svg new file mode 100644 index 0000000000..173ea47692 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-waves.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-waves.svg new file mode 100644 index 0000000000..cf21b5606b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-waves.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound.svg new file mode 100644 index 0000000000..ff3ba17166 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-spades.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-spades.svg new file mode 100644 index 0000000000..f97a5457f8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-spades.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-speaker.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-speaker.svg new file mode 100644 index 0000000000..dc922a00d3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-speaker.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-speed-gauge.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-speed-gauge.svg new file mode 100644 index 0000000000..ce52283ddb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-speed-gauge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-split-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-split-alt.svg new file mode 100644 index 0000000000..a5ad049940 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-split-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-split.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-split.svg new file mode 100644 index 0000000000..1bdfd8a66b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-split.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sprout.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sprout.svg new file mode 100644 index 0000000000..1d139dd355 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sprout.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-squiggly-line.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-squiggly-line.svg new file mode 100644 index 0000000000..2c88881018 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-squiggly-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ssd.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ssd.svg new file mode 100644 index 0000000000..483398df2d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ssd.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stacked-disks.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stacked-disks.svg new file mode 100644 index 0000000000..0c6fb6e8d1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stacked-disks.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stamp.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stamp.svg new file mode 100644 index 0000000000..2468ef2c74 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stamp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-alt.svg new file mode 100644 index 0000000000..ed61a5b6cc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-hand.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-hand.svg new file mode 100644 index 0000000000..3742256b80 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-hand.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop.svg new file mode 100644 index 0000000000..6b61d9904b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-store.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-store.svg new file mode 100644 index 0000000000..3a9618fef2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-store.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stream.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stream.svg new file mode 100644 index 0000000000..97ea6bed56 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stream.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sunny.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sunny.svg new file mode 100644 index 0000000000..07391fec24 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sunny.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sweatshirt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sweatshirt.svg new file mode 100644 index 0000000000..3b33e88738 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sweatshirt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sync.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sync.svg new file mode 100644 index 0000000000..b3e8e396bc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sync.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-t-shirt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-t-shirt.svg new file mode 100644 index 0000000000..860762bf35 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-t-shirt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab-key.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab-key.svg new file mode 100644 index 0000000000..dcd4d918c8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab-key.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab.svg new file mode 100644 index 0000000000..a03fd4e379 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tactics.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tactics.svg new file mode 100644 index 0000000000..ba1a383471 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tactics.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tag.svg new file mode 100644 index 0000000000..ffeadcc433 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tags.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tags.svg new file mode 100644 index 0000000000..681f38712d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tags.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-takeaway-cup.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-takeaway-cup.svg new file mode 100644 index 0000000000..5360908485 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-takeaway-cup.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-target.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-target.svg new file mode 100644 index 0000000000..f61b84adc6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-target.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperatrure-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperatrure-alt.svg new file mode 100644 index 0000000000..235b8a1eb9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperatrure-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperature.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperature.svg new file mode 100644 index 0000000000..fa6c7859fa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperature.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-terminal.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-terminal.svg new file mode 100644 index 0000000000..edb6b159e0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-terminal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-theater.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-theater.svg new file mode 100644 index 0000000000..b3a293ab48 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-theater.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-theif.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-theif.svg new file mode 100644 index 0000000000..f3b3ec69ad --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-theif.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thought-bubble.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thought-bubble.svg new file mode 100644 index 0000000000..59b9b71150 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thought-bubble.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-down.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-down.svg new file mode 100644 index 0000000000..933450deab --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-up.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-up.svg new file mode 100644 index 0000000000..1068c845bd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnail-list.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnail-list.svg new file mode 100644 index 0000000000..c6ddb31ec2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnail-list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails-small.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails-small.svg new file mode 100644 index 0000000000..ced7db6e71 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails-small.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails.svg new file mode 100644 index 0000000000..b8800a7000 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ticket.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ticket.svg new file mode 100644 index 0000000000..b69e61beec --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ticket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-time.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-time.svg new file mode 100644 index 0000000000..cd65d62e2e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-time.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-timer.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-timer.svg new file mode 100644 index 0000000000..f93538095b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-timer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tools.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tools.svg new file mode 100644 index 0000000000..a8a1aec10f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tools.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-top.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-top.svg new file mode 100644 index 0000000000..2bea18be1e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-top.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-traffic-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-traffic-alt.svg new file mode 100644 index 0000000000..9cb29dfaa0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-traffic-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trafic.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trafic.svg new file mode 100644 index 0000000000..420832c521 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trafic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-train.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-train.svg new file mode 100644 index 0000000000..b1de2d26e1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-train.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt-2.svg new file mode 100644 index 0000000000..8bb390a394 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt.svg new file mode 100644 index 0000000000..5fba12abc3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash.svg new file mode 100644 index 0000000000..abae234837 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tree.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tree.svg new file mode 100644 index 0000000000..8da9048412 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tree.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trophy.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trophy.svg new file mode 100644 index 0000000000..75229f89a8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trophy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-truck.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-truck.svg new file mode 100644 index 0000000000..112c57941f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-truck.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv-old.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv-old.svg new file mode 100644 index 0000000000..6bde7d04ac --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv-old.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv.svg new file mode 100644 index 0000000000..d3fc2d2cd9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-content.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-content.svg new file mode 100644 index 0000000000..3ee9892c48 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-content.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-contour.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-contour.svg new file mode 100644 index 0000000000..2590acf88d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-contour.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-deploy.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-deploy.svg new file mode 100644 index 0000000000..37c500ddd3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-deploy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-developer.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-developer.svg new file mode 100644 index 0000000000..f99365c4b4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-developer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-media.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-media.svg new file mode 100644 index 0000000000..9230e040bd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-media.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-members.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-members.svg new file mode 100644 index 0000000000..9193b6baa6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-members.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-settings.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-settings.svg new file mode 100644 index 0000000000..554ecdef32 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-users.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-users.svg new file mode 100644 index 0000000000..f8ef77731c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-users.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umbrella.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umbrella.svg new file mode 100644 index 0000000000..620eac158a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umbrella.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-undo.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-undo.svg new file mode 100644 index 0000000000..ca5152f6da --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-undo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-universal.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-universal.svg new file mode 100644 index 0000000000..49118f2935 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-universal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-unlocked.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-unlocked.svg new file mode 100644 index 0000000000..2254dfc910 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-unlocked.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-untitled.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-untitled.svg new file mode 100644 index 0000000000..4e621d71c1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-untitled.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb-connector.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb-connector.svg new file mode 100644 index 0000000000..0d97d4094d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb-connector.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb.svg new file mode 100644 index 0000000000..7478d50f9e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-female.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-female.svg new file mode 100644 index 0000000000..61b554428b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-female.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females-alt.svg new file mode 100644 index 0000000000..e4813ece0b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females.svg new file mode 100644 index 0000000000..b4f9776fa5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-glasses.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-glasses.svg new file mode 100644 index 0000000000..3816df4ce6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-glasses.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user.svg new file mode 100644 index 0000000000..9f46a9853d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-users-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-users-alt.svg new file mode 100644 index 0000000000..6d87232e4d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-users-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-users.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-users.svg new file mode 100644 index 0000000000..65f0703bcc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-users.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-utilities.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-utilities.svg new file mode 100644 index 0000000000..5181d06074 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-utilities.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-vcard.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-vcard.svg new file mode 100644 index 0000000000..485275849a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-vcard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-video.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-video.svg new file mode 100644 index 0000000000..48cb996cae --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-video.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-voice.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-voice.svg new file mode 100644 index 0000000000..786dc7572c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-voice.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wall-plug.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wall-plug.svg new file mode 100644 index 0000000000..d7d6d12e26 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wall-plug.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wallet.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wallet.svg new file mode 100644 index 0000000000..36506ede4a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wallet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wand.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wand.svg new file mode 100644 index 0000000000..beeffe5d4e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wand.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-war.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-war.svg new file mode 100644 index 0000000000..ae01d407d2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-war.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-weight.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-weight.svg new file mode 100644 index 0000000000..cd5f49fbb8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-weight.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-width.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-width.svg new file mode 100644 index 0000000000..77864d37b5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-width.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wifi.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wifi.svg new file mode 100644 index 0000000000..0118ed13b1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wifi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-popin.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-popin.svg new file mode 100644 index 0000000000..aec2173f09 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-popin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-sizes.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-sizes.svg new file mode 100644 index 0000000000..26af884833 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-sizes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-windows.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-windows.svg new file mode 100644 index 0000000000..3e00719e9e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-windows.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wine-glass.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wine-glass.svg new file mode 100644 index 0000000000..abb0115e23 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wine-glass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrench.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrench.svg new file mode 100644 index 0000000000..96040a486e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrench.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrong.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrong.svg new file mode 100644 index 0000000000..09f0a7376d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrong.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-yen-bag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-yen-bag.svg new file mode 100644 index 0000000000..2680a40cca --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-yen-bag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zip.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zip.svg new file mode 100644 index 0000000000..2691f1c586 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zom-out.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zom-out.svg new file mode 100644 index 0000000000..8afc74de61 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zom-out.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zoom-in.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zoom-in.svg new file mode 100644 index 0000000000..df7748938e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zoom-in.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbappheader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbappheader.directive.js index 8efaf0c024..b52b0a5763 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbappheader.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbappheader.directive.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function AppHeaderDirective(eventsService, appState, userService, focusService, backdropService) { + function AppHeaderDirective(eventsService, appState, userService, focusService, backdropService, overlayService) { function link(scope, el, attr, ctrl) { @@ -71,21 +71,17 @@ }; scope.avatarClick = function () { - if (!scope.userDialog) { - backdropService.open(); - scope.userDialog = { - view: "user", - show: true, - close: function (oldModel) { - scope.userDialog.show = false; - scope.userDialog = null; - backdropService.close(); - } - }; - } else { - scope.userDialog.show = false; - scope.userDialog = null; - } + + const dialog = { + view: "user", + position: "right", + name: "overlay-user", + close: function () { + overlayService.close(); + } + }; + + overlayService.open(dialog); }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsearch.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsearch.directive.js index e03e63b68f..42daf1dd75 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsearch.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsearch.directive.js @@ -160,7 +160,8 @@ searchService.searchAll(search).then(function (result) { //result is a dictionary of group Title and it's results var filtered = {}; - _.each(result, function (value, key) { + Object.keys(result).forEach(key => { + let value = result[key]; if (value.results.length > 0) { filtered[key] = value; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js index dc012945dd..5e007a7ff4 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js @@ -55,8 +55,8 @@ Use this directive to render an umbraco button. The directive can be used to gen @param {callback} action The button action which should be performed when the button is clicked. -@param {string=} href Url/Path to navigato to. -@param {string=} type Set the button type ("button" or "submit"). +@param {string=} href Url/Path to navigato to. (requires "type" to be set to "link") +@param {string=} type Set the button type ("button", "link", "submit"). @param {string=} buttonStyle Set the style of the button. The directive uses the default bootstrap styles ("primary", "info", "success", "warning", "danger", "inverse", "link", "block"). Pass in array to add multple styles [success,block]. @param {string=} state Set a progress state on the button ("init", "busy", "success", "error"). @param {string=} shortcut Set a keyboard shortcut for the button ("ctrl+c"). diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbuttonellipsis.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbuttonellipsis.directive.js new file mode 100644 index 0000000000..67b85c13b9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbuttonellipsis.directive.js @@ -0,0 +1,93 @@ +/** +@ngdoc directive +@name umbraco.directives.directive:umbButtonEllipsis +@restrict E +@scope + +@description +Added in Umbraco version 8.7.0 Use this directive to render an umbraco ellipsis. + +

Markup example

+
+    
+ + + + +
+
+ +@param {string} text Set the text for the checkbox label. +@param {string} labelKey Set a dictinary/localization string for the checkbox label +@param {callback} action Callback when the value of the checkbox change by interaction. +@param {string} cssClass Set a css class modifier +@param {string} color Set a hex code like #f5c1bc +@param {boolean} showText Set to true to show the text. false by default +@param {domElement} element Highlights a DOM-element (HTML-selector) +@param {string} state Set the initial state of the component. To have it hidden use hidden +@param {string} mode Set the mode, which decides how to style the component. "small" and "tab" are currently supported +**/ + +(function () { + 'use strict'; + + function UmbButtonEllipsis($timeout, localizationService) { + + var vm = this; + + vm.$onInit = onInit; + vm.clickButton = clickButton; + + function onInit() { + setText(); + + setColor(); + } + + function clickButton(event) { + if(vm.action) { + vm.action({$event: event}); + } + } + + function setText() { + if (vm.labelKey) { + localizationService.localize(vm.labelKey).then(function (data) { + // If a labelKey is passed let's update the returned text if it's does not contain an opening square bracket [ + if(data.indexOf('[') === -1){ + vm.text = data; + } + }); + } + } + + function setColor() { + vm.color = vm.color ? vm.color : '#000000'; + } + } + + var component = { + templateUrl: 'views/components/buttons/umb-button-ellipsis.html', + controller: UmbButtonEllipsis, + controllerAs: 'vm', + transclude: true, + bindings: { + text: "@", + labelKey: "@?", + action: "&", + cssClass: "@?", + color: "@?", + showText: " { if ((vm.culture === "invariant" || v.language && v.language.culture === vm.culture) && v.segment === vm.segment) { activeVariant = v; } }); + if (!activeVariant) { // Set the first variant to active if we can't find it. // If the content item is invariant, then only one item exists in the array. @@ -103,13 +105,16 @@ //now re-sync any other editor content (i.e. if split view is open) for (var s = 1; s < vm.editors.length; s++) { //get the variant from the scope model - var variant = _.find(vm.content.variants, function (v) { - return (!v.language || v.language.culture === vm.editors[s].content.language.culture) && v.segment === vm.editors[s].content.segment; - }); + var variant = vm.content.variants.find(v => + (!v.language || v.language.culture === vm.editors[s].content.language.culture) && v.segment === vm.editors[s].content.segment); + vm.editors[s].content = variant; } } - + + if (vm.content.variants.length > 1) { + eventsService.emit('editors.content.cultureChanged', activeVariant.language); + } } /** @@ -160,32 +165,30 @@ */ function openSplitView(selectedVariant) { // enforce content contentApp in splitview. - var contentApp = vm.content.apps.find((app) => app.alias === "umbContent"); + var contentApp = vm.content.apps.find(app => app.alias === "umbContent"); if(contentApp) { selectApp(contentApp); } insertVariantEditor(vm.editors.length, selectedVariant); - splitViewChanged(); - + splitViewChanged(); } - - $scope.$on("editors.content.splitViewRequest", function(event, args) {requestSplitView(args);}); - vm.requestSplitView = requestSplitView; + function requestSplitView(args) { var culture = args.culture; var segment = args.segment; - var variant = _.find(vm.content.variants, function (v) { - return (!v.language || v.language.culture === culture) && v.segment === segment; - }); + var variant = vm.content.variants.find(v => + (!v.language || v.language.culture === culture) && v.segment === segment); if (variant != null) { openSplitView(variant); } } + eventsService.on("editors.content.splitViewRequest", (_, args) => requestSplitView(args)); + /** Closes the split view */ function closeSplitView(editorIndex) { // TODO: hacking animation states - these should hopefully be easier to do when we upgrade angular @@ -194,8 +197,9 @@ editor.content.active = false; //update the current culture to reflect the last open variant (closing the split view corresponds to selecting the other variant) - - $location.search({"cculture": vm.editors[0].content.language ? vm.editors[0].content.language.culture : null, "csegment": vm.editors[0].content.segment}); + const culture = vm.editors[0].content.language ? vm.editors[0].content.language.culture : null; + + $location.search({"cculture": culture, "csegment": vm.editors[0].content.segment}); splitViewChanged(); } @@ -222,11 +226,9 @@ $location.search("cculture", variantCulture).search("csegment", variantSegment); } else { - //update the editors collection - insertVariantEditor(editorIndex, variant); - - } + insertVariantEditor(editorIndex, variant); + } } /** @@ -244,7 +246,6 @@ vm.onSelectAppAnchor({"app": app, "anchor": anchor}); } } - function getScope() { return $scope; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js index 389aec2044..717cefbb0a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js @@ -31,8 +31,10 @@ @param {boolean} disabled Set the checkbox to be disabled. @param {boolean} required Set the checkbox to be required. @param {callback} onChange Callback when the value of the checkbox change by interaction. -@param {string} cssClass Set a css class modifier -@param {boolean} disableDirtyCheck Disable checking if the model is dirty +@param {string} cssClass Set a css class modifier. +@deprecated @param {string} iconClass Set an icon next to checkbox. Use "icon" parameter instead. +@param {string} icon Set an icon next to checkbox. +@param {boolean} disableDirtyCheck Disable checking if the model is dirty. **/ @@ -49,6 +51,8 @@ function onInit() { vm.inputId = vm.inputId || "umb-check_" + String.CreateGuid(); + vm.icon = vm.icon || vm.iconClass || null; + // If a labelKey is passed let's update the returned text if it's does not contain an opening square bracket [ if (vm.labelKey) { localizationService.localize(vm.labelKey).then(function (data) { @@ -85,7 +89,8 @@ required: "<", onChange: "&?", cssClass: "@?", - iconClass: "@?", + iconClass: "@?", // deprecated + icon: "@?", disableDirtyCheck: "=?" } }; 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 new file mode 100644 index 0000000000..569f49b88a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbfocuslock.directive.js @@ -0,0 +1,82 @@ +(function() { + 'use strict'; + + function FocusLock($timeout) { + + function getAutoFocusElement (elements) { + var elmentWithAutoFocus = null; + + elements.forEach((element) => { + if(element.getAttribute('umb-auto-focus') === 'true') { + elmentWithAutoFocus = element; + } + }); + + return elmentWithAutoFocus; + } + + function link(scope, element) { + + function onInit() { + // List of elements that can be focusable within the focus lock + var focusableElementsSelector = 'a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled])'; + var bodyElement = document.querySelector('body'); + + $timeout(function() { + var target = element[0]; + + var focusableElements = target.querySelectorAll(focusableElementsSelector); + 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 ){ + firstFocusableElement.focus(); + } + + target.addEventListener('keydown', function(event){ + var isTabPressed = (event.key === 'Tab' || event.keyCode === 9); + + if (!isTabPressed){ + return; + } + + // If shift + tab key + if(event.shiftKey){ + // Set focus on the last focusable element if shift+tab are pressed meaning we go backwards + if(document.activeElement === firstFocusableElement){ + lastFocusableElement.focus(); + event.preventDefault(); + } + } + // Else only the tab key is pressed + else{ + // Using only the tab key we set focus on the first focusable element mening we go forward + if (document.activeElement === lastFocusableElement) { + firstFocusableElement.focus(); + event.preventDefault(); + } + } + }); + }, 250); + } + + onInit(); + } + + var directive = { + restrict: 'A', + link: link + }; + + return directive; + } + + angular.module('umbraco.directives').directive('umbFocusLock', FocusLock); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js index d79140f947..3232ed7f34 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js @@ -26,10 +26,14 @@ @param {string} value Set the value of the radiobutton. @param {string} name Set the name of the radiobutton. @param {string} text Set the text for the radiobutton label. -@param {string} labelKey Set a dictinary/localization string for the checkbox label +@param {string} labelKey Set a dictinary/localization string for the checkbox label. +@param {string} serverValidationField Set the val-server-field of the radiobutton. @param {boolean} disabled Set the radiobutton to be disabled. @param {boolean} required Set the radiobutton to be required. @param {callback} onChange Callback when the value of the radiobutton change by interaction. +@param {string} cssClass Set a css class modifier. +@param {string} iconClass Set an icon next to radiobutton. +@param {boolean} disableDirtyCheck Disable checking if the model is dirty. **/ @@ -46,6 +50,8 @@ function onInit() { vm.inputId = vm.inputId || "umb-radio_" + String.CreateGuid(); + vm.icon = vm.icon || vm.iconClass || null; + // If a labelKey is passed let's update the returned text if it's does not contain an opening square bracket [ if (vm.labelKey) { localizationService.localize(vm.labelKey).then(function (data) { @@ -77,9 +83,14 @@ name: "@", text: "@", labelKey: "@?", + serverValidationField: "@", disabled: "<", required: "<", - onChange: "&?" + onChange: "&?", + cssClass: "@?", + iconClass: "@?", // deprecated + icon: "@?", + disableDirtyCheck: "=?" } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbsearchfilter.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbsearchfilter.directive.js new file mode 100644 index 0000000000..7929316275 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbsearchfilter.directive.js @@ -0,0 +1,84 @@ +/** +@ngdoc directive +@name umbraco.directives.directive:umbSearchFilter +@restrict E +@scope + +@description +Added in Umbraco version 8.7.0 Use this directive to render an umbraco search filter. + +

Markup example

+
+    
+ + + + +
+
+ +@param {boolean} model Set to true or false to set the checkbox to checked or unchecked. +@param {string} inputId Set the id of the checkbox. +@param {string} text Set the text for the checkbox label. +@param {string} labelKey Set a dictinary/localization string for the checkbox label +@param {callback} onChange Callback when the value of the checkbox change by interaction. +@param {boolean} autoFocus Add autofocus to the input field +@param {boolean} preventSubmitOnEnter Set the enter prevent directive or not + +**/ + +(function () { + 'use strict'; + + function UmbSearchFilterController($timeout, localizationService) { + + var vm = this; + + vm.$onInit = onInit; + vm.change = change; + + function onInit() { + vm.inputId = vm.inputId || "umb-check_" + String.CreateGuid(); + + // If a labelKey is passed let's update the returned text if it's does not contain an opening square bracket [ + if (vm.labelKey) { + localizationService.localize(vm.labelKey).then(function (data) { + if(data.indexOf('[') === -1){ + vm.text = data; + } + }); + } + } + + function change() { + if (vm.onChange) { + $timeout(function () { + vm.onChange({ model: vm.model, value: vm.value }); + }, 0); + } + } + } + + var component = { + templateUrl: 'views/components/forms/umb-search-filter.html', + controller: UmbSearchFilterController, + controllerAs: 'vm', + transclude: true, + bindings: { + model: "=", + inputId: "@", + text: "@", + labelKey: "@?", + onChange: "&?", + autoFocus: " constraints.left.max) - { - left = constraints.left.max; - } + var validatePosition = function (left, top) { + if (left > constraints.left.max) { + left = constraints.left.max; + } - if(left <= constraints.left.min){ - left = constraints.left.min; - } + if (left <= constraints.left.min) { + left = constraints.left.min; + } - if(top > constraints.top.max) - { - top = constraints.top.max; - } - if(top <= constraints.top.min){ - top = constraints.top.min; - } + if (top > constraints.top.max) { + top = constraints.top.max; + } + if (top <= constraints.top.min) { + top = constraints.top.min; + } - if(scope.dimensions.image.left !== left){ - scope.dimensions.image.left = left; - } + if (scope.dimensions.image.left !== left) { + scope.dimensions.image.left = left; + } - if(scope.dimensions.image.top !== top){ - scope.dimensions.image.top = top; - } - }; + if (scope.dimensions.image.top !== top) { + scope.dimensions.image.top = top; + } + }; - //sets scope.crop to the recalculated % based crop - var calculateCropBox = function(){ - scope.crop = cropperHelper.pixelsToCoordinates(scope.dimensions.image, scope.dimensions.cropper.width, scope.dimensions.cropper.height, scope.dimensions.margin); - }; + //sets scope.crop to the recalculated % based crop + var calculateCropBox = function () { + scope.crop = cropperHelper.pixelsToCoordinates(scope.dimensions.image, scope.dimensions.cropper.width, scope.dimensions.cropper.height, scope.dimensions.margin); + }; - //Drag and drop positioning, using jquery ui draggable - var onStartDragPosition, top, left; - $overlay.draggable({ - drag: function(event, ui) { - scope.$apply(function(){ - validatePosition(ui.position.left, ui.position.top); - }); - }, - stop: function(event, ui){ - scope.$apply(function(){ - //make sure that every validates one more time... - validatePosition(ui.position.left, ui.position.top); + //Drag and drop positioning, using jquery ui draggable + var onStartDragPosition, top, left; + $overlay.draggable({ + drag: function (event, ui) { + scope.$apply(function () { + validatePosition(ui.position.left, ui.position.top); + }); + }, + stop: function (event, ui) { + scope.$apply(function () { + //make sure that every validates one more time... + validatePosition(ui.position.left, ui.position.top); - calculateCropBox(); - scope.dimensions.image.rnd = Math.random(); - }); - } - }); + calculateCropBox(); + scope.dimensions.image.rnd = Math.random(); + }); + } + }); - var init = function(image){ - scope.loaded = false; + var init = function (image) { + scope.loaded = false; - //set dimensions on image, viewport, cropper etc - setDimensions(image); + //set dimensions on image, viewport, cropper etc + setDimensions(image); - //create a default crop if we haven't got one already + //create a default crop if we haven't got one already var createDefaultCrop = !scope.crop; if (createDefaultCrop) { calculateCropBox(); } - resizeImageToCrop(); + resizeImageToCrop(); //if we're creating a new crop, make sure to zoom out fully if (createDefaultCrop) { scope.dimensions.scale.current = scope.dimensions.scale.min; - resizeImageToScale(scope.dimensions.scale.min); + resizeImageToScale(scope.dimensions.scale.min); + + if (scope.center) { + // Move image to focal point if set + // Repeating a few calls here, but logic is too difficult to follow elsewhere + var x1 = Math.min( + Math.max( + scope.center.left * scope.dimensions.image.width - scope.dimensions.cropper.width / 2, + 0 + ), + scope.dimensions.image.width - scope.dimensions.cropper.width + ); + var y1 = Math.min( + Math.max( + scope.center.top * scope.dimensions.image.height - scope.dimensions.cropper.height / 2, + 0 + ), + scope.dimensions.image.height - scope.dimensions.cropper.height + ); + scope.dimensions.image.left = x1; + scope.dimensions.image.top = y1; + calculateCropBox(); + resizeImageToCrop(); + } } - //sets constaints for the cropper - setConstraints(); - scope.loaded = true; - }; + //sets constaints for the cropper + setConstraints(); + scope.loaded = true; + }; - // Watchers - scope.$watchCollection('[width, height]', function(newValues, oldValues){ - // We have to reinit the whole thing if - // one of the external params changes - if(newValues !== oldValues){ - setDimensions($image); - setConstraints(); - } - }); + // Watchers + scope.$watchCollection('[width, height]', function (newValues, oldValues) { + // We have to reinit the whole thing if + // one of the external params changes + if (newValues !== oldValues) { + setDimensions($image); + setConstraints(); + } + }); - var throttledResizing = _.throttle(function(){ + var throttledResizing = _.throttle(function () { resizeImageToScale(scope.dimensions.scale.current); - calculateCropBox(); - }, 15); + calculateCropBox(); + }, 15); - // Happens when we change the scale + // Happens when we change the scale scope.$watch("dimensions.scale.current", function (newValue, oldValue) { - if (scope.loaded) { - throttledResizing(); - } - }); + if (scope.loaded) { + throttledResizing(); + } + }); - // Init - $image.on("load", function(){ - $timeout(function(){ - init($image); - }); - }); - } - }; - }); + // Init + $image.on("load", function () { + $timeout(function () { + init($image); + }); + }); + } + }; + }); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js index dfa1afc247..6f34cfc0a1 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js @@ -1,7 +1,7 @@ (function () { 'use strict'; - function MediaNodeInfoDirective($timeout, $location, eventsService, userService, dateHelper, editorService, mediaHelper, mediaResource, $q) { + function MediaNodeInfoDirective($timeout, $location, $q, eventsService, userService, dateHelper, editorService, mediaHelper, mediaResource) { function link(scope, element, attrs, ctrl) { @@ -37,7 +37,7 @@ }); }); - // get document type details + // get media type details scope.mediaType = scope.node.contentType; // set the media link initially diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/member/umbmembernodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/member/umbmembernodeinfo.directive.js index 3b6a2c069a..8dd6d56139 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/member/umbmembernodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/member/umbmembernodeinfo.directive.js @@ -11,6 +11,19 @@ scope.allowChangeMemberType = false; function onInit() { + + userService.getCurrentUser().then(function (user) { + // only allow change of member type if user has access to the settings sections + Utilities.forEach(user.sections, function (section) { + if (section.alias === "settings") { + scope.allowChangeMemberType = true; + } + }); + }); + + // get member type details + scope.memberType = scope.node.contentType; + // make sure dates are formatted to the user's locale formatDatesToLocal(); } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js index d1bdf6f42f..f7ba043ef1 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js @@ -221,6 +221,10 @@ Opens an overlay to show a custom YSOD.
$timeout(function () { + if (!scope.name) { + scope.name = 'overlay'; + } + if (scope.position === "target" && scope.model.event) { setTargetPosition(); @@ -403,11 +407,15 @@ Opens an overlay to show a custom YSOD.
function setTargetPosition() { - var container = $("#contentwrapper"); - var containerLeft = container[0].offsetLeft; - var containerRight = containerLeft + container[0].offsetWidth; - var containerTop = container[0].offsetTop; - var containerBottom = containerTop + container[0].offsetHeight; + var overlay = $(scope.model.event.target).closest('.umb-overlay'); + var container = overlay.length > 0 ? overlay : $("#contentwrapper"); + + let rect = container[0].getBoundingClientRect(); + + var containerLeft = rect.left; + var containerRight = containerLeft + rect.width; + var containerTop = rect.top; + var containerBottom = containerTop + rect.height; var mousePositionClickX = null; var mousePositionClickY = null; @@ -430,8 +438,9 @@ Opens an overlay to show a custom YSOD.
elementWidth = el[0].clientWidth; // move element to this position - position.left = mousePositionClickX - (elementWidth / 2); - position.top = mousePositionClickY - (elementHeight / 2); + // when using hotkey it fallback to center of container + position.left = mousePositionClickX ? mousePositionClickX - (elementWidth / 2) : (containerLeft + containerRight) / 2 - (elementWidth / 2); + position.top = mousePositionClickY ? mousePositionClickY - (elementHeight / 2) : (containerTop + containerBottom) / 2 - (elementHeight / 2); // check to see if element is outside screen // outside right @@ -459,6 +468,7 @@ Opens an overlay to show a custom YSOD.
} el.css(position); + el.css("visibility", "visible"); } scope.submitForm = function (model) { @@ -530,6 +540,7 @@ Opens an overlay to show a custom YSOD.
view: "=", position: "@", size: "=?", + name: "=?", parentScope: "=?" }, link: link diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js index 0ccaf7b05c..a412f73c5a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js @@ -88,9 +88,8 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use /** Helper function to emit tree events */ function emitEvent(eventName, args) { if (registeredCallbacks[eventName] && Utilities.isArray(registeredCallbacks[eventName])) { - _.each(registeredCallbacks[eventName], function (c) { - c(args);//call it - }); + // call it + registeredCallbacks[eventName].forEach(c => c(args)); } } @@ -342,26 +341,17 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use var css = []; if (node.cssClasses) { - _.each(node.cssClasses, function (c) { - css.push(c); - }); + node.cssClasses.forEach(c => css.push(c)); } return css.join(" "); }; - $scope.selectEnabledNodeClass = function (node) { - return node ? - node.selected ? - 'icon umb-tree-icon sprTree icon-check green temporary' : - '' : - ''; - }; + $scope.selectEnabledNodeClass = node => + node && node.selected ? 'icon umb-tree-icon sprTree icon-check green temporary' : ''; /* helper to force reloading children of a tree node */ - $scope.loadChildren = function (node, forceReload) { - return loadChildren(node, forceReload); - }; + $scope.loadChildren = (node, forceReload) => loadChildren(node, forceReload); /** Method called when the options button next to the root node is called. diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js index 8767de446a..f2fc0d2dae 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js @@ -70,9 +70,7 @@ angular.module("umbraco.directives") var css = []; if (node.cssClasses) { - _.each(node.cssClasses, function(c) { - css.push(c); - }); + node.cssClasses.forEach(c => css.push(c)); } if (node.selected) { css.push("umb-tree-node-checked"); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js index 96ce8735eb..9a841e3e4a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js @@ -21,14 +21,6 @@ Use this directive to render a ui component for selecting child items to a paren on-remove="vm.removeChild"> - - - - @@ -37,7 +29,7 @@ Use this directive to render a ui component for selecting child items to a paren (function () { "use strict"; - function Controller() { + function Controller(overlayService) { var vm = this; @@ -64,23 +56,29 @@ Use this directive to render a ui component for selecting child items to a paren vm.removeChild = removeChild; function addChild($event) { - vm.overlay = { + + const dialog = { view: "itempicker", title: "Choose child", availableItems: vm.availableChildren, selectedItems: vm.selectedChildren, event: $event, - show: true, submit: function(model) { - - // add selected child - vm.selectedChildren.push(model.selectedItem); + + if (model.selectedItem) { + // add selected child + vm.selectedChildren.push(model.selectedItem); + } // close overlay - vm.overlay.show = false; - vm.overlay = null; + overlayService.close(); + }, + close: function() { + overlayService.close(); } }; + + overlayService.open(dialog); } function removeChild($index) { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbconfirmaction.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbconfirmaction.directive.js index 1dcccda481..2f682205ad 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbconfirmaction.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbconfirmaction.directive.js @@ -14,10 +14,10 @@ The prompt can be opened in four direction up, down, left or right.

- @@ -71,17 +71,23 @@ The prompt can be opened in four direction up, down, left or right.

function link(scope, el, attr, ctrl) { - scope.clickConfirm = function() { - if(scope.onConfirm) { - scope.onConfirm(); - } - }; + scope.clickButton = function (event) { + if(scope.onDelete) { + scope.onDelete({$event: event}); + } + } - scope.clickCancel = function() { - if(scope.onCancel) { - scope.onCancel(); - } - }; + scope.clickConfirm = function() { + if(scope.onConfirm) { + scope.onConfirm(); + } + }; + + scope.clickCancel = function() { + if(scope.onCancel) { + scope.onCancel(); + } + }; } @@ -91,6 +97,8 @@ The prompt can be opened in four direction up, down, left or right.

templateUrl: 'views/components/umb-confirm-action.html', scope: { direction: "@", + show: "<", + onDelete: "&?", onConfirm: "&", onCancel: "&" }, diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js index 0498b81963..ed9c011d72 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js @@ -189,7 +189,7 @@ Use this directive to render a date time picker }; } - // bind hook for onOpen + // bind hook for onOpen if (ctrl.options && ctrl.onClose) { ctrl.options.onClose = function (selectedDates, dateStr, instance) { $timeout(function () { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js index 3f53a1e18c..92d2df43e5 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js @@ -161,19 +161,17 @@ var resourceLookup = scope.contentType === "documentType" ? contentTypeResource.getAvailableCompositeContentTypes : mediaTypeResource.getAvailableCompositeContentTypes; return resourceLookup(scope.model.id, selectedContentTypeAliases, propAliasesExisting).then(function (filteredAvailableCompositeTypes) { - _.each(scope.compositionsDialogModel.availableCompositeContentTypes, function (current) { + scope.compositionsDialogModel.availableCompositeContentTypes.forEach(current => { //reset first current.allowed = true; //see if this list item is found in the response (allowed) list - var found = _.find(filteredAvailableCompositeTypes, function (f) { - return current.contentType.alias === f.contentType.alias; - }); + var found = filteredAvailableCompositeTypes.find(f => current.contentType.alias === f.contentType.alias); //allow if the item was found in the response (allowed) list - // and ensure its set to allowed if it is currently checked, // DO not allow if it's a locked content type. - current.allowed = scope.model.lockedCompositeContentTypes.indexOf(current.contentType.alias) === -1 && - (selectedContentTypeAliases.indexOf(current.contentType.alias) !== -1) || ((found !== null && found !== undefined) ? found.allowed : false); + current.allowed = scope.model.lockedCompositeContentTypes.includes(current.contentType.alias) && + (selectedContentTypeAliases.includes(current.contentType.alias)) || (found ? found.allowed : false); }); }); @@ -192,15 +190,15 @@ function setupAvailableContentTypesModel(result) { scope.compositionsDialogModel.availableCompositeContentTypes = result; //iterate each one and set it up - _.each(scope.compositionsDialogModel.availableCompositeContentTypes, function (c) { + scope.compositionsDialogModel.availableCompositeContentTypes.forEach(c => { //enable it if it's part of the selected model - if (scope.compositionsDialogModel.compositeContentTypes.indexOf(c.contentType.alias) !== -1) { + if (scope.compositionsDialogModel.compositeContentTypes.includes(c.contentType.alias)) { c.allowed = true; } //set the inherited flags c.inherited = false; - if (scope.model.lockedCompositeContentTypes.indexOf(c.contentType.alias) > -1) { + if (scope.model.lockedCompositeContentTypes.includes(c.contentType.alias)) { c.inherited = true; } // convert icons for composite content types @@ -281,6 +279,8 @@ }, selectCompositeContentType: function (selectedContentType) { + var deferred = $q.defer(); + //first check if this is a new selection - we need to store this value here before any further digests/async // because after that the scope.model.compositeContentTypes will be populated with the selected value. var newSelection = scope.model.compositeContentTypes.indexOf(selectedContentType.alias) === -1; @@ -308,7 +308,10 @@ //based on the selection, we need to filter the available composite types list filterAvailableCompositions(selectedContentType, newSelection).then(function () { + deferred.resolve({ selectedContentType, newSelection }); // TODO: Here we could probably re-enable selection if we previously showed a throbber or something + }, function () { + deferred.reject(); }); }); } @@ -318,10 +321,14 @@ //based on the selection, we need to filter the available composite types list filterAvailableCompositions(selectedContentType, newSelection).then(function () { + deferred.resolve({ selectedContentType, newSelection }); // TODO: Here we could probably re-enable selection if we previously showed a throbber or something + }, function () { + deferred.reject(); }); } + return deferred.promise; } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbicon.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbicon.directive.js new file mode 100644 index 0000000000..517776388b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbicon.directive.js @@ -0,0 +1,86 @@ +/** +@ngdoc directive +@name umbraco.directives.directive:umbIcon +@restrict E +@scope +@description +Use this directive to show an render an umbraco backoffice svg icon. All svg icons used by this directive should use the following naming convention to keep things consistent: icon-[name of icon]. For example
icon-alert.svg
+ +

Markup example

+ +Simple icon +
+    
+
+ +Icon with additional attribute. It can be treated like any other dom element +
+    
+
+ +Manual svg string +This format is only used in the iconpicker.html +
+    
+    
+
+@example + **/ + +(function () { + "use strict"; + + function UmbIconDirective(iconHelper) { + + var directive = { + replace: true, + transclude: true, + templateUrl: "views/components/umb-icon.html", + scope: { + icon: "@", + svgString: "=?" + }, + + link: function (scope) { + + if (scope.svgString === undefined && scope.svgString !== null && scope.icon !== undefined && scope.icon !== null) { + var icon = scope.icon.split(" ")[0]; // Ensure that only the first part of the icon is used as sometimes the color is added too, e.g. see umbeditorheader.directive scope.openIconPicker + + _requestIcon(icon); + } + scope.$watch("icon", function (newValue, oldValue) { + if (newValue && oldValue) { + var newicon = newValue.split(" ")[0]; + var oldicon = oldValue.split(" ")[0]; + + if (newicon !== oldicon) { + _requestIcon(newicon); + } + } + }); + + function _requestIcon(icon) { + // Reset svg string before requesting new icon. + scope.svgString = null; + + iconHelper.getIcon(icon) + .then(data => { + if (data !== null && data.svgString !== undefined) { + // Watch source SVG string + //icon.svgString.$$unwrapTrustedValue(); + scope.svgString = data.svgString; + } + }); + } + } + + }; + + return directive; + } + + angular.module("umbraco.directives").directive("umbIcon", UmbIconDirective); + +})(); 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 aa28d49c4a..241f1e80e8 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 @@ -322,6 +322,41 @@ Use this directive to generate a thumbnail grid of media items. scope.$on('$destroy', function() { unbindItemsWatcher(); }); + //determine if sort is current + scope.sortColumn = "name"; + scope.sortReverse = false; + scope.sortDirection = "asc"; + //check sort status + scope.isSortDirection = function (col, direction) { + return col === scope.sortColumn && direction === scope.sortDirection; + }; + //change sort + scope.setSort = function (col) { + if (scope.sortColumn === col) { + scope.sortReverse = !scope.sortReverse; + } + else { + scope.sortColumn = col; + if (col === "updateDate") { + scope.sortReverse = true; + } + else { + scope.sortReverse = false; + } + } + scope.sortDirection = scope.sortReverse ? "desc" : "asc"; + + } + // sort function + scope.sortBy = function (item) { + if (scope.sortColumn === "updateDate") { + return [-item['isFolder'],item['updateDate']]; + } + else { + return [-item['isFolder'],item['name']]; + } + }; + } @@ -345,7 +380,8 @@ Use this directive to generate a thumbnail grid of media items. onlyImages: "@", onlyFolders: "@", includeSubFolders: "@", - currentFolderId: "@" + currentFolderId: "@", + showMediaList: "=" }, link: link }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbminilistview.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbminilistview.directive.js index 66e03a7302..3865ffcdae 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbminilistview.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbminilistview.directive.js @@ -63,7 +63,7 @@ } // update children miniListView.children = data.items; - _.each(miniListView.children, function(c) { + miniListView.children.forEach(c => { // child allowed by default c.allowed = true; @@ -95,7 +95,8 @@ var filtered = angular.isFunction(scope.entityTypeFilter.filter) ? _.filter(miniListView.children, scope.entityTypeFilter.filter) : _.where(miniListView.children, scope.entityTypeFilter.filter); - _.each(filtered, (node) => node.allowed = false); + + filtered.forEach(node => node.allowed = false); } // update pagination diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js index ef7006be2c..ce1885a7cf 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js @@ -77,13 +77,17 @@ Use this directive to render a tooltip. scope.tooltipStyles.left = 0; scope.tooltipStyles.top = 0; - function setTooltipPosition(event) { + function setTooltipPosition(event) { - var container = $("#contentwrapper"); - var containerLeft = container[0].offsetLeft; - var containerRight = containerLeft + container[0].offsetWidth; - var containerTop = container[0].offsetTop; - var containerBottom = containerTop + container[0].offsetHeight; + var overlay = $(event.target).closest('.umb-overlay'); + var container = overlay.length > 0 ? overlay : $("#contentwrapper"); + + let rect = container[0].getBoundingClientRect(); + + var containerLeft = rect.left; + var containerRight = containerLeft + rect.width; + var containerTop = rect.top; + var containerBottom = containerTop + rect.height; var elementHeight = null; var elementWidth = null; @@ -102,39 +106,43 @@ Use this directive to render a tooltip. position.left = event.pageX - (elementWidth / 2); position.top = event.pageY; - // check to see if element is outside screen - // outside right - if (position.left + elementWidth > containerRight) { - position.right = 10; - position.left = "inherit"; + if (overlay.length > 0) { + position.left = event.pageX - rect.left - (elementWidth / 2); + position.top = event.pageY - rect.top; } + else { + // check to see if element is outside screen + // outside right + if (position.left + elementWidth > containerRight) { + position.right = 10; + position.left = "inherit"; + } - // outside bottom - if (position.top + elementHeight > containerBottom) { - position.bottom = 10; - position.top = "inherit"; - } + // outside bottom + if (position.top + elementHeight > containerBottom) { + position.bottom = 10; + position.top = "inherit"; + } - // outside left - if (position.left < containerLeft) { - position.left = containerLeft + 10; - position.right = "inherit"; - } + // outside left + if (position.left < containerLeft) { + position.left = containerLeft + 10; + position.right = "inherit"; + } - // outside top - if (position.top < containerTop) { - position.top = 10; - position.bottom = "inherit"; + // outside top + if (position.top < containerTop) { + position.top = 10; + position.bottom = "inherit"; + } } scope.tooltipStyles = position; el.css(position); - } setTooltipPosition(scope.event); - } var directive = { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js index 6a8ffa7969..3581aed9e0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js @@ -19,6 +19,17 @@ function umbFileUpload() { //clear the element value - this allows us to pick the same file again and again el.val(''); }); + + el.on('drag dragstart dragend dragover dragenter dragleave drop', function (e) { + e.preventDefault(); + e.stopPropagation(); + }) + .on('dragover dragenter', function () { + scope.$emit("isDragover", { value: true }); + }) + .on('dragleave dragend drop', function () { + scope.$emit("isDragover", { value: false }); + }); } }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js index 653b4f427c..db1e38adc6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js @@ -78,6 +78,8 @@ /** Called when the component initializes */ function onInit() { $scope.$on("filesSelected", onFilesSelected); + $scope.$on("isDragover", isDragover); + initialize(); } @@ -118,7 +120,9 @@ isImage: mediaHelper.detectIfImageByExtension(file), extension: getExtension(file) }; + f.fileSrc = getThumbnail(f); + return f; }); @@ -228,19 +232,22 @@ var index = i; //capture var isImage = mediaHelper.detectIfImageByExtension(files[i].name); + var extension = getExtension(files[i].name); - //save the file object to the files collection - vm.files.push({ + var f = { isImage: isImage, - extension: getExtension(files[i].name), + extension: extension, fileName: files[i].name, isClientSide: true - }); + }; + + // Save the file object to the files collection + vm.files.push(f); //special check for a comma in the name newVal += files[i].name.split(',').join('-') + ","; - if (isImage) { + if (isImage || extension === "svg") { var deferred = $q.defer(); @@ -293,6 +300,11 @@ } } + function isDragover(e, args) { + vm.dragover = args.value; + angularHelper.safeApply($scope); + } + }; var umbPropertyFileUploadComponent = { @@ -303,6 +315,7 @@ propertyAlias: "@", value: "<", hideSelection: "<", + dragover: "<", /** * Called when a file is selected on this instance */ diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js index 77c26e066e..c7894da171 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js @@ -204,7 +204,7 @@ function valFormManager(serverValidationManager, $rootScope, $timeout, $location var parts = nextPath.split("?"); var query = {}; if (parts.length > 1) { - _.each(parts[1].split("&"), function (q) { + parts[1].split("&").forEach(q => { var keyVal = q.split("="); query[keyVal[0]] = keyVal[1]; }); diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.mocks.js index 3b58c127a7..aeb6229360 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.mocks.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.mocks.js @@ -8,12 +8,12 @@ angular.module('umbraco.mocks'). } function returnNodebyIds(status, data, headers) { - var ids = mocksUtils.getParameterByName(data, "ids") || "1234,1234,4234"; + var ids = mocksUtils.getParameterByName(data, "ids") || ['1234','1234','4234']; var items = []; - _.each(ids, function(id){ - items.push(_getNode( parseInt( id, 10 )) ); - }); + for (var i = 0; i < ids.length; i += 1) { + items.push(_getNode(parseInt(ids[i], 10))); + } return [200, items, null]; } @@ -26,8 +26,6 @@ angular.module('umbraco.mocks'). var id = mocksUtils.getParameterByName(data, "id") || 1234; id = parseInt(id, 10); - - return [200, _getNode(id), null]; } diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js b/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js index da6f78a6a5..868bc4c6d5 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js @@ -19,7 +19,8 @@ Umbraco.Sys.ServerVariables = { "dashboardApiBaseUrl": "/umbraco/UmbracoApi/Dashboard/", "updateCheckApiBaseUrl": "/umbraco/Api/UpdateCheck/", "relationApiBaseUrl": "/umbraco/UmbracoApi/Relation/", - "rteApiBaseUrl": "/umbraco/UmbracoApi/RichTextPreValue/" + "rteApiBaseUrl": "/umbraco/UmbracoApi/RichTextPreValue/", + "iconApiBaseUrl": "/umbraco/UmbracoApi/Icon/" }, umbracoSettings: { "umbracoPath": "/umbraco", 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 4ca85f44e6..3dfbeade4f 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 @@ -442,9 +442,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { getByIds: function (ids) { var idQuery = ""; - _.each(ids, function (item) { - idQuery += "ids=" + item + "&"; - }); + ids.forEach(id => idQuery += `ids=${id}&`); return umbRequestHelper.resourcePromise( $http.get( @@ -455,9 +453,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { 'Failed to retrieve data for content with multiple ids') .then(function (result) { //each item needs to be re-formatted - _.each(result, function (r) { - umbDataFormatter.formatContentGetData(r) - }); + result.forEach(r => umbDataFormatter.formatContentGetData(r)); return $q.when(result); }); }, 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 e24f4786eb..06eb2ed4d2 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 @@ -226,9 +226,7 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) { getByIds: function (ids) { var idQuery = ""; - _.each(ids, function (item) { - idQuery += "ids=" + item + "&"; - }); + ids.forEach(id => idQuery += `ids=${id}&`); return umbRequestHelper.resourcePromise( $http.get( diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/membergroup.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/membergroup.resource.js index c83a31e47c..f9b9da9944 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/membergroup.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/membergroup.resource.js @@ -32,9 +32,7 @@ function memberGroupResource($q, $http, umbRequestHelper) { getByIds: function (ids) { var idQuery = ""; - _.each(ids, function (item) { - idQuery += "ids=" + item + "&"; - }); + ids.forEach(id => idQuery += `ids=${id}&`); return umbRequestHelper.resourcePromise( $http.get( diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/membertype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/membertype.resource.js index 6c15b89c0e..2314fa6d6c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/membertype.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/membertype.resource.js @@ -16,16 +16,15 @@ function memberTypeResource($q, $http, umbRequestHelper, umbDataFormatter) { } var query = ""; - _.each(filterContentTypes, function (item) { - query += "filterContentTypes=" + item + "&"; - }); + filterContentTypes.forEach(fct => query += `filterContentTypes=${fct}&`); + // if filterContentTypes array is empty we need a empty variable in the querystring otherwise the service returns a error if (filterContentTypes.length === 0) { query += "filterContentTypes=&"; } - _.each(filterPropertyTypes, function (item) { - query += "filterPropertyTypes=" + item + "&"; - }); + + filterPropertyTypes.forEach(fpt => query += `filterPropertyTypes=${fpt}&`); + // if filterPropertyTypes array is empty we need a empty variable in the querystring otherwise the service returns a error if (filterPropertyTypes.length === 0) { query += "filterPropertyTypes=&"; diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js index 2b9e0c0fd5..91f00a36e3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js @@ -295,6 +295,38 @@ "Failed to retrieve data for user " + userId); } + + /** + * @ngdoc method + * @name umbraco.resources.usersResource#getUsers + * @methodOf umbraco.resources.usersResource + * + * @description + * Gets users from ids + * + * ##usage + *
+          * usersResource.getUsers([1,2,3])
+          *    .then(function(data) {
+          *        alert("It's here");
+          *    });
+          * 
+ * + * @param {Array} userIds user ids. + * @returns {Promise} resourcePromise object containing the users array. + * + */ + function getUsers(userIds) { + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "userApiBaseUrl", + "GetByIds", + { ids: userIds })), + "Failed to retrieve data for users " + userIds); + } + /** * @ngdoc method * @name umbraco.resources.usersResource#createUser @@ -481,6 +513,7 @@ setUserGroupsOnUsers: setUserGroupsOnUsers, getPagedResults: getPagedResults, getUser: getUser, + getUsers: getUsers, createUser: createUser, inviteUser: inviteUser, saveUser: saveUser, diff --git a/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js b/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js index 30e59e9a88..b474b66174 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js @@ -276,7 +276,7 @@ angular.module('umbraco.services') //blocking var promises = []; var assets = []; - _.each(nonEmpty, function (path) { + nonEmpty.forEach(path => { path = convertVirtualPath(path); var asset = service._getAssetPromise(path); //if not previously loaded, add to list of promises @@ -325,19 +325,17 @@ angular.module('umbraco.services') scope = $rootScope; } angularHelper.safeApply(scope, - function () { - asset.deferred.resolve(true); - }); + () => asset.deferred.resolve(true)); } if (cssAssets.length > 0) { - var cssPaths = _.map(cssAssets, function (asset) { return appendRnd(asset.path) }); - LazyLoad.css(cssPaths, function () { _.each(cssAssets, assetLoaded); }); + var cssPaths = cssAssets.map(css => appendRnd(css.path)); + LazyLoad.css(cssPaths, () => cssAssets.forEach(assetLoaded)); } if (jsAssets.length > 0) { - var jsPaths = _.map(jsAssets, function (asset) { return appendRnd(asset.path) }); - LazyLoad.js(jsPaths, function () { _.each(jsAssets, assetLoaded); }); + var jsPaths = jsAssets.map(js => appendRnd(js.path)); + LazyLoad.js(jsPaths, () => jsAssets.forEach(assetLoaded)); } return promise; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js index 4ffd0c3c0b..c27283d5ad 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js @@ -123,10 +123,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt self.handleSaveError({ showNotifications: args.showNotifications, softRedirect: args.softRedirect, - err: err, - rebindCallback: function () { - rebindCallback.apply(self, [args.content, err.data]); - } + err: err }); //update editor state to what is current 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 538bd41ce0..0f4f04c6bf 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 @@ -669,23 +669,6 @@ When building a custom infinite editor view you can use the same components as a open(editor); } - /** - * @ngdoc method - * @name umbraco.services.editorService#memberTypeEditor - * @methodOf umbraco.services.editorService - * - * @description - * Opens the member type editor in infinite editing, the submit callback returns the saved member type - * @param {Object} editor rendering options - * @param {Callback} editor.submit Submits the editor - * @param {Callback} editor.close Closes the editor - * @returns {Object} editor object - */ - function memberTypeEditor(editor) { - editor.view = "views/membertypes/edit.html"; - open(editor); - } - /** * @ngdoc method * @name umbraco.services.editorService#queryBuilder diff --git a/src/Umbraco.Web.UI.Client/src/common/services/focuslock.service.js b/src/Umbraco.Web.UI.Client/src/common/services/focuslock.service.js new file mode 100644 index 0000000000..a3dd91194e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/services/focuslock.service.js @@ -0,0 +1,26 @@ +(function () { + "use strict"; + + function focusLockService() { + var elementToInert = document.querySelector('#mainwrapper'); + + function addInertAttribute() { + elementToInert.setAttribute('inert', true); + } + + function removeInertAttribute() { + elementToInert.removeAttribute('inert'); + } + + var service = { + addInertAttribute: addInertAttribute, + removeInertAttribute: removeInertAttribute + } + + return service; + + } + + angular.module("umbraco.services").factory("focusLockService", focusLockService); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js index 5866e28b1e..d9c11770cc 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js @@ -17,10 +17,10 @@ function formHelper(angularHelper, serverValidationManager, notificationsService * @function * * @description - * Called by controllers when submitting a form - this ensures that all client validation is checked, + * Called by controllers when submitting a form - this ensures that all client validation is checked, * server validation is cleared, that the correct events execute and status messages are displayed. * This returns true if the form is valid, otherwise false if form submission cannot continue. - * + * * @param {object} args An object containing arguments for form submission */ submitForm: function (args) { @@ -33,6 +33,7 @@ function formHelper(angularHelper, serverValidationManager, notificationsService if (!args.scope) { throw "args.scope cannot be null"; } + if (!args.formCtrl) { //try to get the closest form controller currentForm = angularHelper.getRequiredCurrentForm(args.scope); @@ -44,15 +45,13 @@ function formHelper(angularHelper, serverValidationManager, notificationsService //the first thing any form must do is broadcast the formSubmitting event args.scope.$broadcast("formSubmitting", { scope: args.scope, action: args.action }); - // Some property editors need to perform an action after all property editors have reacted to the formSubmitting. - args.scope.$broadcast("formSubmittingFinalPhase", { scope: args.scope, action: args.action }); - - // Set the form state to submitted - currentForm.$setSubmitted(); + this.focusOnFirstError(currentForm); + args.scope.$broadcast("postFormSubmitting", { scope: args.scope, action: args.action }); //then check if the form is valid if (!args.skipValidation) { if (currentForm.$invalid) { + return false; } } @@ -68,6 +67,32 @@ function formHelper(angularHelper, serverValidationManager, notificationsService return true; }, + /** + * @ngdoc function + * @name umbraco.services.formHelper#focusOnFirstError + * @methodOf umbraco.services.formHelper + * @function + * + * @description + * Called by submitForm when a form has been submitted, it will fire a focus on the first found invalid umb-property it finds in the form.. + * + * @param {object} form Pass in a form object. + */ + focusOnFirstError: function(form) { + var invalidNgForms = form.$$element.find(`.umb-property ng-form.ng-invalid, .umb-property-editor ng-form.ng-invalid-required`); + var firstInvalidNgForm = invalidNgForms.first(); + + if(firstInvalidNgForm.length !== 0) { + var focusableFields = [...firstInvalidNgForm.find("umb-range-slider .noUi-handle,input,textarea,select,button")]; + if(focusableFields.length !== 0) { + var firstErrorEl = focusableFields.find(el => el.type !== "hidden" && el.hasAttribute("readonly") === false); + if(firstErrorEl.length !== 0) { + firstErrorEl.focus(); + } + } + } + }, + /** * @ngdoc function * @name umbraco.services.formHelper#submitForm @@ -76,32 +101,18 @@ function formHelper(angularHelper, serverValidationManager, notificationsService * * @description * Called by controllers when a form has been successfully submitted, this ensures the correct events are raised. - * + * * @param {object} args An object containing arguments for form submission */ resetForm: function (args) { - - var currentForm; - if (!args) { throw "args cannot be null"; } if (!args.scope) { throw "args.scope cannot be null"; } - if (!args.formCtrl) { - //try to get the closest form controller - currentForm = angularHelper.getRequiredCurrentForm(args.scope); - } - else { - currentForm = args.formCtrl; - } - // Set the form state to pristine - currentForm.$setPristine(); - currentForm.$setUntouched(); - - args.scope.$broadcast(args.hasErrors ? "formSubmittedValidationFailed" : "formSubmitted", { scope: args.scope }); + args.scope.$broadcast("formSubmitted", { scope: args.scope }); }, showNotifications: function (args) { @@ -126,7 +137,7 @@ function formHelper(angularHelper, serverValidationManager, notificationsService * @description * Needs to be called when a form submission fails, this will wire up all server validation errors in ModelState and * add the correct messages to the notifications. If a server error has occurred this will show a ysod. - * + * * @param {object} err The error object returned from the http promise */ handleError: function (err) { @@ -165,7 +176,7 @@ function formHelper(angularHelper, serverValidationManager, notificationsService * * @description * This wires up all of the server validation model state so that valServer and valServerField directives work - * + * * @param {object} err The error object returned from the http promise */ handleServerValidation: function (modelState) { diff --git a/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js index 0fa2d0df1a..0d0135fff8 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js @@ -3,7 +3,7 @@ * @name umbraco.services.iconHelper * @description A helper service for dealing with icons, mostly dealing with legacy tree icons **/ -function iconHelper($q, $timeout) { +function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) { var converter = [ { oldIcon: ".sprNew", newIcon: "add" }, @@ -85,11 +85,15 @@ function iconHelper($q, $timeout) { { oldIcon: ".sprTreeDeveloperPython", newIcon: "icon-linux" } ]; + var collectedIcons; + var imageConverter = [ {oldImage: "contour.png", newIcon: "icon-umb-contour"} ]; - var collectedIcons; + var iconCache = []; + var liveRequests = []; + var allIconsRequested = false; return { @@ -154,9 +158,110 @@ function iconHelper($q, $timeout) { return false; }, - /** Return a list of icons, optionally filter them */ + /** Converts the icon from legacy to a new one if an old one is detected */ + convertFromLegacyIcon: function (icon) { + if (this.isLegacyIcon(icon)) { + //its legacy so convert it if we can + var found = _.find(converter, function (item) { + return item.oldIcon.toLowerCase() === icon.toLowerCase(); + }); + return (found ? found.newIcon : icon); + } + return icon; + }, + + convertFromLegacyImage: function (icon) { + var found = _.find(imageConverter, function (item) { + return item.oldImage.toLowerCase() === icon.toLowerCase(); + }); + return (found ? found.newIcon : undefined); + }, + + /** If we detect that the tree node has legacy icons that can be converted, this will convert them */ + convertFromLegacyTreeNodeIcon: function (treeNode) { + if (this.isLegacyTreeNodeIcon(treeNode)) { + return this.convertFromLegacyIcon(treeNode.icon); + } + return treeNode.icon; + }, + + /** Gets a single IconModel */ + getIcon: function(iconName) { + return $q((resolve, reject) => { + var icon = this._getIconFromCache(iconName); + + if(icon !== undefined) { + resolve(icon); + } else { + var iconRequestPath = Umbraco.Sys.ServerVariables.umbracoUrls.iconApiBaseUrl + 'GetIcon?iconName=' + iconName; + + // If the current icon is being requested, wait a bit so that we don't have to make another http request and can instead get the icon from the cache. + // This is a bit rough and ready and could probably be improved used an event based system + if(liveRequests.indexOf(iconRequestPath) >= 0) { + setTimeout(() => { + resolve(this.getIcon(iconName)); + }, 10); + } else { + liveRequests.push(iconRequestPath); + // TODO - fix bug where Umbraco.Sys.ServerVariables.umbracoUrls.iconApiBaseUrl is undefinied when help icon + umbRequestHelper.resourcePromise( + $http.get(iconRequestPath) + ,'Failed to retrieve icon: ' + iconName) + .then(icon => { + if(icon) { + var trustedIcon = { + name: icon.Name, + svgString: $sce.trustAsHtml(icon.SvgString) + }; + this._cacheIcon(trustedIcon); + + liveRequests = _.filter(liveRequests, iconRequestPath); + + resolve(trustedIcon); + } + }) + .catch(err => { + console.warn(err); + }); + }; + + } + }); + }, + + /** Gets all the available icons in the backoffice icon folder and returns them as an array of IconModels */ + getAllIcons: function() { + return $q((resolve, reject) => { + if(allIconsRequested === false) { + allIconsRequested = true; + + umbRequestHelper.resourcePromise( + $http.get(Umbraco.Sys.ServerVariables.umbracoUrls.iconApiBaseUrl + 'GetAllIcons') + ,'Failed to retrieve icons') + .then(icons => { + icons.forEach(icon => { + var trustedIcon = { + name: icon.Name, + svgString: $sce.trustAsHtml(icon.SvgString) + }; + + this._cacheIcon(trustedIcon); + }); + + resolve(iconCache); + }) + .catch(err => { + console.warn(err); + });; + } else { + resolve(iconCache); + } + }); + }, + + /** LEGACY - Return a list of icons from icon fonts, optionally filter them */ /** It fetches them directly from the active stylesheets in the browser */ - getIcons: function(){ + getLegacyIcons: function(){ var deferred = $q.defer(); $timeout(function(){ if(collectedIcons){ @@ -188,8 +293,13 @@ function iconHelper($q, $timeout) { s = s.substring(0, hasPseudo); } - if(collectedIcons.indexOf(s) < 0){ - collectedIcons.push(s); + var icon = { + name: s, + svgString: undefined + }; + + if(collectedIcons.indexOf(icon) < 0 && s !== "icon-chevron-up" && s !== "icon-chevron-down"){ + collectedIcons.push(icon); } } } @@ -198,35 +308,20 @@ function iconHelper($q, $timeout) { deferred.resolve(collectedIcons); } }, 100); - + return deferred.promise; }, - /** Converts the icon from legacy to a new one if an old one is detected */ - convertFromLegacyIcon: function (icon) { - if (this.isLegacyIcon(icon)) { - //its legacy so convert it if we can - var found = _.find(converter, function (item) { - return item.oldIcon.toLowerCase() === icon.toLowerCase(); - }); - return (found ? found.newIcon : icon); - } - return icon; + /** A simple cache to ensure that the icon is only requested from the server if is isn't already in memory */ + _cacheIcon: function(icon) { + if(_.find(iconCache, {name: icon.name}) === undefined) { + iconCache = _.union(iconCache, [icon]); + } }, - convertFromLegacyImage: function (icon) { - var found = _.find(imageConverter, function (item) { - return item.oldImage.toLowerCase() === icon.toLowerCase(); - }); - return (found ? found.newIcon : undefined); - }, - - /** If we detect that the tree node has legacy icons that can be converted, this will convert them */ - convertFromLegacyTreeNodeIcon: function (treeNode) { - if (this.isLegacyTreeNodeIcon(treeNode)) { - return this.convertFromLegacyIcon(treeNode.icon); - } - return treeNode.icon; + /** Returns the cached icon or undefined */ + _getIconFromCache: function(iconName) { + return _.find(iconCache, {name: iconName}); } }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js index 75c9dccc30..6e5ee82ec7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js @@ -435,11 +435,16 @@ function mediaHelper(umbRequestHelper, $http, $log) { imagePath, animationProcessMode: options.animationProcessMode, cacheBusterValue: options.cacheBusterValue, - focalPoint: options.focalPoint, + focalPointLeft: options.focalPoint.left, + focalPointTop: options.focalPoint.top, height: options.height, mode: options.mode, upscale: options.upscale || false, - width: options.width + width: options.width, + cropX1: options.crop.x1, + cropX2: options.crop.x2, + cropY1: options.crop.y1, + cropY2: options.crop.y2 })), "Failed to retrieve processed image URL for image: " + imagePath); } 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 f903c44ad5..2a5d182a59 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 @@ -169,7 +169,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService //if the routing parameter keys are the same, we'll compare their values to see if any have changed and if so then the routing will be allowed. if (diff1.length === 0 && diff2.length === 0) { var partsChanged = 0; - _.each(currRoutingKeys, function (k) { + currRoutingKeys.forEach(k => { if (currUrlParams[k] != nextUrlParams[k]) { partsChanged++; } @@ -206,7 +206,8 @@ function navigationService($routeParams, $location, $q, $injector, eventsService var toRetain = _.union(retainedQueryStrings, toRetain); var currentSearch = $location.search(); $location.search(''); - _.each(toRetain, function (k) { + + toRetain.forEach(k => { if (currentSearch[k]) { $location.search(k, currentSearch[k]); } @@ -240,7 +241,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService var toRetain = Utilities.copy(nextRouteParams); var updated = false; - _.each(retainedQueryStrings, function (r) { + retainedQueryStrings.forEach(r => { // if mculture is set to null in nextRouteParams, the value will be undefined and we will not retain any query string that has a value of "null" if (currRouteParams[r] && nextRouteParams[r] !== undefined && !nextRouteParams[r]) { toRetain[r] = currRouteParams[r]; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js b/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js index 123845a63b..ea05dad4e7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js @@ -8,14 +8,14 @@ (function () { "use strict"; - function overlayService(eventsService, backdropService) { + function overlayService(eventsService, backdropService, focusLockService) { var currentOverlay = null; function open(newOverlay) { // prevent two open overlays at the same time - if(currentOverlay) { + if (currentOverlay) { close(); } @@ -23,32 +23,34 @@ var overlay = newOverlay; // set the default overlay position to center - if(!overlay.position) { + if (!overlay.position) { overlay.position = "center"; } // set the default overlay size to small - if(!overlay.size) { + if (!overlay.size) { overlay.size = "small"; } // use a default empty view if nothing is set - if(!overlay.view) { + if (!overlay.view) { overlay.view = "views/common/overlays/default/default.html"; } // option to disable backdrop clicks - if(overlay.disableBackdropClick) { + if (overlay.disableBackdropClick) { backdropOptions.disableEventsOnClick = true; } overlay.show = true; + focusLockService.addInertAttribute(); backdropService.open(backdropOptions); currentOverlay = overlay; eventsService.emit("appState.overlay", overlay); } function close() { + focusLockService.removeInertAttribute(); backdropService.close(); currentOverlay = null; eventsService.emit("appState.overlay", null); @@ -90,7 +92,6 @@ } open(overlay); - } function confirmDelete(overlay) { diff --git a/src/Umbraco.Web.UI.Client/src/common/services/search.service.js b/src/Umbraco.Web.UI.Client/src/common/services/search.service.js index fef286ec7e..803cd857b7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/search.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/search.service.js @@ -21,8 +21,8 @@ * */ angular.module('umbraco.services') - .factory('searchService', function ($q, $log, entityResource, contentResource, umbRequestHelper, $injector, searchResultFormatter) { - + .factory('searchService', function (entityResource, $injector, searchResultFormatter) { + return { /** @@ -42,12 +42,11 @@ angular.module('umbraco.services') throw "args.term is required"; } - return entityResource.search(args.term, "Member", args.searchFrom).then(function (data) { - _.each(data, function (item) { - searchResultFormatter.configureMemberResult(item); + return entityResource.search(args.term, "Member", args.searchFrom) + .then(data => { + data.forEach(item => searchResultFormatter.configureMemberResult(item)); + return data; }); - return data; - }); }, /** @@ -67,12 +66,11 @@ angular.module('umbraco.services') throw "args.term is required"; } - return entityResource.search(args.term, "Document", args.searchFrom, args.canceler, args.dataTypeKey).then(function (data) { + return entityResource.search(args.term, "Document", args.searchFrom, args.canceler, args.dataTypeKey) _.each(data, function (item) { - searchResultFormatter.configureContentResult(item); + data.forEach(item => searchResultFormatter.configureContentResult(item)); + return data; }); - return data; - }); }, /** @@ -92,12 +90,11 @@ angular.module('umbraco.services') throw "args.term is required"; } - return entityResource.search(args.term, "Media", args.searchFrom, args.canceler, args.dataTypeKey).then(function (data) { - _.each(data, function (item) { - searchResultFormatter.configureMediaResult(item); + return entityResource.search(args.term, "Media", args.searchFrom, args.canceler, args.dataTypeKey) + .then(data => { + data.forEach(item => searchResultFormatter.configureMediaResult(item)); + return data; }); - return data; - }); }, /** @@ -117,10 +114,8 @@ angular.module('umbraco.services') throw "args.term is required"; } - return entityResource.searchAll(args.term, args.canceler).then(function (data) { - - _.each(data, function (resultByType) { - + return entityResource.searchAll(args.term, args.canceler).then(data => { + Object.values(data).forEach(resultByType => { //we need to format the search result data to include things like the subtitle, urls, etc... // this is done with registered angular services as part of the SearchableTreeAttribute, if that // is not found, than we format with the default formatter @@ -140,7 +135,7 @@ angular.module('umbraco.services') } } //now apply the formatter for each result - _.each(resultByType.results, function (item) { + resultByType.results.forEach(item => { formatterMethod.apply(this, [item, resultByType.treeAlias, resultByType.appAlias]); }); @@ -148,12 +143,10 @@ angular.module('umbraco.services') return data; }); - }, // TODO: This doesn't do anything! setCurrent: function (sectionAlias) { - var currentSection = sectionAlias; } }; 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 9945396262..5d6b4646a3 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 @@ -1372,6 +1372,9 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s // throw "args.model.value is required"; //} + // force TinyMCE to load plugins/themes from minified files (see http://archive.tinymce.com/wiki.php/api4:property.tinymce.suffix.static) + args.editor.suffix = ".min"; + var unwatch = null; //Starts a watch on the model value so that we can update TinyMCE if the model changes behind the scenes or from the server @@ -1516,6 +1519,8 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s }); args.editor.on('Dirty', function (e) { + syncContent(); // Set model.value to the RTE's content + //make the form dirty manually so that the track changes works, setting our model doesn't trigger // the angular bits because tinymce replaces the textarea. if (args.currentForm) { diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js index 0d6216f7cc..37485ea7eb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js @@ -54,7 +54,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS //take the last child var childPath = this.getPath(node.children[node.children.length - 1]).join(","); //check if this already exists, if so exit - if (expandedPaths.indexOf(childPath) !== -1) { + if (expandedPaths.includes(childPath)) { return; } @@ -65,18 +65,18 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS var clonedPaths = expandedPaths.slice(0); //make a copy to iterate over so we can modify the original in the iteration - _.each(clonedPaths, function (p) { + clonedPaths.forEach(p => { if (childPath.startsWith(p + ",")) { //this means that the node's path supercedes this path stored so we can remove the current 'p' and replace it with node.path expandedPaths.splice(expandedPaths.indexOf(p), 1); //remove it - if (expandedPaths.indexOf(childPath) === -1) { + if (expandedPaths.includes(childPath) === false) { expandedPaths.push(childPath); //replace it } } else if (p.startsWith(childPath + ",")) { //this means we've already tracked a deeper node so we shouldn't track this one } - else if (expandedPaths.indexOf(childPath) === -1) { + else if (expandedPaths.includes(childPath) === false) { expandedPaths.push(childPath); //track it } }); 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 90125e7de6..78c8b5fa88 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 @@ -264,9 +264,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe //reset the tabs and set the active one if (response.data.tabs && response.data.tabs.length > 0) { - _.each(response.data.tabs, function (item) { - item.active = false; - }); + response.data.tabs.forEach(item => item.active = false); response.data.tabs[activeTabIndex].active = true; } @@ -327,7 +325,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe if (!jsonData) { throw "jsonData cannot be null"; } if (Utilities.isArray(jsonData)) { - _.each(jsonData, function (item) { + jsonData.forEach(item => { if (!item.key || !item.value) { throw "jsonData array item must have both a key and a value property"; } }); } @@ -345,7 +343,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe var formData = new FormData(); //add the json data if (Utilities.isArray(data)) { - _.each(data, function(item) { + data.forEach(item => { formData.append(item.key, !Utilities.isString(item.value) ? Utilities.toJson(item.value) : item.value); }); } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/usershelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/usershelper.service.js index 1bda86c3b3..e6450798fb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/usershelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/usershelper.service.js @@ -12,36 +12,23 @@ { "value": 4, "name": "Inactive", "key": "Inactive", "color": "warning" } ]; - localizationService.localizeMany(_.map(userStates, function (userState) { - return "user_state" + userState.key; - })).then(function (data) { - var reg = /^\[[\S\s]*]$/g; - _.each(data, function (value, index) { - if (!reg.test(value)) { - // Only translate if key exists - userStates[index].name = value; - } + localizationService.localizeMany(userStates.map(userState => "user_state" + userState.key)) + .then(data => { + var reg = /^\[[\S\s]*]$/g; + data.forEach((value, index) => { + if (!reg.test(value)) { + // Only translate if key exists + userStates[index].name = value; + } + }); }); - }); - function getUserStateFromValue(value) { - var foundUserState; - angular.forEach(userStates, function (userState) { - if(userState.value === value) { - foundUserState = userState; - } - }); - return foundUserState; + function getUserStateFromValue(value) { + return userStates.find(userState => userState.value === value); } function getUserStateByKey(key) { - var foundUserState; - angular.forEach(userStates, function (userState) { - if(userState.key === key) { - foundUserState = userState; - } - }); - return foundUserState; + return userStates.find(userState => userState.key === key); } function getUserStatesFilter(userStatesObject) { @@ -49,7 +36,7 @@ var userStatesFilter = []; for (var key in userStatesObject) { - if (userStatesObject.hasOwnProperty(key)) { + if (hasOwnProperty.call(userStatesObject, key)) { var userState = getUserStateByKey(key); if(userState) { userState.count = userStatesObject[key]; @@ -59,7 +46,6 @@ } return userStatesFilter; - } //////////// @@ -71,10 +57,7 @@ }; return service; - } angular.module('umbraco.services').factory('usersHelper', usersHelperService); - - })(); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js index 82353df744..1fb5884d4c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js @@ -173,9 +173,9 @@ function umbModelMapper() { /** This converts the source model to a basic entity model, it will throw an exception if there isn't enough data to create the model */ convertToEntityBasic: function (source) { var required = ["id", "name", "icon", "parentId", "path"]; - _.each(required, function (k) { - if (!_.has(source, k)) { - throw "The source object does not contain the property " + k; + required.forEach(k => { + if (!hasOwnProperty.call(source, k)) { + throw `The source object does not contain the property ${k}`; } }); var optional = ["metaData", "key", "alias"]; diff --git a/src/Umbraco.Web.UI.Client/src/installer/steps/database.html b/src/Umbraco.Web.UI.Client/src/installer/steps/database.html index fc870858cf..cfe0940aa2 100644 --- a/src/Umbraco.Web.UI.Client/src/installer/steps/database.html +++ b/src/Umbraco.Web.UI.Client/src/installer/steps/database.html @@ -1,118 +1,121 @@
-

Configure your database

-

- Enter connection and authentication details for the database you want to install Umbraco on -

+

Configure your database

+

+ Enter connection and authentication details for the database you want to install Umbraco on +

-
-
- What type of database do you use? - -
- -
-
+ +
+ What type of database do you use? + +
+ +
+
-
+

Great! No need to configure anything, you can simply click the continue button below to continue to the next step

-
+
-
- What is the exact connection string we should use? -
- -
- - - Enter a valid database connection string. -
-
-
- -
-
- Where do we find your database? -
-
- -
- - Enter server domain or IP -
-
-
- -
-
- -
- - Enter the name of the database -
-
-
-
- -
- What credentials are used to access the database? -
-
- -
- - Enter the database user name -
-
-
- -
-
- -
- - Enter the database password -
-
-
- -
-
- -
-
-
-
- -
-
-
- - - - - - Validating your database connection... - - - - Could not connect to database - +
+ What is the exact connection string we should use? +
+ +
+ + Enter a valid database connection string.
-
-
+
+
+
+
+ Where do we find your database? +
+
+ +
+ + Enter server domain or IP +
+
+
- +
+
+ +
+ + Enter the name of the database +
+
+
+
+ +
+ What credentials are used to access the database? +
+
+ +
+ + Enter the database user name +
+
+
+ +
+
+ +
+ + Enter the database password +
+
+
+ +
+
+ +
+
+
+
+ +
+
+
+ + + + + + Validating your database connection... + + + + Could not connect to database + +
+
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index cdccbf527b..d99573decb 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -147,6 +147,7 @@ @import "components/umb-color-swatches.less"; @import "components/check-circle.less"; @import "components/umb-file-icon.less"; +@import "components/umb-icon.less"; @import "components/umb-iconpicker.less"; @import "components/umb-insert-code-box.less"; @import "components/umb-packages.less"; @@ -174,11 +175,13 @@ @import "components/umb-dropdown.less"; @import "components/umb-range-slider.less"; @import "components/umb-number.less"; +@import "components/umb-tags-editor.less"; @import "components/buttons/umb-button.less"; @import "components/buttons/umb-button-group.less"; @import "components/buttons/umb-toggle.less"; @import "components/buttons/umb-toggle-group.less"; +@import "components/buttons/umb-button-ellipsis.less"; @import "components/notifications/umb-notifications.less"; @import "components/umb-file-dropzone.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/buttons.less b/src/Umbraco.Web.UI.Client/src/less/buttons.less index 2b50b60ae8..2caa223647 100644 --- a/src/Umbraco.Web.UI.Client/src/less/buttons.less +++ b/src/Umbraco.Web.UI.Client/src/less/buttons.less @@ -336,20 +336,17 @@ input[type="submit"].btn { // This is lifted from umb-group-builder.less .btn-icon { - border: none; - + border: none; font-size: 18px; position: relative; cursor: pointer; color: @ui-icon; - margin: 0; padding: 5px 10px; width: auto; overflow: visible; background: transparent; line-height: normal; - outline: 0; -webkit-appearance: none; &:hover { diff --git a/src/Umbraco.Web.UI.Client/src/less/colors.less b/src/Umbraco.Web.UI.Client/src/less/colors.less index 4cb70cdf5e..ba4909c997 100644 --- a/src/Umbraco.Web.UI.Client/src/less/colors.less +++ b/src/Umbraco.Web.UI.Client/src/less/colors.less @@ -24,7 +24,7 @@ /* Colors based on https://zavoloklom.github.io/material-design-color-palette/colors.html */ .btn-color-black {background-color: @black;} -.color-black i { color: @black;} +.color-black, .color-black i { color: @black !important;} .btn-color-blue-grey {background-color: @blueGrey;} .color-blue-grey, .color-blue-grey i { color: @blueGrey !important;} @@ -78,4 +78,4 @@ .color-deep-purple, .color-deep-purple i { color: @deepPurpleIcon !important; } .btn-color-indigo{background-color: @indigoIcon;} -.color-indigo, .color-indigo i { color: @indigoIcon !important; } \ No newline at end of file +.color-indigo, .color-indigo i { color: @indigoIcon !important; } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-ellipsis.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-ellipsis.less new file mode 100644 index 0000000000..54302ba869 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-ellipsis.less @@ -0,0 +1,76 @@ +.umb-button-ellipsis{ + padding: 0 5px; + text-align: center; + margin: 0 auto; + cursor: pointer; + border-radius: @baseBorderRadius; + color: black; + position: relative; + opacity: 0.8; + transition: opacity .3s ease-out; + + &--absolute { + position: absolute; + } + + &--small { + height: 15px; + } + + &.show-text { + display: flex; + flex-wrap: wrap; + justify-content: center; + } + + .umb-button-ellipsis--tab, + .umb-tour-is-visible .umb-tree &, + &:hover, + &:focus{ + opacity: 1; + } + + &--hidden{ + opacity: 0; + + &:hover, + &:focus { + opacity: 1; + } + } + + &__content { + display: flex; + flex-wrap: wrap; + } + + &__icon { + color: inherit; + flex-basis: 100%; + + .umb-button-ellipsis--tab & { + margin: 0 0 7px; + } + + .umb-button-ellipsis--small & { + font-size: 8px; + position: relative; + top: -2px; + } + } + + &__text { + color: inherit; + font-size: 12px; + line-height: 1em; + flex-basis: 100%; + + .umb-button-ellipsis--tab & { + position: absolute; + right: 0; + left: 0; + bottom: 13px; + margin: 0 auto; + } + } +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less index 02b67460f6..24800c1142 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less @@ -14,7 +14,7 @@ display: flex; } -.umb-button-group { +.umb-button-group.-with-button-group-toggle { .umb-button__button { border-radius: @baseBorderRadius 0 0 @baseBorderRadius; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less index 4127c2201c..d523b24141 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less @@ -31,6 +31,11 @@ margin-left: 5px; } +.umb-button__button[disabled] .umb-button__caret { + border-top-color: @gray-7; + border-bottom-color: @gray-7; +} + .umb-button__progress { position: absolute; left: 50%; 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 ff4122b258..701af849cc 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 @@ -41,9 +41,6 @@ } } - - - .umb-toggle__handler { position: absolute; top: 1px; @@ -59,10 +56,8 @@ transform: translateX(20px); background-color: @white; } - } - /* Icons */ .umb-toggle__icon { @@ -78,9 +73,7 @@ color:@white; transition: opacity 120ms; opacity: 0; - // .umb-toggle:hover & { - // color: @ui-btn-hover; - // } + .umb-toggle--checked & { opacity: 1; } @@ -93,6 +86,7 @@ right: 5px; color: @ui-btn; transition: opacity 120ms; + .umb-toggle--checked & { opacity: 0; } @@ -101,23 +95,41 @@ } } - - -.umb-toggle.umb-toggle--disabled.umb-toggle--checked, .umb-toggle.umb-toggle--disabled { .umb-toggle__toggle { cursor: not-allowed; - background-color: @gray-9; - border-color: @gray-9; } - .umb-toggle__icon--left { - color: @gray-6; + + &, &.umb-toggle--checked { + + .umb-toggle__toggle { + .umb-toggle__handler { + background-color: @gray-10; + } + } } - .umb-toggle__icon--right { - color: @gray-6; + + &:not(.umb-toggle--checked) { + .umb-toggle__toggle { + background-color: @gray-8; + border-color: @gray-8; + } + + .umb-toggle__icon--left, + .umb-toggle__icon--right { + color: @gray-6; + } } - .umb-toggle__handler { - background-color: @gray-10; + + &.umb-toggle--checked { + .umb-toggle__toggle { + background-color: lighten(@ui-btn, 50%); + border-color: lighten(@ui-btn, 50%); + } + .umb-toggle__icon--left, + .umb-toggle__icon--right { + color: @gray-9; + } } } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor.less b/src/Umbraco.Web.UI.Client/src/less/components/editor.less index ac55c6ffb1..d4069cdd2b 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/editor.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/editor.less @@ -73,6 +73,11 @@ height: @editorHeaderHeight; } +.umb-editor-header .umb-button__button[disabled] { + // do not dim down the background color of disabled buttons in the header + background-color: unset; +} + .umb-editor-header__back { background: transparent; border: 0; @@ -135,22 +140,19 @@ input.umb-editor-header__name-input:disabled { margin-left: auto; } -a.umb-editor-header__close-split-view { - +.umb-editor-header__close-split-view { display: flex; justify-content: center; align-items: center; position: relative; height: 69px; width: 69px; - - font-size: 20px; - color: @gray-6; - text-decoration: none !important; -} + font-size: 20px; + color: @gray-6; -a.umb-editor-header__close-split-view:hover { - color: @black; + &:hover { + color: @black; + } } .umb-editor-header { @@ -162,9 +164,7 @@ a.umb-editor-header__close-split-view:hover { } } - // container - .umb-editor-container { position: absolute; top: @editorHeaderHeight; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less index eae25b273c..95625d9e73 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less @@ -90,6 +90,7 @@ button.umb-variant-switcher__toggle { align-items: center; border-bottom: 1px solid @gray-9; position: relative; + .umb-variant-switcher__name-wrapper:hover { .umb-variant-switcher__name { color: @blueMid; @@ -99,6 +100,11 @@ button.umb-variant-switcher__toggle { } } } + +.umb-variant-switcher__item.--not-allowed:not(.--current) .umb-variant-switcher__name-wrapper:hover { + cursor: default; +} + .umb-variant-switcher__item.--state-notCreated:not(.--active) { .umb-variant-switcher__name-wrapper::before { content: "+"; @@ -106,38 +112,44 @@ button.umb-variant-switcher__toggle { float: left; font-size: 15px; font-weight: 900; - padding: 8px 16px 8px 6px; + padding: 8px 12px 8px 0; color: @gray-5; } + .umb-variant-switcher__item-expand-button + .umb-variant-switcher__name-wrapper::before { padding: 8px 16px 8px 20px; } + .umb-variant-switcher__name { color: @gray-5; } + .umb-variant-switcher__state { color: @gray-6; } + .umb-variant-switcher__name-wrapper::after { content: ""; position: absolute; z-index: 1; - border: 1px dashed @gray-9; - top: 7px; - bottom: 7px; - left: 7px; - right: 7px; - border-radius: 3px; + border: 2px dashed @gray-9; + margin: 2px; + top: 0; + bottom: 0; + left: 0; + right: 0; pointer-events: none; } - + .umb-variant-switcher__name-wrapper:hover { &::before { color: @blueMid; } + .umb-variant-switcher__name { color: @blueMid; } + .umb-variant-switcher__state { color: @blueMid; } @@ -183,8 +195,11 @@ button.umb-variant-switcher__toggle { } .umb-variant-switcher__item.--current { - //color: @ui-light-active-type; + color: @ui-light-active-type; //background-color: @pinkExtraLight; + .umb-variant-switcher__name-wrapper { + border-left: 4px solid @ui-active; + } .umb-variant-switcher__name { //color: @ui-light-active-type; font-weight: 700; @@ -216,7 +231,7 @@ button.umb-variant-switcher__toggle { .umb-variant-switcher__item:focus-within .umb-variant-switcher__split-view, .umb-variant-switcher__item:hover .umb-variant-switcher__split-view, .umb-variant-switcher__split-view:focus { - display: block; + display: flex; cursor: pointer; } @@ -263,7 +278,10 @@ button.umb-variant-switcher__toggle { cursor: pointer; background-color: transparent; border: none; + padding-top: 6px !important; + padding-bottom: 6px !important; } + .dropdown-menu>li { > .umb-variant-switcher__name-wrapper { padding-top: 10px; @@ -290,7 +308,7 @@ button.umb-variant-switcher__toggle { .umb-variant-switcher__split-view { font-size: 12px; display: none; - padding: 20px 20px; + padding: 16px 20px; position: absolute; right: 0; top: 0; @@ -303,7 +321,6 @@ button.umb-variant-switcher__toggle { } } - .umb-variant-switcher__sub-variants { position: relative; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/overlays.less b/src/Umbraco.Web.UI.Client/src/less/components/overlays.less index 25bfc2fce5..035bf02f91 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/overlays.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/overlays.less @@ -106,7 +106,6 @@ height: auto; top: 50%; left: 50%; - transform: translate(-50%, 0); transform: translate(-50%, -50%); border-radius: @baseBorderRadius; } @@ -128,6 +127,7 @@ width: 400px; max-height: 100vh; box-sizing: border-box; + visibility: hidden; border-radius: @baseBorderRadius; &.umb-overlay--small { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less index 4a483ce3f0..97caf66497 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less @@ -17,8 +17,9 @@ .umb-tree-item__arrow { position: relative; margin-left: -16px; - width: 16px; - height: 16px; + margin-right: 4px; + width: 12px; + height: 12px; visibility: hidden; text-decoration: none; font-size: 12px; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less index 839e61c5f9..59d81eb3ea 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less @@ -15,6 +15,16 @@ text-decoration: none; } + .umb-tree-item__arrow { + visibility: hidden; + text-decoration: none; + font-size: 12px; + transition: color 120ms; + + &:hover { + color: @ui-option-type-hover; + } + } i.noSpr { display: inline-block; margin-top: 1px; @@ -75,8 +85,8 @@ body.touch .umb-tree { &:hover { background: @ui-option-hover; - color: @ui-option-type-hover; + a { color: @ui-option-type-hover; } @@ -85,11 +95,15 @@ body.touch .umb-tree { position: relative; width: auto; height: auto; - margin: 0 10px 0 auto; - padding: 9px 5px; + margin: 0 5px 0 auto; + padding: 7px 5px; overflow: visible; clip: auto; } + + .umb-button-ellipsis--hidden { + opacity: 1; + } .umb-tree-icon { color: @ui-option-type-hover; @@ -171,9 +185,9 @@ body.touch .umb-tree { display: flex; flex: 0 0 auto; justify-content: flex-end; - padding: 9px 5px; + padding: 7px 5px; text-align: center; - margin: 0 10px 0 auto; + margin: 0 5px 0 auto; cursor: pointer; border-radius: @baseBorderRadius; @@ -184,18 +198,20 @@ body.touch .umb-tree { display: inline-block; margin: 0 2px 0 0; background: @ui-active-type; - + &:last-child { margin: 0; } } + &:hover { background: rgba(255, 255, 255, .5); + i { background: @ui-active-type-hover; } } - + // NOTE - We're having to repeat ourselves here due to an .sr-only class appearing in umbraco/lib/font-awesome/css/font-awesome.min.css &.sr-only--hoverable:hover, &.sr-only--focusable:focus { @@ -203,9 +219,9 @@ body.touch .umb-tree { display: flex; flex: 0 0 auto; justify-content: flex-end; - padding: 9px 5px; + padding: 7px 5px; text-align: center; - margin: 0 10px 0 auto; + margin: 0 auto; cursor: pointer; border-radius: 3px; } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-badge.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-badge.less index 9a18bef2de..d79bbbde20 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-badge.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-badge.less @@ -29,6 +29,11 @@ color: @white; } +.umb-badge--info { + background-color: @blue; + color: @white; +} + .umb-badge--warning { background-color: @orange; color: @white; @@ -39,6 +44,11 @@ color: @white; } +.umb-badge--dark { + background-color: @grayDark; + color: @white; +} + // Size .umb-badge--xxs { font-size: 11px; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-code-snippet.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-code-snippet.less index b372841910..96b4fc08c8 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-code-snippet.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-code-snippet.less @@ -18,6 +18,7 @@ justify-content: flex-start; flex-grow: 1; padding: 2px 10px; + text-transform: uppercase; } button { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-confirm-action.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-confirm-action.less index f972633bf4..a6548123ac 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-confirm-action.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-confirm-action.less @@ -1,3 +1,8 @@ +//WRAPPER +.umb_confirm-action { + display: inline-block; +} + // OVERLAY .umb_confirm-action__overlay { position: absolute; @@ -13,19 +18,6 @@ left: 0; animation: fadeInUp 0.2s; flex-direction: column; - - .umb_confirm-action__overlay-action { - margin-bottom: 5px; - } - - .umb_confirm-action__overlay-action.-confirm { - order: 1; - } - - .umb_confirm-action__overlay-action.-cancel { - order: 2; - } - } .umb_confirm-action__overlay.-right { @@ -35,18 +27,6 @@ left: auto; animation: fadeInLeft 0.2s; flex-direction: row; - - .umb_confirm-action__overlay-action { - margin-left: 5px; - } - - .umb_confirm-action__overlay-action.-confirm { - order: 2; - } - - .umb_confirm-action__overlay-action.-cancel { - order: 1; - } } .umb_confirm-action__overlay.-bottom { @@ -56,18 +36,6 @@ left: 0; animation: fadeInDown 0.2s; flex-direction: column; - - .umb_confirm-action__overlay-action { - margin-top: 5px; - } - - .umb_confirm-action__overlay-action.-confirm { - order: 2; - } - - .umb_confirm-action__overlay-action.-cancel { - order: 1; - } } .umb_confirm-action__overlay.-left { @@ -77,55 +45,59 @@ left: -50px; animation: fadeInRight 0.2s; flex-direction: row; +} + +.umb_confirm-action__overlay { .umb_confirm-action__overlay-action { margin-right: 5px; + + &.-confirm { + order: 1; + } + + &.-cancel { + order: 2; + } } - .umb_confirm-action__overlay-action.-confirm { - order: 1; - } + // BUTTONS + .umb_confirm-action__overlay-action { + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + color: @white; + border-radius: 40px; + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); + font-size: 18px; + cursor: pointer; + user-select: none; - .umb_confirm-action__overlay-action.-cancel { - order: 2; + &:hover { + text-decoration: none; + color: @white; + } + + // confirm button + &.-confirm { + background: @white; + color: @green !important; + + &:hover { + color: @green !important; + } + } + + // cancel button + &.-cancel { + background: @white; + color: @red !important; + + &:hover { + color: @red !important; + } + } } } - -// BUTTONS -.umb_confirm-action__overlay-action { - width: 20px; - height: 20px; - display: flex; - align-items: center; - justify-content: center; - color: @white; - border-radius: 40px; - box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); - font-size: 18px; - cursor: pointer; -} - -.umb_confirm-action__overlay-action:hover { - text-decoration: none; - color: @white; -} - -// confirm button -.umb_confirm-action__overlay-action.-confirm { - background: @white; - color: @green !important; -} - -.umb_confirm-action__overlay-action.-confirm:hover { - color: @green !important; -} - -// cancel button -.umb_confirm-action__overlay-action.-cancel { - background: @white; - color: @red !important; -} - -.umb_confirm-action__overlay-action.-cancel:hover { - color: @red !important; -} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less index 5bcfdd1c71..b8084bc435 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less @@ -3,23 +3,28 @@ box-shadow: 0 5px 10px 0 rgba(0,0,0,0.16); } -span.flatpickr-day { +.flatpickr-day { border-radius: @baseBorderRadius; border: none; &.today:not(.active) { border: 1px solid; } -} -span.flatpickr-day:hover { - background-color: @gray-10; -} + &:hover { + background-color: @gray-10; + } -span.flatpickr-day.selected { - background-color: @ui-selected; -} + &.selected, &.startRange, &.endRange { + background-color: @ui-selected-type !important; + border-color: @ui-selected-type !important; -span.flatpickr-day.selected:hover { - background-color: @ui-selected-hover; + &:hover { + background-color: @ui-selected-type-hover !important; + } + + &.startRange + .endRange:not(:nth-child(7n+1)) { + box-shadow: -10px 0 0 @ui-selected-type !important; + } + } } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less index 2fc705b11b..641e0dc7a7 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less @@ -46,7 +46,7 @@ } &.is-active { - color: @ui-light-active-type; + color: @ui-light-active-type !important; &::before { opacity: 1; @@ -93,8 +93,8 @@ .box-shadow(~"inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05)"); } - &:focus-within &__anchor_dropdown, - &:hover &__anchor_dropdown { + &:focus-within > &__anchor_dropdown, + &:hover > &__anchor_dropdown { visibility: visible; opacity: 1; transition: opacity 20ms 0; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-form-check.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-form-check.less index 8a24d948ac..cff9980483 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-form-check.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-form-check.less @@ -1,25 +1,18 @@ @checkboxWidth: 18px; @checkboxHeight: 18px; -label.umb-form-check--checkbox{ - margin:3px 0; -} .umb-form-check { display: flex; + align-items: center; position: relative; - padding-left: 0px; - margin: 0; - min-height: 22px; + padding-left: 0; + margin: 5px 0; + min-height: 20px; cursor: pointer !important; - .umb-form-check__symbol { - margin-top: 4px; - margin-right: 10px; - } .umb-form-check__info { - margin-left:20px; + margin-left: 30px; position: relative; - top: 3px; } @@ -84,7 +77,6 @@ label.umb-form-check--checkbox{ } .tabbing-active &.umb-form-check--radiobutton &__input:focus ~ .umb-form-check__state .umb-form-check__check { - //outline: 2px solid @inputBorderTabFocus; border: 2px solid @inputBorderTabFocus; margin: -1px; } @@ -102,11 +94,10 @@ label.umb-form-check--checkbox{ &__state { display: flex; - height: 18px; + height: 20px; + width: 20px; position: absolute; - margin-top: 2px; - top: 0; - left: -1px; + top: -1px; } &__check { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less index 26d61412ae..a8c428ba7a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less @@ -751,9 +751,19 @@ margin-right: 5px; position: relative; cursor: pointer; - display:inline-block; + display: inline-block; } +.umb-grid .cell-tools, +.umb-grid .umb-control-tool { + .btn-icon { + padding: 0; + } +} + +.umb-grid .umb-control-tool .btn-icon { + color: @white; +} // Template @@ -1007,8 +1017,6 @@ display: block; } - - // Configuration specific styles // ------------------------- .umb-grid-configuration .umb-templates { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less index 6eded29b8b..2590e0610a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less @@ -347,23 +347,20 @@ input.umb-group-builder__group-title-input:disabled:hover { .umb-group-builder__property-actions { flex: 0 0 44px; display: flex; - align-items: center; + align-items: flex-start; justify-content: flex-end; } .umb-group-builder__property-action { - position: relative; margin: 5px 0; > button { border: none; - font-size: 18px; position: relative; cursor: pointer; color: @ui-icon; - margin: 0; padding: 5px 10px; width: auto; @@ -399,18 +396,21 @@ input.umb-group-builder__group-title-input:disabled:hover { padding: 0 4px; display: flex; border-radius: 3px; -} + align-items: center; -.umb-group-builder__property-tag:first-child { - margin-left: 0; -} + &:first-child { + margin-left: 0; + } -.umb-group-builder__property-tag.-white { - background-color: @white; + &.-white { + background-color: @white; + } } .umb-group-builder__property-tag-icon { margin-right: 3px; + display: flex; + align-items: center; } /* ---------- SORTABLE ---------- */ @@ -513,17 +513,14 @@ input.umb-group-builder__group-sort-value { display: flex; align-items: center; align-content: stretch; - min-height: 80px; - border: 1px solid @gray-9; color: @ui-action-discreet-type; border-radius: @baseBorderRadius; - } .editor-info { - flex: 1 0 auto; + flex: 1 1 auto; text-align: left; display: flex; align-items: center; @@ -537,6 +534,9 @@ input.umb-group-builder__group-sort-value { } .editor-icon-wrapper { + display: flex; + justify-content: center; + align-items: center; width: 60px; height: 60px; text-align: center; @@ -548,12 +548,12 @@ input.umb-group-builder__group-sort-value { font-size: 32px; } } - + .editor-details { flex: 1 1 auto; margin-top: 10px; margin-bottom: 10px; - + .editor-name { display: block; font-weight: bold; @@ -570,9 +570,9 @@ input.umb-group-builder__group-sort-value { width: 48px; height: 48px; font-size: 18px; - min-height: 80px; color: @ui-action-discreet-type; + &:hover { color: @ui-action-discreet-type-hover; background-color: @ui-action-discreet-hover; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-icon.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-icon.less new file mode 100644 index 0000000000..e3b0550d15 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-icon.less @@ -0,0 +1,9 @@ +.umb-icon { + &:before, &:after { + content: none !important; + } + + > i { + font-family: inherit; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-iconpicker.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-iconpicker.less index 98b2b1d72d..e23325a7d2 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-iconpicker.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-iconpicker.less @@ -26,6 +26,11 @@ padding: 15px 0; text-decoration: none; border-radius: 3px; + background: none; + background: none; + border: none; + cursor: pointer; + color: currentColor; } .umb-iconpicker-item button:hover, @@ -41,34 +46,41 @@ box-sizing: border-box; } +.umb-iconpicker-svg svg { + display: block; + width: 30px; + height: 30px; + fill: currentColor; +} + .umb-iconpicker-item button:active { background: @gray-10; } .umb-iconpicker-item i { + font-family: inherit; font-size: 30px; } - // Color swatch .button { - border: none; - color: @white; - padding: 5px; - text-align: center; - text-decoration: none; - display: inline-block; - margin: 5px; - border-radius: 3px; - } + border: none; + color: @white; + padding: 5px; + text-align: center; + text-decoration: none; + display: inline-block; + margin: 5px; + border-radius: 3px; +} - // Circle behind the checkmark - i.small.active{ - font-size: 14px; - display: inline-block; - width: 20px; - height: 20px; - border-radius: 50%; - background-color: rgba(0,0,0,.15); - float: right; - } +// Circle behind the checkmark +i.small.active{ + font-size: 14px; + display: inline-block; + width: 20px; + height: 20px; + border-radius: 50%; + background-color: rgba(0,0,0,.15); + float: right; +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less index 44955e8f8e..57ba73305a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less @@ -40,7 +40,7 @@ a.umb-list-item:focus { } .umb-list-item__description--checkbox{ - margin: 0 0 0 26px; + margin: 0 0 0 30px; } .umb-list-checkbox { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-logviewer.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-logviewer.less index 8beff55b7c..56fa905310 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-logviewer.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-logviewer.less @@ -78,19 +78,22 @@ padding-right: 160px; } - .icon-rate { + .save-search, + .filter-search { position: absolute; top: 0; - line-height: 32px; + display: flex; + align-items: center;; + height: 32px; + } + + .save-search { right: 140px; color: @yellow-d1; cursor: pointer; } - .icon-wrong { - position: absolute; - top: 0; - line-height: 32px; + .filter-search { right: 120px; color: @gray-7; cursor: pointer; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less index 5d6b7ad962..abd1bfd047 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less @@ -217,3 +217,19 @@ text-decoration: none; box-shadow: 0 1px 2px rgba(0,0,0,.2); } + +/*for the listview*/ + +.umb-media-grid__list-item.selected, .umb-media-grid__list-item.selected:hover, .umb-media-grid__list-item.selected:focus { + border: 2px solid #f5c1bc !important; +} + +.umb-media-grid__list-view .umb-table-cell.umb-table__name { + flex: 1 1 25%; + max-width: none; + white-space: normal; +} + +.umb-media-grid__list-view .umb-table-cell.umb-table__name .item-name { + white-space:normal; +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-list-view.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-list-view.less index 8cd08f5045..ecb1ad1904 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-list-view.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-list-view.less @@ -44,6 +44,10 @@ color: @black; } +.umb-minilistview { + overflow: hidden; +} + /* Animations */ .umb-mini-list-view.ng-animate { transition: 120ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all; 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 30a32b8123..39eb7e92e4 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,9 +1,11 @@ -.umb-multiple-textbox{ - &__confirm{ +.umb-multiple-textbox { + .umb-property-editor--limit-width(); + + &__confirm { position: relative; display: inline-block; - &-action{ + &-action { margin: -2px 0 0 0; padding: 2px; background: transparent; @@ -12,10 +14,6 @@ } } -.umb-multiple-textbox .icon-wrapper { - width: 50px; -} - .umb-multiple-textbox .textbox-wrapper { align-items: center; margin-bottom: 15px; @@ -30,15 +28,10 @@ } .umb-multiple-textbox .textbox-wrapper i.handle { - margin-left: 5px; + margin-left: 10px; cursor: move; } -.umb-multiple-textbox .textbox-wrapper a.remove { - margin-left: 5px; - text-decoration: none; -} - .umb-multiple-textbox .add-link { &:extend(.umb-node-preview-add); } 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 0f2b1402dc..384d9b4ac1 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 @@ -210,7 +210,7 @@ .umb-nested-content__add-content.--disabled:hover { color: @gray-7; border-color: @gray-7; - cursor: default; + cursor: not-allowed; } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less index b808e6574a..197a5eb176 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less @@ -59,15 +59,12 @@ .umb-package-link { display: block; - flex-wrap: wrap; - flex-direction: column; - justify-content: center; position: relative; box-sizing: border-box; height: 100%; width: 100%; border-radius: 3px; - border: 0 none; + border: 1px solid transparent; text-decoration: none !important; transition: border-color 100ms ease; background-color: @white; @@ -78,8 +75,6 @@ } } - - // Icon .umb-package-icon { display: flex; @@ -94,22 +89,20 @@ border-top-right-radius: 3px; border-top-left-radius: 3px; min-height: 60px; -} -.umb-package-icon img { - max-width: 70px; - width: 70px; - height: auto; + img { + max-width: 70px; + width: 70px; + height: auto; + } } - // Info .umb-package-info { padding: 15px; text-align: center; } - // Name .umb-package-name { font-size: 14px; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-pagination.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-pagination.less index 8d3d563cab..f44aa645c4 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-pagination.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-pagination.less @@ -1,3 +1,5 @@ -.umb-pagination ul { - box-shadow: none; -} \ No newline at end of file +.umb-pagination { + ul { + box-shadow: none; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less index 17c4bf1a55..f86b27af17 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less @@ -85,7 +85,7 @@ .umb-contextmenu { border-top-left-radius: 0; - margin-top:1px; + margin-top:-2px; } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less index 39b2f4002e..83774e2dae 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less @@ -14,6 +14,12 @@ color: @gray-8; } + &:focus-within { + .tabbing-active & { + box-shadow: 0 0 2px @ui-outline, inset 0 0 2px 1px @ui-outline; + } + } + i.icon { font-size: 55px; line-height: 70px @@ -26,4 +32,10 @@ width: 100%; } } + + .drag-over { + .umb-upload-button-big { + border-color: @gray-1; + } + } } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-stylesheet.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-stylesheet.less index 38ceba2a59..36d9913d66 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-stylesheet.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-stylesheet.less @@ -41,6 +41,7 @@ textarea.umb-stylesheet-rule-styles { width: 300px; height: 100px; resize: none; + font-family: @monoFontFamily; } .umb-stylesheet-rule-preview { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less index 202c488bb4..d0427cad0a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less @@ -164,7 +164,7 @@ input.umb-table__input { } } -.umb-table-body__icon { +.umb-table-body .umb-table-body__icon { margin: 0 auto; font-size: 20px; line-height: 20px; @@ -173,7 +173,7 @@ input.umb-table__input { text-decoration: none; } -.umb-table-body__checkicon { +.umb-table-body .umb-table-body__icon.umb-table-body__checkicon { display: none; font-size: 18px; line-height: 20px; @@ -218,15 +218,15 @@ input.umb-table__input { } // Show checkmark when checked, hide file icon -.umb-table-row.-selected { - - .umb-table-body__fileicon { - display: none; - } - .umb-table-body__checkicon { - display: inline-block; - } - +.umb-table-body .umb-table-row.-selected { + .umb-table-body__icon { + &.umb-table-body__fileicon { + display: none; + } + &.umb-table-body__checkicon { + display: inline-block; + } + } } // Table Row Styles diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-tags-editor.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-tags-editor.less new file mode 100644 index 0000000000..9a80aa4ff3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-tags-editor.less @@ -0,0 +1,53 @@ +.umb-tags-editor { + border: @inputBorder solid 1px; + padding: 5px; + min-height: 54px; + font-size: 13px; + text-shadow: none; + box-sizing: border-box; + + .tag { + cursor: default; + margin: 10px; + padding: 10px 15px; + background: @blueExtraDark; + position: relative; + user-select: all; + + .umb_confirm-action { + + > .btn-icon { + color: @white; + padding: 0; + position: relative; + cursor: pointer; + padding-left: 2px; + font-size: 15px; + right: -5px; + bottom: -1px; + user-select: none; + } + + .umb_confirm-action__overlay.-left { + top: 8px; + left: auto; + right: 15px; + } + } + } + + input { + border: none; + background: @white; + } + + .twitter-typeahead { + margin: 10px; + margin-top: 16px; + vertical-align: top; + + input { + padding-left: 0; + } + } +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-preview.less b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-preview.less index f62f3afd37..d0dca54403 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-preview.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-preview.less @@ -4,6 +4,11 @@ display: flex; box-sizing: border-box; border-bottom: 1px solid @gray-9; + flex-wrap: wrap; +} + +.umb-editor-wrapper .umb-user-preview { + .umb-property-editor--limit-width(); } .umb-user-preview:last-of-type { @@ -29,22 +34,26 @@ flex: 0 0 auto; display: flex; align-items: center; + margin-left: auto; } .umb-user-preview__action { + background: transparent; + padding: 0; + border: 0 none; margin-left: 5px; margin-right: 5px; font-size: 13px; font-weight: bold; - color: @gray-5; + color: @ui-action-type; } .umb-user-preview__action:hover { - color: @turquoise; + color: @ui-action-type-hover; text-decoration: none; opacity: 1; } .umb-user-preview__action--red:hover { color: @red; -} \ No newline at end of file +} diff --git a/src/Umbraco.Web.UI.Client/src/less/forms.less b/src/Umbraco.Web.UI.Client/src/less/forms.less index ffc0626981..ed5a2c0622 100644 --- a/src/Umbraco.Web.UI.Client/src/less/forms.less +++ b/src/Umbraco.Web.UI.Client/src/less/forms.less @@ -29,7 +29,7 @@ label.control-label, .control-label { } -.controls-row label{padding: 0 10px 0 10px; vertical-align: middle;} +.controls-row label:not(.umb-form-check){padding: 0 10px 0 10px; vertical-align: middle;} @@ -68,8 +68,9 @@ label.control-label, .control-label { .form-search .icon, .form-search .icon-search { position: absolute; z-index: 1; - top: 6px; + top: 50%; left: 6px; + transform: translateY(-50%); color: @gray-8; } @@ -113,6 +114,9 @@ label.control-label, .control-label { } } +.form-search .umb-search-field { + width: 100%; +} // GENERAL STYLES // -------------- diff --git a/src/Umbraco.Web.UI.Client/src/less/helveticons.less b/src/Umbraco.Web.UI.Client/src/less/helveticons.less index 82663270e9..a51f4e9f6f 100644 --- a/src/Umbraco.Web.UI.Client/src/less/helveticons.less +++ b/src/Umbraco.Web.UI.Client/src/less/helveticons.less @@ -8,35 +8,57 @@ font-style: normal; } +span[class^="icon-"], +span[class*=" icon-"] { + display: inline-block; + width: 1em; + height: 1em; + *margin-right: .3em; + + svg { + width: 100%; + height: 100%; + fill: currentColor; + } + + &.large{ + width: 32px; + height: 32px; + } + &.medium{ + width: 24px; + height: 24px; + } + &.small{ + width: 14px; + height: 14px; + } +} + [class^="icon-"], -[class*=" icon-"] { - font-family: icomoon; - font-weight: normal; - font-style: normal; - text-decoration: inherit; - -webkit-font-smoothing: antialiased; - *margin-right: .3em; +[class*=" icon-"], +button.icon-trash { + font-family: 'icomoon'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } [class^="icon-"]:before, -[class*=" icon-"]:before { - text-decoration: inherit; - display: inline-block; - speak: none; +[class*=" icon-"]:before, +button.icon-trash { + text-decoration: inherit; + display: inline-block; + speak: none; } -/* -[class^="icon-"]:before, [class*=" icon-"]:before { - font-family: 'icomoon'; - speak: none; - font-weight: normal; - font-style: normal; - display: inline-block; - text-decoration: inherit; - font-size: 14px; - -webkit-font-smoothing: antialiased; -}*/ - i.large{ font-size: 32px; } @@ -47,1834 +69,1838 @@ i.small{ font-size: 14px; } -.icon-zoom-out:before { +i.icon-zoom-out:before { content: "\e000"; } -.icon-truck:before { +i.icon-truck:before { content: "\e001"; } -.icon-zoom-in:before { +i.icon-zoom-in:before { content: "\e002"; } -.icon-zip:before { +i.icon-zip:before { content: "\e003"; } -.icon-axis-rotation:before { +i.icon-axis-rotation:before { content: "\e004"; } -.icon-yen-bag:before { +i.icon-yen-bag:before { content: "\e005"; } -.icon-axis-rotation-2:before { +i.icon-axis-rotation-2:before { content: "\e006"; } -.icon-axis-rotation-3:before { +i.icon-axis-rotation-3:before { content: "\e007"; } -.icon-wrench:before { +i.icon-wrench:before { content: "\e008"; } -.icon-wine-glass:before { +i.icon-wine-glass:before { content: "\e009"; } -.icon-wrong:before { +i.icon-wrong:before { content: "\e00a"; } -.icon-windows:before { +i.icon-windows:before { content: "\e00b"; } -.icon-window-sizes:before { +i.icon-window-sizes:before { content: "\e00c"; } -.icon-window-popin:before { +i.icon-window-popin:before { content: "\e00d"; } -.icon-wifi:before { +i.icon-wifi:before { content: "\e00e"; } -.icon-width:before { +i.icon-width:before { content: "\e00f"; } -.icon-weight:before { +i.icon-weight:before { content: "\e010"; } -.icon-war:before { +i.icon-war:before { content: "\e011"; } -.icon-wand:before { +i.icon-wand:before { content: "\e012"; } -.icon-wallet:before { +i.icon-wallet:before { content: "\e013"; } -.icon-wall-plug:before { +i.icon-wall-plug:before { content: "\e014"; } -.icon-voice:before { +i.icon-voice:before { content: "\e016"; } -.icon-video:before { +i.icon-video:before { content: "\e017"; } -.icon-vcard:before { +i.icon-vcard:before { content: "\e018"; } -.icon-utilities:before { +i.icon-utilities:before { content: "\e019"; } -.icon-users:before { +i.icon-users:before { content: "\e01a"; } -.icon-users-alt:before { +i.icon-users-alt:before { content: "\e01b"; } -.icon-user:before { +i.icon-user:before { content: "\e01c"; } -.icon-user-glasses:before { +i.icon-user-glasses:before { content: "\e01d"; } -.icon-user-females:before { +i.icon-user-females:before { content: "\e01e"; } -.icon-user-females-alt:before { +i.icon-user-females-alt:before { content: "\e01f"; } -.icon-user-female:before { +i.icon-user-female:before { content: "\e020"; } -.icon-usb:before { +i.icon-usb:before { content: "\e021"; } -.icon-usb-connector:before { +i.icon-usb-connector:before { content: "\e022"; } -.icon-unlocked:before { +i.icon-unlocked:before { content: "\e023"; } -.icon-universal:before { +i.icon-universal:before { content: "\e024"; } -.icon-undo:before { +i.icon-undo:before { content: "\e025"; } -.icon-umbrella:before { +i.icon-umbrella:before { content: "\e026"; } -.icon-umb-deploy:before { +i.icon-umb-deploy:before { content: "\e027"; } -.icon-umb-contour:before, .traycontour:before, { +i.icon-umb-contour:before, .traycontour:before { content: "\e028"; } -.icon-umb-settings:before, .traysettings:before, { +i.icon-umb-settings:before, .traysettings:before { content: "\e029"; } -.icon-umb-users:before, .trayuser:before, .trayusers:before{ +i.icon-umb-users:before, .trayuser:before, .trayusers:before{ content: "\e02a"; } -.icon-umb-media:before, .traymedia:before, { +i.icon-umb-media:before, .traymedia:before { content: "\e02b"; } -.icon-umb-content:before, .traycontent:before{ +i.icon-umb-content:before, .traycontent:before{ content: "\e02c"; } -.icon-umb-developer:before, .traydeveloper:before, { +i.icon-umb-developer:before, .traydeveloper:before { content: "\e02d"; } -.icon-umb-members:before, .traymember:before { +i.icon-umb-members:before, .traymember:before { content: "\e015"; } -.icon-umb-translation:before, .traytranslation:before { +i.icon-umb-translation:before, .traytranslation:before { content: "\e1fd"; } -.icon-tv:before { +i.icon-tv:before { content: "\e02e"; } -.icon-tv-old:before { +i.icon-tv-old:before { content: "\e02f"; } -.icon-trophy:before { +i.icon-trophy:before { content: "\e030"; } -.icon-tree:before { +i.icon-tree:before { content: "\e031"; } -.icon-trash:before { +i.icon-trash:before, +button.icon-trash:before { content: "\e032"; } -.icon-trash-alt:before { +i.icon-trash-alt:before, +button.icon-trash-alt:before { content: "\e033"; } -.icon-trash-alt-2:before { +i.icon-trash-alt-2:before, +button.icon-trash-alt-2:before { content: "\e034"; } -.icon-train:before { +i.icon-train:before { content: "\e035"; } -.icon-trafic:before, -.icon-traffic:before { +i.icon-trafic:before, +i.icon-traffic:before { content: "\e036"; } -.icon-traffic-alt:before { +i.icon-traffic-alt:before { content: "\e037"; } -.icon-top:before { +i.icon-top:before { content: "\e038"; } -.icon-tools:before { +i.icon-tools:before { content: "\e039"; } -.icon-timer:before { +i.icon-timer:before { content: "\e03a"; } -.icon-time:before { +i.icon-time:before { content: "\e03b"; } -.icon-t-shirt:before { +i.icon-t-shirt:before { content: "\e03c"; } -.icon-tab-key:before { +i.icon-tab-key:before { content: "\e03d"; } -.icon-tab:before { +i.icon-tab:before { content: "\e03e"; } -.icon-tactics:before { +i.icon-tactics:before { content: "\e03f"; } -.icon-tag:before { +i.icon-tag:before { content: "\e040"; } -.icon-tags:before { +i.icon-tags:before { content: "\e041"; } -.icon-takeaway-cup:before { +i.icon-takeaway-cup:before { content: "\e042"; } -.icon-target:before { +i.icon-target:before { content: "\e043"; } -.icon-temperature-alt:before, -.icon-temperatrure-alt:before { +i.icon-temperature-alt:before, +i.icon-temperatrure-alt:before { content: "\e044"; } -.icon-temperature:before { +i.icon-temperature:before { content: "\e045"; } -.icon-terminal:before { +i.icon-terminal:before { content: "\e046"; } -.icon-theater:before { +i.icon-theater:before { content: "\e047"; } -.icon-thief:before, -.icon-theif:before { +i.icon-thief:before, +i.icon-theif:before { content: "\e048"; } -.icon-thought-bubble:before { +i.icon-thought-bubble:before { content: "\e049"; } -.icon-thumb-down:before { +i.icon-thumb-down:before { content: "\e04a"; } -.icon-thumb-up:before { +i.icon-thumb-up:before { content: "\e04b"; } -.icon-thumbnail-list:before { +i.icon-thumbnail-list:before { content: "\e04c"; } -.icon-thumbnails-small:before { +i.icon-thumbnails-small:before { content: "\e04d"; } -.icon-thumbnails:before { +i.icon-thumbnails:before { content: "\e04e"; } -.icon-ticket:before { +i.icon-ticket:before { content: "\e04f"; } -.icon-sync:before { +i.icon-sync:before { content: "\e050"; } -.icon-sweatshirt:before { +i.icon-sweatshirt:before { content: "\e051"; } -.icon-sunny:before { +i.icon-sunny:before { content: "\e052"; } -.icon-stream:before { +i.icon-stream:before { content: "\e053"; } -.icon-store:before { +i.icon-store:before { content: "\e054"; } -.icon-stop:before { +i.icon-stop:before { content: "\e055"; } -.icon-stop-hand:before { +i.icon-stop-hand:before { content: "\e056"; } -.icon-stop-alt:before { +i.icon-stop-alt:before { content: "\e057"; } -.icon-stamp:before { +i.icon-stamp:before { content: "\e058"; } -.icon-stacked-disks:before { +i.icon-stacked-disks:before { content: "\e059"; } -.icon-ssd:before { +i.icon-ssd:before { content: "\e05a"; } -.icon-squiggly-line:before { +i.icon-squiggly-line:before { content: "\e05b"; } -.icon-sprout:before { +i.icon-sprout:before { content: "\e05c"; } -.icon-split:before { +i.icon-split:before { content: "\e05d"; } -.icon-split-alt:before { +i.icon-split-alt:before { content: "\e05e"; } -.icon-speed-gauge:before { +i.icon-speed-gauge:before { content: "\e05f"; } -.icon-speaker:before { +i.icon-speaker:before { content: "\e060"; } -.icon-sound:before { +i.icon-sound:before { content: "\e061"; } -.icon-spades:before { +i.icon-spades:before { content: "\e062"; } -.icon-sound-waves:before { +i.icon-sound-waves:before { content: "\e063"; } -.icon-shipping-box:before { +i.icon-shipping-box:before { content: "\e064"; } -.icon-shipping:before { +i.icon-shipping:before { content: "\e065"; } -.icon-shoe:before { +i.icon-shoe:before { content: "\e066"; } -.icon-shopping-basket-alt-2:before { +i.icon-shopping-basket-alt-2:before { content: "\e067"; } -.icon-shopping-basket:before { +i.icon-shopping-basket:before { content: "\e068"; } -.icon-shopping-basket-alt:before { +i.icon-shopping-basket-alt:before { content: "\e069"; } -.icon-shorts:before { +i.icon-shorts:before { content: "\e06a"; } -.icon-shuffle:before { +i.icon-shuffle:before { content: "\e06b"; } -.icon-science:before, -.icon-sience:before { +i.icon-science:before, +i.icon-sience:before { content: "\e06c"; } -.icon-simcard:before { +i.icon-simcard:before { content: "\e06d"; } -.icon-single-note:before { +i.icon-single-note:before { content: "\e06e"; } -.icon-sitemap:before { +i.icon-sitemap:before { content: "\e06f"; } -.icon-sleep:before { +i.icon-sleep:before { content: "\e070"; } -.icon-slideshow:before { +i.icon-slideshow:before { content: "\e071"; } -.icon-smiley-inverted:before { +i.icon-smiley-inverted:before { content: "\e072"; } -.icon-smiley:before { +i.icon-smiley:before { content: "\e073"; } -.icon-snow:before { +i.icon-snow:before { content: "\e074"; } -.icon-sound-low:before { +i.icon-sound-low:before { content: "\e075"; } -.icon-sound-medium:before { +i.icon-sound-medium:before { content: "\e076"; } -.icon-sound-off:before { +i.icon-sound-off:before { content: "\e077"; } -.icon-shift:before { +i.icon-shift:before { content: "\e078"; } -.icon-shield:before { +i.icon-shield:before { content: "\e079"; } -.icon-sharing-iphone:before { +i.icon-sharing-iphone:before { content: "\e07a"; } -.icon-share:before { +i.icon-share:before { content: "\e07b"; } -.icon-share-alt:before { +i.icon-share-alt:before { content: "\e07c"; } -.icon-share-alt-2:before { +i.icon-share-alt-2:before { content: "\e07d"; } -.icon-settings:before { +i.icon-settings:before, +button.icon-settings:before { content: "\e07e"; } -.icon-settings-alt:before { +i.icon-settings-alt:before { content: "\e07f"; } -.icon-settings-alt-2:before { +i.icon-settings-alt-2:before { content: "\e080"; } -.icon-server:before { +i.icon-server:before { content: "\e081"; } -.icon-server-alt:before { +i.icon-server-alt:before { content: "\e082"; } -.icon-sensor:before { +i.icon-sensor:before { content: "\e083"; } -.icon-security-camera:before { +i.icon-security-camera:before { content: "\e084"; } -.icon-search:before { +i.icon-search:before { content: "\e085"; } -.icon-scull:before { +i.icon-scull:before { content: "\e086"; } -.icon-script:before { +i.icon-script:before { content: "\e087"; } -.icon-script-alt:before { +i.icon-script-alt:before { content: "\e088"; } -.icon-screensharing:before { +i.icon-screensharing:before { content: "\e089"; } -.icon-school:before { +i.icon-school:before { content: "\e08a"; } -.icon-scan:before { +i.icon-scan:before { content: "\e08b"; } -.icon-refresh:before { +i.icon-refresh:before { content: "\e08c"; } -.icon-remote:before { +i.icon-remote:before { content: "\e08d"; } -.icon-remove:before { +i.icon-remove:before { content: "\e08e"; } -.icon-repeat-one:before { +i.icon-repeat-one:before { content: "\e08f"; } -.icon-repeat:before { +i.icon-repeat:before { content: "\e090"; } -.icon-resize:before { +i.icon-resize:before { content: "\e091"; } -.icon-reply-arrow:before { +i.icon-reply-arrow:before { content: "\e092"; } -.icon-return-to-top:before { +i.icon-return-to-top:before { content: "\e093"; } -.icon-right-double-arrow:before { +i.icon-right-double-arrow:before { content: "\e094"; } -.icon-road:before { +i.icon-road:before { content: "\e095"; } -.icon-roadsign:before { +i.icon-roadsign:before { content: "\e096"; } -.icon-rocket:before { +i.icon-rocket:before { content: "\e097"; } -.icon-rss:before { +i.icon-rss:before { content: "\e098"; } -.icon-ruler-alt:before { +i.icon-ruler-alt:before { content: "\e099"; } -.icon-ruler:before { +i.icon-ruler:before { content: "\e09a"; } -.icon-sandbox-toys:before { +i.icon-sandbox-toys:before { content: "\e09b"; } -.icon-satellite-dish:before { +i.icon-satellite-dish:before { content: "\e09c"; } -.icon-save:before { +i.icon-save:before { content: "\e09d"; } -.icon-safedial:before { +i.icon-safedial:before { content: "\e09e"; } -.icon-safe:before { +i.icon-safe:before { content: "\e09f"; } -.icon-redo:before { +i.icon-redo:before { content: "\e0a0"; } -.icon-printer-alt:before { +i.icon-printer-alt:before { content: "\e0a1"; } -.icon-planet:before { +i.icon-planet:before { content: "\e0a2"; } -.icon-paste-in:before { +i.icon-paste-in:before { content: "\e0a3"; } -.icon-os-x:before { +i.icon-os-x:before { content: "\e0a4"; } -.icon-navigation-left:before { +i.icon-navigation-left:before { content: "\e0a5"; } -.icon-message:before { +i.icon-message:before { content: "\e0a6"; } -.icon-lock:before { +i.icon-lock:before { content: "\e0a7"; } -.icon-layers-alt:before { +i.icon-layers-alt:before { content: "\e0a8"; } -.icon-record:before { +i.icon-record:before { content: "\e0a9"; } -.icon-print:before { +i.icon-print:before { content: "\e0aa"; } -.icon-plane:before { +i.icon-plane:before { content: "\e0ab"; } -.icon-partly-cloudy:before { +i.icon-partly-cloudy:before { content: "\e0ac"; } -.icon-ordered-list:before { +i.icon-ordered-list:before { content: "\e0ad"; } -.icon-navigation-last:before { +i.icon-navigation-last:before { content: "\e0ae"; } -.icon-message-unopened:before { +i.icon-message-unopened:before { content: "\e0af"; } -.icon-location-nearby:before { +i.icon-location-nearby:before { content: "\e0b0"; } -.icon-laptop:before { +i.icon-laptop:before { content: "\e0b1"; } -.icon-reception:before { +i.icon-reception:before { content: "\e0b2"; } -.icon-price-yen:before { +i.icon-price-yen:before { content: "\e0b3"; } -.icon-piracy:before { +i.icon-piracy:before { content: "\e0b4"; } -.icon-parental-control:before { +i.icon-parental-control:before { content: "\e0b5"; } -.icon-operator:before { +i.icon-operator:before { content: "\e0b6"; } -.icon-navigation-horizontal:before { +i.icon-navigation-horizontal:before { content: "\e0b7"; } -.icon-message-open:before { +i.icon-message-open:before { content: "\e0b8"; } -.icon-lab:before { +i.icon-lab:before { content: "\e0b9"; } -.icon-location-near-me:before { +i.icon-location-near-me:before { content: "\e0ba"; } -.icon-receipt-yen:before { +i.icon-receipt-yen:before { content: "\e0bb"; } -.icon-price-pound:before { +i.icon-price-pound:before { content: "\e0bc"; } -.icon-pin-location:before { +i.icon-pin-location:before { content: "\e0bd"; } -.icon-parachute-drop:before { +i.icon-parachute-drop:before { content: "\e0be"; } -.icon-old-phone:before { +i.icon-old-phone:before { content: "\e0bf"; } -.icon-merge:before { +i.icon-merge:before { content: "\e0c0"; } -.icon-navigation-first:before { +i.icon-navigation-first:before { content: "\e0c1"; } -.icon-locate:before { +i.icon-locate:before { content: "\e0c2"; } -.icon-keyhole:before { +i.icon-keyhole:before { content: "\e0c3"; } -.icon-receipt-pound:before { +i.icon-receipt-pound:before { content: "\e0c4"; } -.icon-price-euro:before { +i.icon-price-euro:before { content: "\e0c5"; } -.icon-piggy-bank:before { +i.icon-piggy-bank:before { content: "\e0c6"; } -.icon-paper-plane:before { +i.icon-paper-plane:before { content: "\e0c7"; } -.icon-old-key:before { +i.icon-old-key:before { content: "\e0c8"; } -.icon-navigation-down:before { +i.icon-navigation-down:before { content: "\e0c9"; } -.icon-megaphone:before { +i.icon-megaphone:before { content: "\e0ca"; } -.icon-loading:before { +i.icon-loading:before { content: "\e0cb"; } -.icon-keychain:before { +i.icon-keychain:before { content: "\e0cc"; } -.icon-receipt-euro:before { +i.icon-receipt-euro:before { content: "\e0cd"; } -.icon-price-dollar:before { +i.icon-price-dollar:before { content: "\e0ce"; } -.icon-pie-chart:before { +i.icon-pie-chart:before { content: "\e0cf"; } -.icon-paper-plane-alt:before { +i.icon-paper-plane-alt:before { content: "\e0d0"; } -.icon-notepad:before { +i.icon-notepad:before { content: "\e0d1"; } -.icon-navigation-bottom:before { +i.icon-navigation-bottom:before { content: "\e0d2"; } -.icon-meeting:before { +i.icon-meeting:before { content: "\e0d3"; } -.icon-keyboard:before { +i.icon-keyboard:before { content: "\e0d4"; } -.icon-load:before { +i.icon-load:before { content: "\e0d5"; } -.icon-receipt-dollar:before { +i.icon-receipt-dollar:before { content: "\e0d6"; } -.icon-previous:before { +i.icon-previous:before { content: "\e0d7"; } -.icon-pictures:before { +i.icon-pictures:before { content: "\e0d8"; } -.icon-notepad-alt:before { +i.icon-notepad-alt:before { content: "\e0d9"; } -.icon-paper-bag:before { +i.icon-paper-bag:before { content: "\e0da"; } -.icon-name-badge:before { +i.icon-badge:before { content: "\e0db"; } -.icon-medicine:before { +i.icon-medicine:before { content: "\e0dc"; } -.icon-list:before { +i.icon-list:before { content: "\e0dd"; } -.icon-key:before { +i.icon-key:before { content: "\e0de"; } -.icon-receipt-alt:before { +i.icon-receipt-alt:before { content: "\e0df"; } -.icon-previous-media:before { +i.icon-previous-media:before { content: "\e0e0"; } -.icon-pictures-alt:before { +i.icon-pictures-alt:before { content: "\e0e1"; } -.icon-pants:before { +i.icon-pants:before { content: "\e0e2"; } -.icon-nodes:before { +i.icon-nodes:before { content: "\e0e3"; } -.icon-music:before { +i.icon-music:before { content: "\e0e4"; } -.icon-readonly:before { +i.icon-readonly:before { content: "\e0e5"; } -.icon-presentation:before { +i.icon-presentation:before { content: "\e0e6"; } -.icon-pictures-alt-2:before { +i.icon-pictures-alt-2:before { content: "\e0e7"; } -.icon-panel-close:before, -.icon-pannel-close:before { +i.icon-panel-close:before, +i.icon-pannel-close:before { content: "\e0e8"; } -.icon-next:before { +i.icon-next:before { content: "\e0e9"; } -.icon-multiple-windows:before { +i.icon-multiple-windows:before { content: "\e0ea"; } -.icon-medical-emergency:before { +i.icon-medical-emergency:before { content: "\e0eb"; } -.icon-medal:before { +i.icon-medal:before { content: "\e0ec"; } -.icon-link:before { +i.icon-link:before { content: "\e0ed"; } -.icon-linux-tux:before { +i.icon-linux-tux:before { content: "\e0ee"; } -.icon-junk:before { +i.icon-junk:before { content: "\e0ef"; } -.icon-item-arrangement:before { +i.icon-item-arrangement:before { content: "\e0f0"; } -.icon-iphone:before { +i.icon-iphone:before { content: "\e0f1"; } -.icon-lightning:before { +i.icon-lightning:before { content: "\e0f2"; } -.icon-map:before { +i.icon-map:before { content: "\e0f3"; } -.icon-multiple-credit-cards:before { +i.icon-multiple-credit-cards:before { content: "\e0f4"; } -.icon-next-media:before { +i.icon-next-media:before { content: "\e0f5"; } -.icon-panel-show:before { +i.icon-panel-show:before { content: "\e0f6"; } -.icon-picture:before { +i.icon-picture:before { content: "\e0f7"; } -.icon-power:before { +i.icon-power:before { content: "\e0f8"; } -.icon-re-post:before { +i.icon-re-post:before { content: "\e0f9"; } -.icon-rate:before { +i.icon-rate:before { content: "\e0fa"; } -.icon-rain:before { +i.icon-rain:before { content: "\e0fb"; } -.icon-radio:before { +i.icon-radio:before { content: "\e0fc"; } -.icon-radio-receiver:before { +i.icon-radio-receiver:before { content: "\e0fd"; } -.icon-radio-alt:before { +i.icon-radio-alt:before { content: "\e0fe"; } -.icon-quote:before { +i.icon-quote:before { content: "\e0ff"; } -.icon-qr-code:before { +i.icon-qr-code:before { content: "\e100"; } -.icon-pushpin:before { +i.icon-pushpin:before { content: "\e101"; } -.icon-pulse:before { +i.icon-pulse:before { content: "\e102"; } -.icon-projector:before { +i.icon-projector:before { content: "\e103"; } -.icon-play:before { +i.icon-play:before { content: "\e104"; } -.icon-playing-cards:before { +i.icon-playing-cards:before { content: "\e105"; } -.icon-playlist:before { +i.icon-playlist:before { content: "\e106"; } -.icon-plugin:before { +i.icon-plugin:before { content: "\e107"; } -.icon-podcast:before { +i.icon-podcast:before { content: "\e108"; } -.icon-poker-chip:before { +i.icon-poker-chip:before { content: "\e109"; } -.icon-poll:before { +i.icon-poll:before { content: "\e10a"; } -.icon-post-it:before { +i.icon-post-it:before { content: "\e10b"; } -.icon-pound-bag:before { +i.icon-pound-bag:before { content: "\e10c"; } -.icon-power-outlet:before { +i.icon-power-outlet:before { content: "\e10d"; } -.icon-photo-album:before { +i.icon-photo-album:before { content: "\e10e"; } -.icon-phone:before { +i.icon-phone:before { content: "\e10f"; } -.icon-phone-ring:before { +i.icon-phone-ring:before { content: "\e110"; } -.icon-people:before { +i.icon-people:before { content: "\e111"; } -.icon-people-female:before { +i.icon-people-female:before { content: "\e112"; } -.icon-people-alt:before { +i.icon-people-alt:before { content: "\e113"; } -.icon-people-alt-2:before { +i.icon-people-alt-2:before { content: "\e114"; } -.icon-pc:before { +i.icon-pc:before { content: "\e115"; } -.icon-pause:before { +i.icon-pause:before { content: "\e116"; } -.icon-path:before { +i.icon-path:before { content: "\e117"; } -.icon-out:before { +i.icon-out:before { content: "\e118"; } -.icon-outbox:before { +i.icon-outbox:before { content: "\e119"; } -.icon-outdent:before { +i.icon-outdent:before { content: "\e11a"; } -.icon-page-add:before { +i.icon-page-add:before { content: "\e11b"; } -.icon-page-down:before { +i.icon-page-down:before { content: "\e11c"; } -.icon-page-remove:before { +i.icon-page-remove:before { content: "\e11d"; } -.icon-page-restricted:before { +i.icon-page-restricted:before { content: "\e11e"; } -.icon-page-up:before { +i.icon-page-up:before { content: "\e11f"; } -.icon-paint-roller:before { +i.icon-paint-roller:before { content: "\e120"; } -.icon-palette:before { +i.icon-palette:before { content: "\e121"; } -.icon-newspaper:before { +i.icon-newspaper:before { content: "\e122"; } -.icon-newspaper-alt:before { +i.icon-newspaper-alt:before { content: "\e123"; } -.icon-network-alt:before { +i.icon-network-alt:before { content: "\e124"; } -.icon-navigational-arrow:before { +i.icon-navigational-arrow:before { content: "\e125"; } -.icon-navigation:before { +i.icon-navigation:before { content: "\e126"; } -.icon-navigation-vertical:before { +i.icon-navigation-vertical:before { content: "\e127"; } -.icon-navigation-up:before { +i.icon-navigation-up:before { content: "\e128"; } -.icon-navigation-top:before { +i.icon-navigation-top:before { content: "\e129"; } -.icon-navigation-road:before { +i.icon-navigation-road:before { content: "\e12a"; } -.icon-navigation-right:before { +i.icon-navigation-right:before { content: "\e12b"; } -.icon-microscope:before { +i.icon-microscope:before { content: "\e12c"; } -.icon-mindmap:before { +i.icon-mindmap:before { content: "\e12d"; } -.icon-molecular-network:before { +i.icon-molecular-network:before { content: "\e12e"; } -.icon-molecular:before { +i.icon-molecular:before { content: "\e12f"; } -.icon-mountain:before { +i.icon-mountain:before { content: "\e130"; } -.icon-mouse-cursor:before { +i.icon-mouse-cursor:before { content: "\e131"; } -.icon-mouse:before { +i.icon-mouse:before { content: "\e132"; } -.icon-movie-alt:before { +i.icon-movie-alt:before { content: "\e133"; } -.icon-map-marker:before { +i.icon-map-marker:before { content: "\e134"; } -.icon-movie:before { +i.icon-movie:before { content: "\e135"; } -.icon-map-location:before { +i.icon-map-location:before { content: "\e136"; } -.icon-map-alt:before { +i.icon-map-alt:before { content: "\e137"; } -.icon-male-symbol:before { +i.icon-male-symbol:before { content: "\e138"; } -.icon-male-and-female:before { +i.icon-male-and-female:before { content: "\e139"; } -.icon-mailbox:before { +i.icon-mailbox:before { content: "\e13a"; } -.icon-magnet:before { +i.icon-magnet:before { content: "\e13b"; } -.icon-loupe:before { +i.icon-loupe:before { content: "\e13c"; } -.icon-mobile:before { +i.icon-mobile:before { content: "\e13d"; } -.icon-logout:before { +i.icon-logout:before { content: "\e13e"; } -.icon-log-out:before { +i.icon-log-out:before { content: "\e13f"; } -.icon-layers:before { +i.icon-layers:before { content: "\e140"; } -.icon-left-double-arrow:before { +i.icon-left-double-arrow:before { content: "\e141"; } -.icon-layout:before { +i.icon-layout:before { content: "\e142"; } -.icon-legal:before { +i.icon-legal:before { content: "\e143"; } -.icon-lense:before { +i.icon-lense:before { content: "\e144"; } -.icon-library:before { +i.icon-library:before { content: "\e145"; } -.icon-light-down:before { +i.icon-light-down:before { content: "\e146"; } -.icon-light-up:before { +i.icon-light-up:before { content: "\e147"; } -.icon-lightbulb-active:before { +i.icon-lightbulb-active:before { content: "\e148"; } -.icon-lightbulb:before { +i.icon-lightbulb:before { content: "\e149"; } -.icon-ipad:before { +i.icon-ipad:before { content: "\e14a"; } -.icon-invoice:before { +i.icon-invoice:before { content: "\e14b"; } -.icon-info:before { +i.icon-info:before { content: "\e14c"; } -.icon-infinity:before { +i.icon-infinity:before { content: "\e14d"; } -.icon-indent:before { +i.icon-indent:before { content: "\e14e"; } -.icon-inbox:before { +i.icon-inbox:before { content: "\e14f"; } -.icon-inbox-full:before { +i.icon-inbox-full:before { content: "\e150"; } -.icon-inactive-line:before { +i.icon-inactive-line:before { content: "\e151"; } -.icon-imac:before { +i.icon-imac:before { content: "\e152"; } -.icon-hourglass:before { +i.icon-hourglass:before { content: "\e153"; } -.icon-home:before { +i.icon-home:before { content: "\e154"; } -.icon-grid:before { +i.icon-grid:before { content: "\e155"; } -.icon-food:before { +i.icon-food:before { content: "\e156"; } -.icon-favorite:before { +i.icon-favorite:before { content: "\e157"; } -.icon-door-open-alt:before { +i.icon-door-open-alt:before { content: "\e158"; } -.icon-diagnostics:before { +i.icon-diagnostics:before { content: "\e159"; } -.icon-contrast:before { +i.icon-contrast:before { content: "\e15a"; } -.icon-coins-dollar-alt:before { +i.icon-coins-dollar-alt:before { content: "\e15b"; } -.icon-circle-dotted-active:before { +i.icon-circle-dotted-active:before { content: "\e15c"; } -.icon-cinema:before { +i.icon-cinema:before { content: "\e15d"; } -.icon-chip:before { +i.icon-chip:before { content: "\e15e"; } -.icon-chip-alt:before { +i.icon-chip-alt:before { content: "\e15f"; } -.icon-chess:before { +i.icon-chess:before { content: "\e160"; } -.icon-checkbox:before { +i.icon-checkbox:before { content: "\e161"; } -.icon-checkbox-empty:before { +i.icon-checkbox-empty:before { content: "\e162"; } -.icon-checkbox-dotted:before { +i.icon-checkbox-dotted:before { content: "\e163"; } -.icon-checkbox-dotted-active:before { +i.icon-checkbox-dotted-active:before { content: "\e164"; } -.icon-check:before { +i.icon-check:before { content: "\e165"; } -.icon-chat:before { +i.icon-chat:before { content: "\e166"; } -.icon-chat-active:before { +i.icon-chat-active:before { content: "\e167"; } -.icon-chart:before { +i.icon-chart:before { content: "\e168"; } -.icon-chart-curve:before { +i.icon-chart-curve:before { content: "\e169"; } -.icon-certificate:before { +i.icon-certificate:before { content: "\e16a"; } -.icon-categories:before { +i.icon-categories:before { content: "\e16b"; } -.icon-cash-register:before { +i.icon-cash-register:before { content: "\e16c"; } -.icon-car:before { +i.icon-car:before { content: "\e16d"; } -.icon-caps-lock:before { +i.icon-caps-lock:before { content: "\e16e"; } -.icon-candy:before { +i.icon-candy:before { content: "\e16f"; } -.icon-circle-dotted:before { +i.icon-circle-dotted:before { content: "\e170"; } -.icon-circuits:before { +i.icon-circuits:before { content: "\e171"; } -.icon-circus:before { +i.icon-circus:before { content: "\e172"; } -.icon-client:before { +i.icon-client:before { content: "\e173"; } -.icon-clothes-hanger:before { +i.icon-clothes-hanger:before { content: "\e174"; } -.icon-cloud-drive:before { +i.icon-cloud-drive:before { content: "\e175"; } -.icon-cloud-upload:before { +i.icon-cloud-upload:before { content: "\e176"; } -.icon-cloud:before { +i.icon-cloud:before { content: "\e177"; } -.icon-cloudy:before { +i.icon-cloudy:before { content: "\e178"; } -.icon-clubs:before { +i.icon-clubs:before { content: "\e179"; } -.icon-cocktail:before { +i.icon-cocktail:before { content: "\e17a"; } -.icon-code:before { +i.icon-code:before { content: "\e17b"; } -.icon-coffee:before { +i.icon-coffee:before { content: "\e17c"; } -.icon-coin-dollar:before { +i.icon-coin-dollar:before { content: "\e17d"; } -.icon-coin-pound:before { +i.icon-coin-pound:before { content: "\e17e"; } -.icon-coin-yen:before { +i.icon-coin-yen:before { content: "\e17f"; } -.icon-coin:before { +i.icon-coin:before { content: "\e180"; } -.icon-coins-alt:before { +i.icon-coins-alt:before { content: "\e181"; } -.icon-console:before { +i.icon-console:before { content: "\e182"; } -.icon-connection:before { +i.icon-connection:before { content: "\e183"; } -.icon-compress:before { +i.icon-compress:before { content: "\e184"; } -.icon-company:before { +i.icon-company:before { content: "\e185"; } -.icon-command:before { +i.icon-command:before { content: "\e186"; } -.icon-coin-euro:before { +i.icon-coin-euro:before { content: "\e187"; } -.icon-combination-lock:before { +i.icon-combination-lock:before { content: "\e188"; } -.icon-combination-lock-open:before { +i.icon-combination-lock-open:before { content: "\e189"; } -.icon-comb:before { +i.icon-comb:before { content: "\e18a"; } -.icon-columns:before { +i.icon-columns:before { content: "\e18b"; } -.icon-colorpicker:before { +i.icon-colorpicker:before { content: "\e18c"; } -.icon-color-bucket:before { +i.icon-color-bucket:before { content: "\e18d"; } -.icon-coins:before { +i.icon-coins:before { content: "\e18e"; } -.icon-coins-yen:before { +i.icon-coins-yen:before { content: "\e18f"; } -.icon-coins-yen-alt:before { +i.icon-coins-yen-alt:before { content: "\e190"; } -.icon-coins-pound:before { +i.icon-coins-pound:before { content: "\e191"; } -.icon-coins-pound-alt:before { +i.icon-coins-pound-alt:before { content: "\e192"; } -.icon-coins-euro:before { +i.icon-coins-euro:before { content: "\e193"; } -.icon-coins-euro-alt:before { +i.icon-coins-euro-alt:before { content: "\e194"; } -.icon-coins-dollar:before { +i.icon-coins-dollar:before { content: "\e195"; } -.icon-conversation-alt:before { +i.icon-conversation-alt:before { content: "\e196"; } -.icon-conversation:before { +i.icon-conversation:before { content: "\e197"; } -.icon-coverflow:before { +i.icon-coverflow:before { content: "\e198"; } -.icon-credit-card-alt:before { +i.icon-credit-card-alt:before { content: "\e199"; } -.icon-credit-card:before { +i.icon-credit-card:before { content: "\e19a"; } -.icon-crop:before { +i.icon-crop:before { content: "\e19b"; } -.icon-crosshair:before { +i.icon-crosshair:before { content: "\e19c"; } -.icon-crown-alt:before { +i.icon-crown-alt:before { content: "\e19d"; } -.icon-crown:before { +i.icon-crown:before { content: "\e19e"; } -.icon-cupcake:before { +i.icon-cupcake:before { content: "\e19f"; } -.icon-curve:before { +i.icon-curve:before { content: "\e1a0"; } -.icon-cut:before { +i.icon-cut:before { content: "\e1a1"; } -.icon-dashboard:before { +i.icon-dashboard:before { content: "\e1a2"; } -.icon-defrag:before { +i.icon-defrag:before { content: "\e1a3"; } -.icon-delete:before { +i.icon-delete:before { content: "\e1a4"; } -.icon-delete-key:before { +i.icon-delete-key:before { content: "\e1a5"; } -.icon-departure:before { +i.icon-departure:before { content: "\e1a6"; } -.icon-desk:before { +i.icon-desk:before { content: "\e1a7"; } -.icon-desktop:before { +i.icon-desktop:before { content: "\e1a8"; } -.icon-donate:before { +i.icon-donate:before { content: "\e1a9"; } -.icon-dollar-bag:before { +i.icon-dollar-bag:before { content: "\e1aa"; } -.icon-documents:before { +i.icon-documents:before { content: "\e1ab"; } -.icon-document:before { +i.icon-document:before { content: "\e1ac"; } -.icon-document-dashed-line:before { +i.icon-document-dashed-line:before { content: "\e1ad"; } -.icon-dock-connector:before { +i.icon-dock-connector:before { content: "\e1ae"; } -.icon-dna:before { +i.icon-dna:before { content: "\e1af"; } -.icon-display:before { +i.icon-display:before { content: "\e1b0"; } -.icon-disk-image:before { +i.icon-disk-image:before { content: "\e1b1"; } -.icon-disc:before { +i.icon-disc:before { content: "\e1b2"; } -.icon-directions:before { +i.icon-directions:before { content: "\e1b3"; } -.icon-directions-alt:before { +i.icon-directions-alt:before { content: "\e1b4"; } -.icon-diploma:before { +i.icon-diploma:before { content: "\e1b5"; } -.icon-diploma-alt:before { +i.icon-diploma-alt:before { content: "\e1b6"; } -.icon-dice:before { +i.icon-dice:before { content: "\e1b7"; } -.icon-diamonds:before { +i.icon-diamonds:before { content: "\e1b8"; } -.icon-diamond:before { +i.icon-diamond:before { content: "\e1b9"; } -.icon-diagonal-arrow:before { +i.icon-diagonal-arrow:before { content: "\e1ba"; } -.icon-diagonal-arrow-alt:before { +i.icon-diagonal-arrow-alt:before { content: "\e1bb"; } -.icon-door-open:before { +i.icon-door-open:before { content: "\e1bc"; } -.icon-download-alt:before { +i.icon-download-alt:before { content: "\e1bd"; } -.icon-download:before { +i.icon-download:before { content: "\e1be"; } -.icon-drop:before { +i.icon-drop:before { content: "\e1bf"; } -.icon-eco:before { +i.icon-eco:before { content: "\e1c0"; } -.icon-economy:before { +i.icon-economy:before { content: "\e1c1"; } -.icon-edit:before { +i.icon-edit:before { content: "\e1c2"; } -.icon-eject:before { +i.icon-eject:before { content: "\e1c3"; } -.icon-employee:before { +i.icon-employee:before { content: "\e1c4"; } -.icon-energy-saving-bulb:before { +i.icon-energy-saving-bulb:before { content: "\e1c5"; } -.icon-enter:before { +i.icon-enter:before { content: "\e1c6"; } -.icon-equalizer:before { +i.icon-equalizer:before { content: "\e1c7"; } -.icon-escape:before { +i.icon-escape:before { content: "\e1c8"; } -.icon-ethernet:before { +i.icon-ethernet:before { content: "\e1c9"; } -.icon-euro-bag:before { +i.icon-euro-bag:before { content: "\e1ca"; } -.icon-exit-fullscreen:before { +i.icon-exit-fullscreen:before { content: "\e1cb"; } -.icon-eye:before { +i.icon-eye:before { content: "\e1cc"; } -.icon-facebook-like:before { +i.icon-facebook-like:before { content: "\e1cd"; } -.icon-factory:before { +i.icon-factory:before { content: "\e1ce"; } -.icon-font:before { +i.icon-font:before { content: "\e1cf"; } -.icon-folders:before { +i.icon-folders:before { content: "\e1d0"; } -.icon-folder:before, .icon-folder-close:before { +i.icon-folder:before, i.icon-folder-close:before { content: "\e1d1"; } -.icon-folder-outline:before { +i.icon-folder-outline:before { content: "\e1d2"; } -.icon-folder-open:before { +i.icon-folder-open:before { content: "\e1d3"; } -.icon-flowerpot:before { +i.icon-flowerpot:before { content: "\e1d4"; } -.icon-flashlight:before { +i.icon-flashlight:before { content: "\e1d5"; } -.icon-flash:before { +i.icon-flash:before { content: "\e1d6"; } -.icon-flag:before { +i.icon-flag:before { content: "\e1d7"; } -.icon-flag-alt:before { +i.icon-flag-alt:before { content: "\e1d8"; } -.icon-firewire:before { +i.icon-firewire:before { content: "\e1d9"; } -.icon-firewall:before { +i.icon-firewall:before { content: "\e1da"; } -.icon-fire:before { +i.icon-fire:before { content: "\e1db"; } -.icon-fingerprint:before { +i.icon-fingerprint:before { content: "\e1dc"; } -.icon-filter:before { +i.icon-filter:before { content: "\e1dd"; } -.icon-filter-arrows:before { +i.icon-filter-arrows:before { content: "\e1de"; } -.icon-files:before { +i.icon-files:before { content: "\e1df"; } -.icon-file-cabinet:before { +i.icon-file-cabinet:before { content: "\e1e0"; } -.icon-female-symbol:before { +i.icon-female-symbol:before { content: "\e1e1"; } -.icon-footprints:before { +i.icon-footprints:before { content: "\e1e2"; } -.icon-hammer:before { +i.icon-hammer:before { content: "\e1e3"; } -.icon-hand-active-alt:before { +i.icon-hand-active-alt:before { content: "\e1e4"; } -.icon-forking:before { +i.icon-forking:before { content: "\e1e5"; } -.icon-hand-active:before { +i.icon-hand-active:before { content: "\e1e6"; } -.icon-hand-pointer-alt:before { +i.icon-hand-pointer-alt:before { content: "\e1e7"; } -.icon-hand-pointer:before { +i.icon-hand-pointer:before { content: "\e1e8"; } -.icon-handprint:before { +i.icon-handprint:before { content: "\e1e9"; } -.icon-handshake:before { +i.icon-handshake:before { content: "\e1ea"; } -.icon-handtool:before { +i.icon-handtool:before { content: "\e1eb"; } -.icon-hard-drive:before { +i.icon-hard-drive:before { content: "\e1ec"; } -.icon-help:before { +i.icon-help:before { content: "\e1ed"; } -.icon-graduate:before { +i.icon-graduate:before { content: "\e1ee"; } -.icon-gps:before { +i.icon-gps:before { content: "\e1ef"; } -.icon-help-alt:before { +i.icon-help-alt:before { content: "\e1f0"; } -.icon-height:before { +i.icon-height:before { content: "\e1f1"; } -.icon-globe:before { +i.icon-globe:before { content: "\e1f2"; } -.icon-hearts:before { +i.icon-hearts:before { content: "\e1f3"; } -.icon-globe-inverted-europe-africa:before { +i.icon-globe-inverted-europe-africa:before { content: "\e1f4"; } -.icon-headset:before { +i.icon-headset:before { content: "\e1f5"; } -.icon-globe-inverted-asia:before { +i.icon-globe-inverted-asia:before { content: "\e1f6"; } -.icon-headphones:before { +i.icon-headphones:before { content: "\e1f7"; } -.icon-globe-inverted-america:before { +i.icon-globe-inverted-america:before { content: "\e1f8"; } -.icon-hd:before { +i.icon-hd:before { content: "\e1f9"; } -.icon-globe-europe-africa:before, -.icon-globe-europe---africa:before { +i.icon-globe-europe-africa:before, +i.icon-globe-europe---africa:before { content: "\e1fa"; } -.icon-hat:before { +i.icon-hat:before { content: "\e1fb"; } -.icon-globe-asia:before { +i.icon-globe-asia:before { content: "\e1fc"; } -.icon-globe-alt:before { +i.icon-globe-alt:before { content: "\e1fd"; } -.icon-hard-drive-alt:before { +i.icon-hard-drive-alt:before { content: "\e1fe"; } -.icon-glasses:before { +i.icon-glasses:before { content: "\e1ff"; } -.icon-gift:before { +i.icon-gift:before { content: "\e200"; } -.icon-handtool-alt:before { +i.icon-handtool-alt:before { content: "\e201"; } -.icon-geometry:before { +i.icon-geometry:before { content: "\e202"; } -.icon-game:before { +i.icon-game:before { content: "\e203"; } -.icon-fullscreen:before { +i.icon-fullscreen:before { content: "\e204"; } -.icon-fullscreen-alt:before { +i.icon-fullscreen-alt:before { content: "\e205"; } -.icon-frame:before { +i.icon-frame:before { content: "\e206"; } -.icon-frame-alt:before { +i.icon-frame-alt:before { content: "\e207"; } -.icon-camera-roll:before { +i.icon-camera-roll:before { content: "\e208"; } -.icon-bookmark:before { +i.icon-bookmark:before { content: "\e209"; } -.icon-bill:before { +i.icon-bill:before { content: "\e20a"; } -.icon-baby-stroller:before { +i.icon-baby-stroller:before { content: "\e20b"; } -.icon-alarm-clock:before { +i.icon-alarm-clock:before { content: "\e20c"; } -.icon-addressbook:before, -.icon-adressbook:before { +i.icon-addressbook:before, +i.icon-adressbook:before { content: "\e20d"; } -.icon-add:before { +i.icon-add:before { content: "\e20e"; } -.icon-activity:before { +i.icon-activity:before { content: "\e20f"; } -.icon-untitled:before { +i.icon-untitled:before { content: "\e210"; } -.icon-glasses:before { +i.icon-glasses:before { content: "\e211"; } -.icon-camcorder:before { +i.icon-camcorder:before { content: "\e212"; } -.icon-calendar:before { +i.icon-calendar:before { content: "\e213"; } -.icon-calendar-alt:before { +i.icon-calendar-alt:before { content: "\e214"; } -.icon-calculator:before { +i.icon-calculator:before { content: "\e215"; } -.icon-bus:before { +i.icon-bus:before { content: "\e216"; } -.icon-burn:before { +i.icon-burn:before { content: "\e217"; } -.icon-bulleted-list:before { +i.icon-bulleted-list:before { content: "\e218"; } -.icon-bug:before { +i.icon-bug:before { content: "\e219"; } -.icon-brush:before { +i.icon-brush:before { content: "\e21a"; } -.icon-brush-alt:before { +i.icon-brush-alt:before { content: "\e21b"; } -.icon-brush-alt-2:before { +i.icon-brush-alt-2:before { content: "\e21c"; } -.icon-browser-window:before { +i.icon-browser-window:before { content: "\e21d"; } -.icon-briefcase:before { +i.icon-briefcase:before { content: "\e21e"; } -.icon-brick:before { +i.icon-brick:before { content: "\e21f"; } -.icon-brackets:before { +i.icon-brackets:before { content: "\e220"; } -.icon-box:before { +i.icon-box:before { content: "\e221"; } -.icon-box-open:before { +i.icon-box-open:before { content: "\e222"; } -.icon-box-alt:before { +i.icon-box-alt:before { content: "\e223"; } -.icon-books:before { +i.icon-books:before { content: "\e224"; } -.icon-billboard:before { +i.icon-billboard:before { content: "\e225"; } -.icon-bills-dollar:before { +i.icon-bills-dollar:before { content: "\e226"; } -.icon-bills-euro:before { +i.icon-bills-euro:before { content: "\e227"; } -.icon-bills-pound:before { +i.icon-bills-pound:before { content: "\e228"; } -.icon-bills-yen:before { +i.icon-bills-yen:before { content: "\e229"; } -.icon-bills:before { +i.icon-bills:before { content: "\e22a"; } -.icon-binarycode:before { +i.icon-binarycode:before { content: "\e22b"; } -.icon-binoculars:before { +i.icon-binoculars:before { content: "\e22c"; } -.icon-bird:before { +i.icon-bird:before { content: "\e22d"; } -.icon-birthday-cake:before { +i.icon-birthday-cake:before { content: "\e22e"; } -.icon-blueprint:before { +i.icon-blueprint:before { content: "\e22f"; } -.icon-block:before { +i.icon-block:before { content: "\e230"; } -.icon-bluetooth:before { +i.icon-bluetooth:before { content: "\e231"; } -.icon-boat-shipping:before { +i.icon-boat-shipping:before { content: "\e232"; } -.icon-bomb:before { +i.icon-bomb:before { content: "\e233"; } -.icon-book-alt-2:before { +i.icon-book-alt-2:before { content: "\e234"; } -.icon-bones:before { +i.icon-bones:before { content: "\e235"; } -.icon-book-alt:before { +i.icon-book-alt:before { content: "\e236"; } -.icon-book:before { +i.icon-book:before { content: "\e237"; } -.icon-bill-yen:before { +i.icon-bill-yen:before { content: "\e238"; } -.icon-award:before { +i.icon-award:before { content: "\e239"; } -.icon-bill-pound:before { +i.icon-bill-pound:before { content: "\e23a"; } -.icon-autofill:before { +i.icon-autofill:before { content: "\e23b"; } -.icon-bill-euro:before { +i.icon-bill-euro:before { content: "\e23c"; } -.icon-auction-hammer:before { +i.icon-auction-hammer:before { content: "\e23d"; } -.icon-bill-dollar:before { +i.icon-bill-dollar:before { content: "\e23e"; } -.icon-attachment:before { +i.icon-attachment:before { content: "\e23f"; } -.icon-bell:before { +i.icon-bell:before { content: "\e240"; } -.icon-article:before { +i.icon-article:before { content: "\e241"; } -.icon-bell-off:before { +i.icon-bell-off:before { content: "\e242"; } -.icon-art-easel:before { +i.icon-art-easel:before { content: "\e243"; } -.icon-beer-glass:before { +i.icon-beer-glass:before { content: "\e244"; } -.icon-arrow-up:before { +i.icon-arrow-up:before { content: "\e245"; } -.icon-battery-low:before { +i.icon-battery-low:before { content: "\e246"; } -.icon-arrow-right:before { +i.icon-arrow-right:before { content: "\e247"; } -.icon-battery-full:before { +i.icon-battery-full:before { content: "\e248"; } -.icon-arrow-left:before { +i.icon-arrow-left:before { content: "\e249"; } -.icon-bars:before { +i.icon-bars:before { content: "\e24a"; } -.icon-arrow-down:before { +i.icon-arrow-down:before { content: "\e24b"; } -.icon-barcode:before { +i.icon-barcode:before { content: "\e24c"; } -.icon-arrivals:before { +i.icon-arrivals:before { content: "\e24d"; } -.icon-bar-chart:before { +i.icon-bar-chart:before { content: "\e24e"; } -.icon-application-window:before { +i.icon-application-window:before { content: "\e24f"; } -.icon-band-aid:before { +i.icon-band-aid:before { content: "\e250"; } -.icon-application-window-alt:before { +i.icon-application-window-alt:before { content: "\e251"; } -.icon-ball:before { +i.icon-ball:before { content: "\e252"; } -.icon-application-error:before { +i.icon-application-error:before { content: "\e253"; } -.icon-badge-restricted:before { +i.icon-badge-restricted:before { content: "\e254"; } -.icon-app:before { +i.icon-app:before { content: "\e255"; } -.icon-badge-remove:before { +i.icon-badge-remove:before { content: "\e256"; } -.icon-anchor:before { +i.icon-anchor:before { content: "\e257"; } -.icon-badge-count:before { +i.icon-badge-count:before { content: "\e258"; } -.icon-alt:before { +i.icon-alt:before { content: "\e259"; } -.icon-badge-add:before { +i.icon-badge-add:before { content: "\e25a"; } -.icon-alert:before { +i.icon-alert:before { content: "\e25b"; } -.icon-backspace:before { +i.icon-backspace:before { content: "\e25c"; } -.icon-alert-alt:before { +i.icon-alert-alt:before { content: "\e25d"; } -.icon-section:before { +i.icon-section:before { content: "\e24f"; } diff --git a/src/Umbraco.Web.UI.Client/src/less/listview.less b/src/Umbraco.Web.UI.Client/src/less/listview.less index fe8af6dbc4..9d0ed002bb 100644 --- a/src/Umbraco.Web.UI.Client/src/less/listview.less +++ b/src/Umbraco.Web.UI.Client/src/less/listview.less @@ -32,7 +32,10 @@ position: absolute; padding: 5px 8px; pointer-events: none; - top: 2px; + + &i { + top: 2px; + } } input[type="text"] { diff --git a/src/Umbraco.Web.UI.Client/src/less/main.less b/src/Umbraco.Web.UI.Client/src/less/main.less index 2354e96d38..3bf00fb25c 100644 --- a/src/Umbraco.Web.UI.Client/src/less/main.less +++ b/src/Umbraco.Web.UI.Client/src/less/main.less @@ -284,7 +284,7 @@ label:not([for]) { margin-left: 0; } -.controls-row label { +.controls-row label:not(.umb-form-check) { display: inline-block; } diff --git a/src/Umbraco.Web.UI.Client/src/less/modals.less b/src/Umbraco.Web.UI.Client/src/less/modals.less index 4ce907d06f..a23756f412 100644 --- a/src/Umbraco.Web.UI.Client/src/less/modals.less +++ b/src/Umbraco.Web.UI.Client/src/less/modals.less @@ -24,18 +24,18 @@ } .umb-modalcolumn-body { - padding: 0px; + padding: 0; background: @white; top: @editorHeaderHeight; position: absolute; - left: 0px; - right: 0px; - bottom: 0px; + left: 0; + right: 0; + bottom: 0; overflow: auto; } .no-padding .umb-modalcolumn-body { - padding: 0px + padding: 0; } .umb-modalcolumn .umb-modalcolumn-header .btn { @@ -46,12 +46,12 @@ .umb-modalcolumn iframe.auto-expand, .umb-modal iframe.auto-expand { border: none; - padding: 0px; - margin: 0px; - top: 0px; - bottom: 0px; - left: 0px; - right: 0px; + padding: 0; + margin: 0; + top: 0; + bottom: 0; + left: 0; + right: 0; position: absolute; } @@ -79,12 +79,12 @@ /* umb.dialog is used for the dialogs on the conent tree*/ .umb-dialog { outline: none; - top: 0px; - left: 0px; - right: 0px; - bottom: 0px; + top: 0; + left: 0; + right: 0; + bottom: 0; position: absolute; - padding: 0px; + padding: 0; background: @white; } @@ -100,9 +100,9 @@ .umb-dialog-body{ position: absolute; overflow:auto; - top: 0px; - left: 0px; - right: 0px; + top: 0; + left: 0; + right: 0; bottom: 49px; } .umb-dialog-body .umb-pane{margin-top: 15px;} @@ -112,9 +112,9 @@ overflow:auto; text-align: right; height: 32px; - left: 0px; - right: 0px; - bottom: 0px; + left: 0; + right: 0; + bottom: 0; padding: 8px; margin: 0; @@ -129,13 +129,13 @@ height: auto !Important; padding: 20px; } -.umbracoDialog .umb-pane{margin-left: 0px; margin-right: 0px; margin-top: 0px;} +.umbracoDialog .umb-pane{margin-left: 0; margin-right: 0; margin-top: 0;} .umbracoDialog .umb-dialog-body .umb-pane{margin-left: 20px; margin-right: 20px; margin-top: 20px;} .umbracoDialog form{height: 100%;} /*ensures dialogs doesnt have side-by-side labels*/ .umbracoDialog .controls-row, -.umb-modal .controls-row{margin-left: 0px !important;} +.umb-modal .controls-row{margin-left: 0 !important;} /* modal and umb-modal are used for right.hand dialogs */ .modal { @@ -185,7 +185,7 @@ height: auto; } .umb-modal .umb-panel-body{ - padding: 0px 20px 0px 20px; + padding: 0 20px 0 20px; } .umb-modal.fade.in.wide { diff --git a/src/Umbraco.Web.UI.Client/src/less/pages/welcome-dashboard.less b/src/Umbraco.Web.UI.Client/src/less/pages/welcome-dashboard.less index 59c58c914e..426ffcb5e2 100644 --- a/src/Umbraco.Web.UI.Client/src/less/pages/welcome-dashboard.less +++ b/src/Umbraco.Web.UI.Client/src/less/pages/welcome-dashboard.less @@ -39,21 +39,20 @@ text-decoration: none; display: block; margin: 10px; -} -.welcome-dashboard__info-box:hover { - border: 2px solid @turquoise; - cursor: pointer; - transition: border-color 150ms ease-in-out; - text-decoration: none; -} + &:hover { + border: 2px solid @turquoise; + cursor: pointer; + transition: border-color 150ms ease-in-out; + text-decoration: none; + } -.welcome-dashboard__info-box:active, -.welcome-dashboard__info-box:focus { - text-decoration: none; + &:active, + &:focus { + text-decoration: none; + } } - .welcome-dashboard__info-box-title { color: @turquoise-d1; font-size: 16px; @@ -74,7 +73,7 @@ } .welcome-dashboard__card { - background-color: @gray-10; + background-color: @grayLighter; border-radius: 3px; margin: 10px; display: flex; @@ -113,6 +112,6 @@ } .welcome-dashboard__card-teaser { - font-size: 14px; + font-size: 13px; margin-bottom: 15px; -} \ No newline at end of file +} diff --git a/src/Umbraco.Web.UI.Client/src/less/panel.less b/src/Umbraco.Web.UI.Client/src/less/panel.less index 40c70f5331..115bdaed70 100644 --- a/src/Umbraco.Web.UI.Client/src/less/panel.less +++ b/src/Umbraco.Web.UI.Client/src/less/panel.less @@ -48,6 +48,10 @@ .form-search { flex: 1; + .icon-search { + top: 16px; + } + &__toggle { margin: 10px 0; display: flex; @@ -392,6 +396,7 @@ font-size: 30px; color: @gray-7; transition: opacity 120ms; + line-height: 1; } .umb-panel-header-icon-text { @@ -428,7 +433,7 @@ input.umb-panel-header-description { .umb-panel-header-locked-description { font-size: 12px; - margin-top: 2px; + margin: 2px 0 0 0; height: 22px; line-height: 22px; } diff --git a/src/Umbraco.Web.UI.Client/src/less/properties.less b/src/Umbraco.Web.UI.Client/src/less/properties.less index 9e951feb1a..dc6d2ff6cd 100644 --- a/src/Umbraco.Web.UI.Client/src/less/properties.less +++ b/src/Umbraco.Web.UI.Client/src/less/properties.less @@ -16,8 +16,8 @@ border-left: 1px solid @gray-10; } -.date-wrapper__date .flatpickr-input > a { - +.date-wrapper__date .flatpickr-input > a, +.date-wrapper__date .flatpickr-input > button { display: flex; align-items: center; justify-content: center; @@ -25,16 +25,15 @@ padding: 4px 15px; box-sizing: border-box; min-width: 200px; - color: @ui-action-discreet-type; border: 1px dashed @ui-action-discreet-border; border-radius: 3px; - + &:hover, &:focus { text-decoration: none; color: @ui-action-discreet-type-hover; border-color: @ui-action-discreet-border-hover; - + localize { text-decoration: none; } 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 1d68c9f927..664be1dafc 100644 --- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less +++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less @@ -131,7 +131,7 @@ pre { display: inline-flex; - font-family: monospace; + font-family: @monoFontFamily; margin-left: 15px; margin-right: 15px; white-space: nowrap; @@ -168,7 +168,7 @@ label { border: 1px solid @white; padding: 6px 10px; - font-family: monospace; + font-family: @monoFontFamily; border: 1px solid @gray-8; background: @gray-11; margin: 0 15px 0 3px; @@ -712,8 +712,9 @@ margin-top: 0; } } + // -// folder-browser +// Folder browser // -------------------------------------------------- .umb-folderbrowser .add-link { display: inline-block; @@ -811,55 +812,18 @@ } +// +// Slider +// -------------------------------------------------- +.umb-slider { + .umb-property-editor--limit-width(); +} + // // Tags // -------------------------------------------------- .umb-tags { - border: @inputBorder solid 1px; - padding: 5px; - min-height: 54px; - font-size: 13px; - text-shadow: none; - box-sizing: border-box; .umb-property-editor--limit-width(); - - .tag { - cursor: default; - margin: 10px; - padding: 10px 15px; - background: @blueExtraDark; - position: relative; - user-select: all; - - .icon-trash { - position: relative; - cursor: pointer; - padding-left: 2px; - font-size: 15px; - right: -5px; - bottom: -1px; - } - - .umb_confirm-action__overlay.-left{ - top: 6px; - left: auto; - right: 15px; - } - } - - input { - border: none; - background: @white; - } - - .twitter-typeahead { - margin: 10px; - margin-top: 16px; - vertical-align: top; - input { - padding-left: 0; - } - } } // diff --git a/src/Umbraco.Web.UI.Client/src/less/variables.less b/src/Umbraco.Web.UI.Client/src/less/variables.less index 840c6d529f..cab0745a42 100644 --- a/src/Umbraco.Web.UI.Client/src/less/variables.less +++ b/src/Umbraco.Web.UI.Client/src/less/variables.less @@ -156,11 +156,11 @@ @ui-active-type-hover: @blueMid; @ui-selected: @sand-5; -@ui-selected-hover: ligthen(@sand-5, 10); +@ui-selected-hover: ligthen(@sand-5, 10%); @ui-selected-type: @blueExtraDark; @ui-selected-type-hover: @blueMid; @ui-selected-border: @blueDark; -@ui-selected-border-hover: darken(@blueDark, 10); +@ui-selected-border-hover: darken(@blueDark, 10%); @ui-light-border: @pinkLight; @ui-light-type: @gray-4; @@ -518,7 +518,7 @@ // ------------------------- @gridColumns: 12; @gridColumnWidth: 60px; -@gridGutterWidth: 0px; +@gridGutterWidth: 0; @gridRowWidth: (@gridColumns * @gridColumnWidth) + (@gridGutterWidth * (@gridColumns - 1)); // 1200px min diff --git a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js index 268bfb3a8c..c212a08951 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js @@ -157,8 +157,8 @@ } function openTourGroup(tourAlias) { - angular.forEach(vm.tours, function (group) { - angular.forEach(group, function (tour) { + vm.tours.forEach(function (group) { + group.tours.forEach(function (tour) { if (tour.alias === tourAlias) { group.open = true; } @@ -168,9 +168,9 @@ function getTourGroupCompletedPercentage() { // Finding out, how many tours are completed for the progress circle - angular.forEach(vm.tours, function(group){ + vm.tours.forEach(function(group){ var completedTours = 0; - angular.forEach(group.tours, function(tour){ + group.tours.forEach(function(tour){ if(tour.completed) { completedTours++; } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html index aa6126e73e..6b924d0aef 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html @@ -18,16 +18,16 @@
-
+
{{ tour.name }}
- +
-
+
@@ -102,10 +102,10 @@ {{topic.name}} - + {{topic.description}} - + diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js index aa0cd54dff..ab8c133211 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js @@ -1,15 +1,17 @@ (function () { "use strict"; - function CompositionsController($scope, $location, $filter, overlayService, localizationService) { + function CompositionsController($scope, $location, $filter, $timeout, overlayService, localizationService) { var vm = this; var oldModel = null; vm.showConfirmSubmit = false; + vm.loading = false; vm.isSelected = isSelected; vm.openContentType = openContentType; + vm.selectCompositeContentType = selectCompositeContentType; vm.submit = submit; vm.close = close; @@ -23,10 +25,13 @@ $scope.model.title = "Compositions"; } - // group the content types by their container paths + // Group the content types by their container paths vm.availableGroups = $filter("orderBy")( _.map( _.groupBy($scope.model.availableCompositeContentTypes, function (compositeContentType) { + + compositeContentType.selected = isSelected(compositeContentType.contentType.alias); + return compositeContentType.contentType.metaData.containerPath; }), function (group) { return { @@ -39,12 +44,12 @@ }); } - - + function isSelected(alias) { if ($scope.model.contentType.compositeContentTypes.indexOf(alias) !== -1) { return true; } + return false; } function openContentType(contentType, section) { @@ -52,6 +57,43 @@ $location.path(url); } + function selectCompositeContentType(compositeContentType) { + + vm.loading = true; + + var contentType = compositeContentType.contentType; + + $scope.model.selectCompositeContentType(contentType).then(function (response) { + + Utilities.forEach(vm.availableGroups, function (group) { + + Utilities.forEach(group.compositeContentTypes, function (obj) { + if (obj.allowed === false) { + obj.selected = false; + } + }); + }); + + $timeout(function () { + vm.loading = false; + }, 500); + + }, function () { + $timeout(function () { + vm.loading = false; + }, 500); + }); + + // Check if the template is already selected. + var index = $scope.model.contentType.compositeContentTypes.indexOf(contentType.alias); + + if (index === -1) { + $scope.model.contentType.compositeContentTypes.push(contentType.alias); + } else { + $scope.model.contentType.compositeContentTypes.splice(index, 1); + } + } + function submit() { if ($scope.model && $scope.model.submit) { 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 4096192081..436c4ea30a 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 @@ -19,38 +19,39 @@
- +
- - + + - + +
+ +
+

diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js new file mode 100644 index 0000000000..d9ea5a7a09 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js @@ -0,0 +1,59 @@ +angular.module("umbraco") + .controller("Umbraco.Editors.MediaCropDetailsController", + function ($scope) { + + var vm = this; + + vm.submit = submit; + vm.close = close; + + if (!$scope.model.target.coordinates && !$scope.model.target.focalPoint) { + $scope.model.target.focalPoint = { left: .5, top: .5 }; + } + + vm.shouldShowUrl = shouldShowUrl; + vm.focalPointChanged = focalPointChanged; + + if (!$scope.model.target.image) { + $scope.model.target.image = $scope.model.target.url; + } + + function shouldShowUrl() { + if (!$scope.model.target) { + return false; + } + if ($scope.model.target.id) { + return false; + } + if ($scope.model.target.url && $scope.model.target.url.toLower().indexOf("blob:") === 0) { + return false; + } + return true; + } + + /** + * Called when the umbImageGravity component updates the focal point value + * @param {any} left + * @param {any} top + */ + function focalPointChanged(left, top) { + // update the model focalpoint value + $scope.model.target.focalPoint = { + left: left, + top: top + }; + } + + function submit() { + if ($scope.model && $scope.model.submit) { + $scope.model.submit($scope.model); + } + } + + function close() { + if ($scope.model && $scope.model.close) { + $scope.model.close($scope.model); + } + } + + }); 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 new file mode 100644 index 0000000000..3814ac851e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html @@ -0,0 +1,78 @@ +
+ + + + + + + +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ Preview +
+ + {{model.target.name}} +
+ +
+
+ Crop section +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + +
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js index a6d1383640..6310545b20 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js @@ -202,7 +202,7 @@ var match = false; // find and show if a match from the list has been chosen - angular.forEach(vm.validationTypes, function (validationType, index) { + vm.validationTypes.forEach(function (validationType, index) { if ($scope.model.property.validation.pattern === validationType.pattern) { vm.selectedValidationType = vm.validationTypes[index]; vm.showValidationPattern = true; @@ -212,7 +212,7 @@ // if there is no match - choose the custom validation option. if (!match) { - angular.forEach(vm.validationTypes, function (validationType) { + vm.validationTypes.forEach(function (validationType) { if (validationType.key === "custom") { vm.selectedValidationType = validationType; vm.showValidationPattern = true; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html index 37a0d41207..05ebc56083 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html @@ -71,7 +71,7 @@ -
+ {{property.name}} @@ -90,7 +90,7 @@ - + {{term.name}} @@ -112,13 +112,13 @@ - + - +
@@ -137,7 +137,7 @@ - + {{property.name}} @@ -159,7 +159,7 @@ diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/sectionpicker/sectionpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/sectionpicker/sectionpicker.controller.js index 55d7a75000..f2a89ba7ea 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/sectionpicker/sectionpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/sectionpicker/sectionpicker.controller.js @@ -47,8 +47,8 @@ } function preSelect(selection) { - angular.forEach(selection, function(selected){ - angular.forEach(vm.sections, function(section){ + selection.forEach(function(selected){ + vm.sections.forEach(function(section){ if(selected.alias === section.alias) { section.selected = true; } @@ -65,7 +65,7 @@ } else { - angular.forEach($scope.model.selection, function(selectedSection, index){ + $scope.model.selection.forEach(function(selectedSection, index){ if(selectedSection.alias === section.alias) { section.selected = false; $scope.model.selection.splice(index, 1); @@ -77,7 +77,7 @@ } function setSectionIcon(sections) { - angular.forEach(sections, function(section) { + sections.forEach(function(section) { section.icon = "icon-section"; }); } 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 387dd71da8..c519a1d4fa 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 @@ -188,8 +188,17 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", //used advanced filtering if ($scope.model.filter.startsWith("{")) { $scope.model.filterAdvanced = true; - //convert to object - $scope.model.filter = Utilities.fromJson($scope.model.filter); + + if ($scope.model.filterByMetadata && !angular.isFunction($scope.model.filter)) + { + var filter = angular.fromJson($scope.model.filter); + $scope.model.filter = function (node){ return _.isMatch(node.metaData, filter);}; + } + else + { + //convert to object + $scope.model.filter = Utilities.fromJson($scope.model.filter); + } } } } @@ -274,19 +283,14 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", if (Utilities.isArray(args.children)) { //iterate children - _.each(args.children, - function (child) { - - //now we need to look in the already selected search results and - // toggle the check boxes for those ones that are listed - var exists = _.find(vm.searchInfo.selectedSearchResults, - function (selected) { - return child.id == selected.id; - }); - if (exists) { - child.selected = true; - } - }); + args.children.forEach(child => { + //now we need to look in the already selected search results and + // toggle the check boxes for those ones that are listed + var exists = vm.searchInfo.selectedSearchResults.find(selected => child.id === selected.id); + if (exists) { + child.selected = true; + } + }); //check filter performFiltering(args.children); @@ -456,8 +460,7 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", ? _.filter(nodes, $scope.model.filter) : _.where(nodes, $scope.model.filter); - angular.forEach(filtered, - function (value, key) { + filtered.forEach(function (value) { value.filtered = true; if ($scope.model.filterCssClass) { if (!value.cssClasses) { @@ -470,8 +473,7 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", } else { var a = $scope.model.filter.toLowerCase().replace(/\s/g, '').split(','); - angular.forEach(nodes, - function (value, key) { + nodes.forEach(function (value) { var found = a.indexOf(value.metaData.contentType.toLowerCase()) >= 0; @@ -541,78 +543,66 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", //we need to ensure that any currently displayed nodes that get selected // from the search get updated to have a check box! function checkChildren(children) { - _.each(children, - function (child) { - //check if the id is in the selection, if so ensure it's flagged as selected - var exists = _.find(vm.searchInfo.selectedSearchResults, - function (selected) { - return child.id == selected.id; + children.forEach(child => { + //check if the id is in the selection, if so ensure it's flagged as selected + var exists = vm.searchInfo.selectedSearchResults.find(selected => child.id === selected.id); + //if the curr node exists in selected search results, ensure it's checked + if (exists) { + child.selected = true; + } + //if the curr node does not exist in the selected search result, and the curr node is a child of a list view search result + else if (child.metaData.isSearchResult) { + //if this tree node is under a list view it means that the node was added + // to the tree dynamically under the list view that was searched, so we actually want to remove + // it all together from the tree + var listView = child.parent(); + listView.children = _.reject(listView.children, + function (c) { + return c.id == child.id; }); - //if the curr node exists in selected search results, ensure it's checked - if (exists) { - child.selected = true; - } - //if the curr node does not exist in the selected search result, and the curr node is a child of a list view search result - else if (child.metaData.isSearchResult) { - //if this tree node is under a list view it means that the node was added - // to the tree dynamically under the list view that was searched, so we actually want to remove - // it all together from the tree - var listView = child.parent(); - listView.children = _.reject(listView.children, - function (c) { - return c.id == child.id; - }); - } + } - //check if the current node is a list view and if so, check if there's any new results - // that need to be added as child nodes to it based on search results selected - if (child.metaData.isContainer) { + //check if the current node is a list view and if so, check if there's any new results + // that need to be added as child nodes to it based on search results selected + if (child.metaData.isContainer) { - child.cssClasses = _.reject(child.cssClasses, - function (c) { - return c === 'tree-node-slide-up-hide-active'; - }); + child.cssClasses = _.reject(child.cssClasses, + function (c) { + return c === 'tree-node-slide-up-hide-active'; + }); - var listViewResults = _.filter(vm.searchInfo.selectedSearchResults, - function (i) { - return i.parentId == child.id; - }); - _.each(listViewResults, - function (item) { - var childExists = _.find(child.children, - function (c) { - return c.id == item.id; - }); - if (!childExists) { - var parent = child; - child.children.unshift({ - id: item.id, - name: item.name, - cssClass: "icon umb-tree-icon sprTree " + item.icon, - level: child.level + 1, - metaData: { - isSearchResult: true - }, - hasChildren: false, - parent: function () { - return parent; - } - }); - } - }); - } + var listViewResults = vm.searchInfo.selectedSearchResults.filter(i => i.parentId === child.id); - //recurse - if (child.children && child.children.length > 0) { - checkChildren(child.children); - } - }); + listViewResults.forEach(item => { + var childExists = child.children.find(c => c.id === item.id); + + if (!childExists) { + var parent = child; + child.children.unshift({ + id: item.id, + name: item.name, + cssClass: "icon umb-tree-icon sprTree " + item.icon, + level: child.level + 1, + metaData: { + isSearchResult: true + }, + hasChildren: false, + parent: () => parent + }); + } + }); + } + + //recurse + if (child.children && child.children.length > 0) { + checkChildren(child.children); + } + }); } checkChildren(tree.root.children); } - vm.searchInfo.showSearch = false; vm.searchInfo.searchFromId = vm.startNodeId; vm.searchInfo.searchFromName = null; @@ -625,24 +615,16 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", performFiltering(results); //now actually remove all filtered items so they are not even displayed - results = _.filter(results, - function (item) { - return !item.filtered; - }); - + results = results.filter(item => !item.filtered); vm.searchInfo.results = results; //sync with the curr selected results - _.each(vm.searchInfo.results, - function (result) { - var exists = _.find($scope.model.selection, - function (item) { - return result.id == item.id; - }); - if (exists) { - result.selected = true; - } - }); + vm.searchInfo.results.forEach(result => { + var exists = $scope.model.selection.find(item => result.id === item.id); + if (exists) { + result.selected = true; + } + }); vm.searchInfo.showSearch = true; } @@ -664,12 +646,8 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", } function listViewItemsLoaded(items) { - var selectedIds = _.pluck($scope.model.selection, "id"); - _.each(items, function (item) { - if (_.contains(selectedIds, item.id)) { - item.selected = true; - } - }); + var selectedIds = $scope.model.selection.map(x => x.id); + items.forEach(item => item.selected = selectedIds.includes(item.id)); } function submit(model) { diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.html index 0c10d94136..c816c31b3e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.html @@ -19,12 +19,12 @@
-
-
{{vm.selectedLanguage.name}}
-   -
+
- {{language.name}} +
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/usergrouppicker/usergrouppicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/usergrouppicker/usergrouppicker.controller.js index 8e075e1ab4..b11ae02e4e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/usergrouppicker/usergrouppicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/usergrouppicker/usergrouppicker.controller.js @@ -46,9 +46,9 @@ function preSelect(selection) { - angular.forEach(selection, function(selected){ - - angular.forEach(vm.userGroups, function(userGroup){ + selection.forEach(function (selected) { + + vm.userGroups.forEach(function(userGroup){ if(selected.id === userGroup.id) { userGroup.selected = true; } @@ -66,7 +66,7 @@ } else { - angular.forEach($scope.model.selection, function(selectedUserGroup, index){ + $scope.model.selection.forEach(function(selectedUserGroup, index){ if(selectedUserGroup.id === userGroup.id) { userGroup.selected = false; $scope.model.selection.splice(index, 1); 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 2bd73a5558..a7021b2867 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,7 +1,7 @@ (function () { "use strict"; - function UserPickerController($scope, usersResource, localizationService) { + function UserPickerController($scope, usersResource, localizationService, eventsService) { var vm = this; @@ -15,15 +15,18 @@ vm.submit = submit; vm.close = close; - ////////// + vm.multiPicker = $scope.model.multiPicker === false ? false : true; function onInit() { vm.loading = true; // set default title - if(!$scope.model.title) { - localizationService.localize("defaultdialogs_selectUsers").then(function(value){ + if (!$scope.model.title) { + + var labelKey = vm.multiPicker ? "defaultdialogs_selectUsers" : "defaultdialogs_selectUser"; + + localizationService.localize(labelKey).then(function(value){ $scope.model.title = value; }); } @@ -35,12 +38,11 @@ // get users getUsers(); - } function preSelect(selection, users) { - angular.forEach(selection, function(selected){ - angular.forEach(users, function(user){ + Utilities.forEach(selection, function(selected){ + Utilities.forEach(users, function(user){ if(selected.id === user.id) { user.selected = true; } @@ -50,22 +52,39 @@ function selectUser(user) { - if(!user.selected) { - + if (!user.selected) { user.selected = true; $scope.model.selection.push(user); - } else { - angular.forEach($scope.model.selection, function(selectedUser, index){ - if(selectedUser.id === user.id) { - user.selected = false; - $scope.model.selection.splice(index, 1); + if (user.selected) { + Utilities.forEach($scope.model.selection, function (selectedUser, index) { + if (selectedUser.id === user.id) { + user.selected = false; + $scope.model.selection.splice(index, 1); + } + }); + } else { + if (!vm.multiPicker) { + deselectAllUsers($scope.model.selection); } - }); - + eventsService.emit("dialogs.userPicker.select", user); + user.selected = true; + $scope.model.selection.push(user); + } } + if (!vm.multiPicker) { + submit($scope.model); + } + } + + function deselectAllUsers(users) { + for (var i = 0; i < users.length; i++) { + var user = users[i]; + user.selected = false; + } + users.length = 0; } var search = _.debounce(function () { @@ -95,7 +114,6 @@ preSelect($scope.model.selection, vm.users); vm.loading = false; - }); } @@ -105,14 +123,14 @@ } function submit(model) { - if($scope.model.submit) { + if ($scope.model.submit) { $scope.model.submit(model); } } function close() { - if($scope.model.close) { - $scope.model.close(); + if ($scope.model.close) { + $scope.model.close(); } } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.html index e39d693b47..5536ce38c2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.html @@ -19,7 +19,7 @@ -
@@ -49,27 +48,27 @@
-

{{ article.title }}

-
{{ article.description }}
- {{article.buttonText}} +

{{article.title}}

+
{{article.description}}
+ {{article.buttonText}}
- \ No newline at end of file + diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/default/umbracotv.jpg b/src/Umbraco.Web.UI.Client/src/views/dashboard/default/umbracotv.jpg deleted file mode 100644 index 22ae3653e29eb07c489c976049007c9909034a9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49817 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

Y+C^8i^ig)q#CDII(Q>0IG;>%E~_PH(-ko+jDh? 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 z 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 diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/default/umbracotv.png b/src/Umbraco.Web.UI.Client/src/views/dashboard/default/umbracotv.png new file mode 100644 index 0000000000000000000000000000000000000000..173d2f36d089d560723bc34dd4f779d3986b2885 GIT binary patch literal 314485 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 diff --git a/src/Umbraco.Web.UI.Client/src/views/dataTypes/delete.html b/src/Umbraco.Web.UI.Client/src/views/dataTypes/delete.html index 1fc9a2adfd..e27433c739 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dataTypes/delete.html +++ b/src/Umbraco.Web.UI.Client/src/views/dataTypes/delete.html @@ -106,9 +106,7 @@ - - + diff --git a/src/Umbraco.Web.UI.Client/src/views/dictionary/create.html b/src/Umbraco.Web.UI.Client/src/views/dictionary/create.html index 88a67aaf18..9e628464b2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dictionary/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/dictionary/create.html @@ -1,7 +1,7 @@ 

diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.html b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.html index ab1b84db97..2fb2aab352 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.html @@ -15,12 +15,11 @@ - + diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.html b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.html index e693801495..865b59506b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.html +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.html @@ -6,7 +6,6 @@ -
- - +
+
- - Query for root node with xpath + +
- +
- +
-
    +
    • - - - Show xpath query help - + + - +

      Use Xpath query to set a root node on the tree, either based on a search from the root of the content tree, or by using a context-aware placeholder.

      - Placeholders finds the nearest published ID and runs its query from there. so for instance: + Placeholders finds the nearest published ID and runs its query from there, so for instance:

      $parent/newsArticle
      @@ -68,14 +63,14 @@ $root: root of the content tree
      $site: Ancestor node at level 1

      -
      +
    • - - Cancel and clear query + +
    - +
diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesourcetypepicker.html b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesourcetypepicker.html index f679b53093..cdbacfc7f3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesourcetypepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesourcetypepicker.html @@ -12,12 +12,11 @@ on-remove="vm.remove(itemType)">
- + 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 df76c2d63a..dab8d2c6f8 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,6 +1,28 @@ function booleanEditorController($scope, angularHelper) { + // Setup the default config + // This allow to overwrite the configuration when property editor is re-used + // in e.g. third party packages, dashboard or content app. For example when using umb-property-editor. + // At the moment this use "1/0" as default for "truevalue" and "falsevalue", but allow "True/False" as well. + // Maybe sometime later we can make it support "Yes/No" or "On/Off" as well similar to ng-true-value and ng-false-value in Angular. + var config = { + truevalue: "1", + falsevalue: "0", + showLabels: false + }; + + if ($scope.model.config && $scope.model.config.showLabels && Object.toBoolean($scope.model.config.showLabels)) { + config.showLabels = true; + } + + // Map the user config + Utilities.extend(config, $scope.model.config); + + // Map back to the model + $scope.model.config = config; + function setupViewModel() { + $scope.renderModel = { value: false }; @@ -16,12 +38,12 @@ function booleanEditorController($scope, angularHelper) { setupViewModel(); - if( $scope.model && !$scope.model.value ) { - $scope.model.value = ($scope.renderModel.value === true) ? '1' : '0'; + if ($scope.model && !$scope.model.value) { + $scope.model.value = ($scope.renderModel.value === true) ? $scope.model.config.truevalue : $scope.model.config.falsevalue; } - //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 + // 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) { //update the display val again if it has changed from the server setupViewModel(); @@ -30,13 +52,13 @@ function booleanEditorController($scope, angularHelper) { // Update the value when the toggle is clicked $scope.toggle = function(){ angularHelper.getCurrentForm($scope).$setDirty(); - if($scope.renderModel.value){ - $scope.model.value = "0"; + if ($scope.renderModel.value){ + $scope.model.value = $scope.model.config.falsevalue; setupViewModel(); return; } - $scope.model.value = "1"; + $scope.model.value = $scope.model.config.truevalue; setupViewModel(); }; 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 21ed753c15..75f3f5452a 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 @@ -3,9 +3,9 @@ input-id="{{model.alias}}" checked="renderModel.value" on-click="toggle()" - show-labels="{{model.config.labelOn ? 'true': 'false'}}" + show-labels="{{model.config.showLabels}}" label-position="right" label-on="{{model.config.labelOn}}" - label-off="{{model.config.labelOn}}"> + label-off="{{model.config.labelOff}}"> diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index 238872db40..bd80cdc42c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -3,16 +3,19 @@ * The controller that is used for a couple different Property Editors: Multi Node Tree Picker, Content Picker, * since this is used by MNTP and it supports content, media and members, there is code to deal with all 3 of those types * @param {any} $scope + * @param {any} $q + * @param {any} $routeParams + * @param {any} $location * @param {any} entityResource * @param {any} editorState * @param {any} iconHelper - * @param {any} $routeParams * @param {any} angularHelper * @param {any} navigationService - * @param {any} $location * @param {any} localizationService + * @param {any} editorService + * @param {any} userService */ -function contentPickerController($scope, entityResource, editorState, iconHelper, $routeParams, angularHelper, navigationService, $location, localizationService, editorService, $q) { +function contentPickerController($scope, $q, $routeParams, $location, entityResource, editorState, iconHelper, angularHelper, navigationService, localizationService, editorService, userService) { var vm = { labels: { @@ -139,7 +142,8 @@ function contentPickerController($scope, entityResource, editorState, iconHelper : $scope.model.config.startNode.type === "media" ? "Media" : "Document"; - $scope.allowOpenButton = entityType === "Document"; + + $scope.allowOpenButton = false; $scope.allowEditButton = entityType === "Document"; $scope.allowRemoveButton = true; @@ -303,16 +307,24 @@ function contentPickerController($scope, entityResource, editorState, iconHelper $scope.model.value = null; }; - $scope.openContentEditor = function (node) { - var contentEditor = { - id: node.id, + $scope.openEditor = function (item) { + var editor = { + id: entityType === "Member" ? item.key : item.id, submit: function (model) { + + var node = entityType === "Member" ? model.memberNode : + entityType === "Media" ? model.mediaNode : + model.contentNode; + // update the node - node.name = model.contentNode.name; - node.published = model.contentNode.hasPublishedVersion; + item.name = node.name; + if (entityType !== "Member") { - entityResource.getUrl(model.contentNode.id, entityType).then(function (data) { - node.url = data; + if (entityType === "Document") { + item.published = node.hasPublishedVersion; + } + entityResource.getUrl(node.id, entityType).then(function (data) { + item.url = data; }); } editorService.close(); @@ -321,7 +333,18 @@ function contentPickerController($scope, entityResource, editorState, iconHelper editorService.close(); } }; - editorService.contentEditor(contentEditor); + + switch (entityType) { + case "Document": + editorService.contentEditor(editor); + break; + case "Media": + editorService.mediaEditor(editor); + break; + case "Member": + editorService.memberEditor(editor); + break; + } }; //when the scope is destroyed we need to unsubscribe @@ -423,7 +446,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper if (entityType !== "Member") { entityResource.getUrl(entity.id, entityType).then(function (data) { // update url - angular.forEach($scope.renderModel, function (item) { + $scope.renderModel.forEach(function (item) { if (item.id === entity.id) { if (entity.trashed) { item.url = vm.labels.general_recycleBin; @@ -466,6 +489,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper "icon": item.icon, "path": item.path, "url": item.url, + "key": item.key, "trashed": item.trashed, "published": (item.metaData && item.metaData.IsPublished === false && entityType === "Document") ? false : true // only content supports published/unpublished content so we set everything else to published so the UI looks correct @@ -484,6 +508,26 @@ function contentPickerController($scope, entityResource, editorState, iconHelper } function init() { + + userService.getCurrentUser().then(function (user) { + switch (entityType) { + case "Document": + var hasAccessToContent = user.allowedSections.indexOf("content") !== -1; + $scope.allowOpenButton = hasAccessToContent; + break; + case "Media": + var hasAccessToMedia = user.allowedSections.indexOf("media") !== -1; + $scope.allowOpenButton = hasAccessToMedia; + break; + case "Member": + var hasAccessToMember = user.allowedSections.indexOf("member") !== -1; + $scope.allowOpenButton = hasAccessToMember; + break; + + default: + } + }); + localizationService.localizeMany(["general_recycleBin", "general_add"]) .then(function(data) { vm.labels.general_recycleBin = data[0]; 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 ba22ca9d80..1a17ea2698 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 @@ -15,7 +15,7 @@ allow-remove="allowRemoveButton" allow-open="model.config.showOpenButton && allowOpenButton && !dialogEditor" on-remove="remove($index)" - on-open="openContentEditor(node)"> + on-open="openEditor(node)"> 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 24affc6ac1..30b6fc4c8f 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 @@ -55,7 +55,9 @@ function dateTimePickerController($scope, angularHelper, dateHelper, validationM }; // Don't show calendar if date format has been set to only time - if ($scope.model.config.format === "HH:mm:ss" || $scope.model.config.format === "HH:mm" || $scope.model.config.format === "HH") { + const timeFormat = $scope.model.config.format.toLowerCase(); + const timeFormatPattern = /^h{1,2}:m{1,2}:s{1,2}\s?a?$/gmi; + if (timeFormat.match(timeFormatPattern)) { $scope.datePickerConfig.enableTime = true; $scope.datePickerConfig.noCalendar = true; } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html index b35663c3df..9501a6631b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html @@ -11,21 +11,20 @@ on-change="datePickerChange(dateStr)">
- +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js index 4064df6a24..69de132715 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js @@ -15,14 +15,14 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleCo //ensure this is a bool, old data could store zeros/ones or string versions $scope.model.config.multiple = Object.toBoolean($scope.model.config.multiple); - + //ensure when form is saved that we don't store [] or [null] as string values in the database when no items are selected $scope.$on("formSubmitting", function () { - if ($scope.model.value && ($scope.model.value.length === 0 || $scope.model.value[0] === null)) { + if ($scope.model.value !== null && ($scope.model.value.length === 0 || $scope.model.value[0] === null)) { $scope.model.value = null; } }); - + function convertArrayToDictionaryArray(model){ //now we need to format the items in the dictionary because we always want to have an array var newItems = []; @@ -41,7 +41,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleCo var keys = _.keys($scope.model.config.items); for (var i = 0; i < vals.length; i++) { - var label = vals[i].value ? vals[i].value : vals[i]; + var label = vals[i].value ? vals[i].value : vals[i]; newItems.push({ id: keys[i], sortOrder: vals[i].sortOrder, value: label }); } @@ -65,7 +65,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleCo else { throw "The items property must be either an array or a dictionary"; } - + //sort the values $scope.model.config.items.sort(function (a, b) { return (a.sortOrder > b.sortOrder) ? 1 : ((b.sortOrder > a.sortOrder) ? -1 : 0); }); @@ -80,7 +80,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleCo $scope.model.value = ""; } } - + // if we run in single mode we'll store the value in a local variable // so we can pass an array as the model as our PropertyValueEditor expects that $scope.model.singleDropdownValue = ""; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.controller.js index e56bc67a49..969f675139 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.controller.js @@ -1,10 +1,66 @@ -function EditConfigController($scope) { +function EditConfigController($scope, angularHelper) { var vm = this; - + vm.submit = submit; vm.close = close; + vm.aceOption = { + mode: "json", + theme: "chrome", + showPrintMargin: false, + advanced: { + fontSize: '14px', + enableSnippets: true, + enableBasicAutocompletion: true, + enableLiveAutocompletion: false + }, + onLoad: function (_editor) { + vm.editor = _editor; + + vm.configJson = Utilities.toJson($scope.model.config, true); + + vm.editor.setValue(vm.configJson); + + vm.editor.on("blur", blurAceEditor); + } + }; + + function blurAceEditor(event, _editor) { + const code = _editor.getValue(); + + //var form = angularHelper.getCurrentForm($scope); + var form = vm.gridConfigEditor; + var isValid = isValidJson(code); + + if (isValid) { + $scope.model.config = Utilities.fromJson(code); + + setValid(form); + } + else { + setInvalid(form); + } + } + + function isValidJson(model) { + var flag = true; + try { + Utilities.fromJson(model) + } catch (err) { + flag = false; + } + return flag; + } + + function setValid(form) { + form.$setValidity('json', true); + } + + function setInvalid(form) { + form.$setValidity('json', false); + } + function submit() { if ($scope.model && $scope.model.submit) { $scope.model.submit($scope.model); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.html index 9fed19d4d9..4470c50274 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.html @@ -16,16 +16,18 @@ - +

{{model.name}}

Settings will only save if the entered json configuration is valid

- -
+
+
+ +
This configuration is not valid json, and will not be saved.
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js index 876e4cf8f3..cf201976ad 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js @@ -2,17 +2,29 @@ angular.module("umbraco") .controller("Umbraco.PropertyEditors.GridPrevalueEditor.LayoutConfigController", function ($scope, localizationService) { + var vm = this; + + vm.labels = {}; function init() { - setTitle(); + + var labelKeys = [ + "grid_addGridLayout", + "grid_allowAllRowConfigurations" + ]; + + localizationService.localizeMany(labelKeys).then(function (data) { + + vm.labels.title = data[0]; + vm.labels.allowAllRowConfigurations = data[1]; + + setTitle(vm.labels.title); + }); } - function setTitle() { + function setTitle(value) { if (!$scope.model.title) { - localizationService.localize("grid_addGridLayout") - .then(function(data){ - $scope.model.title = data; - }); + $scope.model.title = value; } } @@ -56,13 +68,15 @@ angular.module("umbraco") }; $scope.toggleAllowed = function (section) { + section.allowAll = !section.allowAll; + if (section.allowed) { delete section.allowed; } else { section.allowed = []; } - } + }; $scope.deleteSection = function(section, template) { if ($scope.currentSection === section) { @@ -71,19 +85,32 @@ angular.module("umbraco") var index = template.sections.indexOf(section) template.sections.splice(index, 1); }; - + + $scope.selectRow = function (section, row) { + section.allowed = section.allowed || []; + + var index = section.allowed.indexOf(row.name); + if (row.allowed === true) { + if (index === -1) { + section.allowed.push(row.name); + } + } + else { + section.allowed.splice(index, 1); + } + }; $scope.close = function() { - if($scope.model.close) { + if ($scope.model.close) { $scope.model.close(); } - } + }; $scope.submit = function () { if ($scope.model.submit) { $scope.model.submit($scope.currentLayout); } - } + }; $scope.$watch("currentLayout", function(layout){ if(layout){ diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html index 06afaa6b45..49e478a10b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html @@ -1,166 +1,165 @@ -
- - - +
- - + + - - - + + + +
+

+ +

+ + + +
+
+
-
+ + -

+ + + - - - +
+
+
-
+
-
-
+ +
+ + {{currentSection.grid}} + +
+
- - + + + + - - - + -
-
-
+ + -
+
+
- -
- - - - {{currentSection.grid}} - - - -
-
+
+
    - - - - Delete - - +
  • +
    - + + - - +
    -
    -
    +
    +
    +
    -
    -
      +
      +
    +
    +
    -
  • +
    + {{row.name}}
    + {{row.areas.length}} cells +
    +
-
-
-
-
+
+ + +
+
+ +
-
-
-
-
+
-
- {{row.name}}
- {{row.areas.length}} cells
-
- +
+
+
-
- - -
-
- -
- - - - - - -
-
- - - - - - + + + + - - + + - + - + - + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.controller.js index 263e7c0d9a..83a9fd5394 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.controller.js @@ -1,22 +1,34 @@ function RowConfigController($scope, localizationService) { + var vm = this; + + vm.labels = {}; + function init() { - setTitle(); + + var labelKeys = [ + "grid_addRowConfiguration", + "grid_allowAllEditors" + ]; + + localizationService.localizeMany(labelKeys).then(function (data) { + + vm.labels.title = data[0]; + vm.labels.allowAllEditors = data[1]; + + setTitle(vm.labels.title); + }); } - function setTitle() { + function setTitle(value) { if (!$scope.model.title) { - localizationService.localize("grid_addRowConfiguration") - .then(function(data){ - $scope.model.title = data; - }); + $scope.model.title = value; } } - $scope.currentRow = $scope.model.currentRow; - $scope.editors = $scope.model.editors; $scope.columns = $scope.model.columns; + $scope.editors = $scope.model.editors; $scope.scaleUp = function(section, max, overflow) { var add = 1; @@ -44,7 +56,7 @@ function RowConfigController($scope, localizationService) { delete $scope.currentCell; } else { - if (cell === undefined) { + if (cell === null) { var available = $scope.availableRowSpace; var space = 4; @@ -58,43 +70,64 @@ function RowConfigController($scope, localizationService) { row.areas.push(cell); } + + cell.allowed = cell.allowed || []; + + $scope.editors.forEach(function (e) { e.allowed = cell.allowed.indexOf(e.alias) !== -1 }); + $scope.currentCell = cell; $scope.currentCell.allowAll = cell.allowAll || !cell.allowed || !cell.allowed.length; } }; $scope.toggleAllowed = function (cell) { + cell.allowAll = !cell.allowAll; + if (cell.allowed) { delete cell.allowed; } else { cell.allowed = []; } - } + }; $scope.deleteArea = function (cell, row) { if ($scope.currentCell === cell) { - $scope.currentCell = undefined; + $scope.currentCell = null; } var index = row.areas.indexOf(cell) row.areas.splice(index, 1); }; $scope.closeArea = function() { - $scope.currentCell = undefined; + $scope.currentCell = null; + }; + + $scope.selectEditor = function (cell, editor) { + cell.allowed = cell.allowed || []; + + var index = cell.allowed.indexOf(editor.alias); + if (editor.allowed === true) { + if (index === -1) { + cell.allowed.push(editor.alias); + } + } + else { + cell.allowed.splice(index, 1); + } }; - $scope.close = function() { - if($scope.model.close) { + $scope.close = function () { + if ($scope.model.close) { $scope.model.close(); } - } + }; $scope.submit = function () { if ($scope.model.submit) { $scope.model.submit($scope.currentRow); } - } + }; $scope.nameChanged = false; var originalName = $scope.currentRow.name; @@ -118,11 +151,8 @@ function RowConfigController($scope, localizationService) { } } }, true); - init(); - - } angular.module("umbraco").controller("Umbraco.PropertyEditors.GridPrevalueEditor.RowConfigController", RowConfigController); 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 9e7034688b..b74ef6bf09 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 @@ -1,10 +1,8 @@ -
+
+ - - - -
+ +
+

+
+

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.

-
+ + - - - + + + +
+
+
- - - +
-
+ +
+ + {{currentCell.grid}} + +
+
-
-
+ + + - - + + + + - - - -
-
-
+ -
+ + - -
- - - - {{currentCell.grid}} - - - -
-
+
+
+
    +
  • - - - + + {{editor.name}} + ({{editor.alias}}) + + +
  • +
+
+ +
- - - - Delete - - +
- -
    -
  • - -
  • -
+ + + -
-
-
    -
  • - -
  • -
-
-
-
- -
- - - - -
- - - - - + + - - - - - -

Warning!

- -

- You are deleting the row configuration {{model.dialogData.rowName}} -

- -

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

- -

- Are you sure? -

- -
-
-
- - - - - - - - - - -
- -
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 7c98fbfc5e..0d558e166c 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 @@ -20,7 +20,16 @@ angular.module("umbraco") $scope.setImage = function () { var startNodeId = $scope.model.config && $scope.model.config.startNodeId ? $scope.model.config.startNodeId : undefined; var startNodeIsVirtual = startNodeId ? $scope.model.config.startNodeIsVirtual : undefined; - + var value = $scope.control.value; + var target = value + ? { + udi: value.udi, + url: value.image, + image: value.image, + focalPoint: value.focalPoint, + coordinates: value.coordinates + } + : null; var mediaPicker = { startNodeId: startNodeId, startNodeIsVirtual: startNodeIsVirtual, @@ -29,11 +38,13 @@ angular.module("umbraco") disableFolderSelect: true, onlyImages: true, dataTypeKey: $scope.model.dataTypeKey, + currentTarget: target, submit: function (model) { var selectedImage = model.selection[0]; $scope.control.value = { focalPoint: selectedImage.focalPoint, + coordinates: selectedImage.coordinates, id: selectedImage.id, udi: selectedImage.udi, image: selectedImage.image, @@ -69,25 +80,46 @@ angular.module("umbraco") } else { if ($scope.control.editor.config && $scope.control.editor.config.size) { + if ($scope.control.value.coordinates) { + // New way, crop by percent must come before width/height. + imageOptions.crop = $scope.control.value.coordinates; + imageOptions.mode = "percentage" + } else { + // Here in order not to break existing content where focalPoint were used. + // For some reason width/height have to come first when mode=crop. + if ($scope.control.value.focalPoint) { + imageOptions.focalPoint = { + left: $scope.control.value.focalPoint.left, + top: $scope.control.value.focalPoint.top + } + imageOptions.mode = "crop"; + } else { + // Prevent black padding and no crop when focal point not set / changed from default + imageOptions.focalPoint = { + left: 0.5, + top: 0.5 + } + imageOptions.mode = "crop"; + } + } imageOptions.animationprocessmode = "first"; imageOptions.height = $scope.control.editor.config.size.height; imageOptions.width = $scope.control.editor.config.size.width; } - if ($scope.control.value.focalPoint) { - imageOptions.focalPoint = { - left: $scope.control.value.focalPoint.left, - top: $scope.control.value.focalPoint.top - } - imageOptions.mode = "crop"; - } + // set default size if no crop present (moved from the view) + if (url.indexOf('?') == -1) + { + imageOptions.width = 800; + imageOptions.upscale = false; + imageOptions.animationprocessmode = false; } - - mediaHelper.getProcessedImageUrl($scope.control.value.image, imageOptions) - .then(function (url) { - $scope.thumbnailUrl = url; - }); } - }; + mediaHelper.getProcessedImageUrl($scope.control.value.image, imageOptions) + .then(function (url) { + $scope.thumbnailUrl = url; + }); + } + }; - }); + }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.html index 184f707ebf..fa32821917 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.html @@ -1,16 +1,16 @@
-
- +
+
Click to insert image
-
+
-
- +
+ -
+
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 a0826f7a96..6d3383c51e 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 @@ -405,14 +405,16 @@ angular.module("umbraco") eventsService.emit("grid.rowAdded", { scope: $scope, element: $element, row: row }); - // TODO: find a nicer way to do this without relying on setTimeout - setTimeout(function () { - var newRowEl = $element.find("[data-rowid='" + row.$uniqueId + "']"); + if (!isInit) { + // TODO: find a nicer way to do this without relying on setTimeout + setTimeout(function () { + var newRowEl = $element.find("[data-rowid='" + row.$uniqueId + "']"); - if (newRowEl !== null) { - newRowEl.focus(); - } - }, 0); + if (newRowEl !== null) { + newRowEl.focus(); + } + }, 0); + } }; @@ -953,7 +955,7 @@ angular.module("umbraco") $scope.availableEditors = response.data; //Localize the grid editor names - angular.forEach($scope.availableEditors, function (value, key) { + $scope.availableEditors.forEach(function (value) { //If no translation is provided, keep using the editor name from the manifest localizationService.localize("grid_" + value.alias, undefined, value.name).then(function (v) { value.name = v; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.html index 0628766638..afb754a0ef 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.html @@ -22,7 +22,7 @@
-

+

Choose a layout

{{row.label || row.name}}
- +

Settings applied

@@ -95,10 +95,10 @@
- @@ -138,24 +138,27 @@
- - + +

This content is not allowed here

- - + +

This content is allowed here

- +

+ Settings applied +

-
- -
+
@@ -163,8 +166,10 @@ @@ -196,13 +201,17 @@
- +
- - @@ -226,7 +235,7 @@
- +
@@ -266,7 +275,7 @@
-

+

Add row

@@ -41,8 +40,7 @@ - @@ -66,14 +64,13 @@
  • -
    +
    + ng-repeat="area in layout.areas | filter: vm.zeroWidthFilter" + ng-style="{width: vm.percentage(area.grid) + '%', 'max-width': '100%'}">

    {{area.maxItems}}

    @@ -84,7 +81,7 @@
    {{layout.label || layout.name}}
    - @@ -93,7 +90,7 @@
  • - @@ -121,7 +118,7 @@
  • - @@ -130,7 +127,7 @@
    • - @@ -149,7 +146,7 @@
    • - @@ -159,7 +156,7 @@
      • - 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 new file mode 100644 index 0000000000..2ba56a5b88 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/overlays/rowdeleteconfirm.html @@ -0,0 +1,16 @@ +
        + +
        + You are deleting the row configuration {{model.layout.name}}. +
        + +

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

        + + ? + +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/icon.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/icon.prevalues.html index 2d3d4eeae2..8a11cb516d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/icon.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/icon.prevalues.html @@ -2,7 +2,7 @@
        - +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html index 0499bea713..42597f0c82 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html @@ -1,10 +1,12 @@ 
        - + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.controller.js index a02215f452..acfb114307 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.controller.js @@ -15,6 +15,8 @@ vm.focusLayoutName = false; vm.layoutsSortableOptions = { + axis: "y", + containment: "parent", distance: 10, tolerance: "pointer", opacity: 0.7, @@ -41,7 +43,6 @@ }; $scope.model.value.push(layout); - } function showPrompt(layout) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html index 1240a61fbb..acc3f1d261 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html @@ -1,49 +1,54 @@
        -
        +
        -
        +
        - +
        -
        + - +
        -
        - -
        + -
        +
        + +
        -
        - - {{ layout.name }} - (system layout) -
        +
        -
        - -
        +
        + + {{ layout.name }} + (system layout) +
        -
        - -
        - - - -
        -
        +
        + +
        -
        +
        + - +
        + + +
        +
        -
        +
        + +
        + + + +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js index 4230633e96..fd49d3f706 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js @@ -86,22 +86,20 @@ } function markAsSensitive() { - angular.forEach($scope.options.includeProperties, function (option) { + $scope.options.includeProperties.forEach(function (option) { option.isSensitive = false; - angular.forEach($scope.items, - function (item) { + $scope.items.forEach(function (item) { - angular.forEach(item.properties, - function (property) { + item.properties.forEach(function (property) { - if (option.alias === property.alias) { - option.isSensitive = property.isSensitive; - } + if (option.alias === property.alias) { + option.isSensitive = property.isSensitive; + } - }); + }); - }); + }); }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index 9a86dc575a..d98dc92f24 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -227,26 +227,21 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time if (err.status && err.status >= 500) { // Open ysod overlay - $scope.ysodOverlay = { - view: "ysod", - error: err, - show: true - }; + overlayService.ysod(err); } $timeout(function () { $scope.bulkStatus = ""; $scope.actionInProgress = false; - }, - 500); + }, 500); - if (successMsgPromise) { - localizationService.localize("bulk_done") - .then(function (v) { - successMsgPromise.then(function (successMsg) { - notificationsService.success(v, successMsg); - }) - }); + if (successMsgPromise) + { + localizationService.localize("bulk_done").then(function (v) { + successMsgPromise.then(function (successMsg) { + notificationsService.success(v, successMsg); + }) + }); } } @@ -271,7 +266,6 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time with simple values */ $scope.getContent = function (contentId) { - $scope.reloadView($scope.contentId, true); } @@ -327,8 +321,6 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time }); }; - - $scope.makeSearch = function() { if ($scope.options.filter !== null && $scope.options.filter !== undefined) { $scope.options.pageNumber = 1; @@ -408,7 +400,6 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time dialog.title = value; overlayService.open(dialog); }); - }; function performDelete() { @@ -704,8 +695,6 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time // set what we've got on the result result[alias] = value; }); - - } function isDate(val) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index ee1847b430..05a294cc1c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -14,29 +14,28 @@
        -
        - - - - @@ -53,13 +52,13 @@ - - @@ -230,11 +229,4 @@
        - - -
        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 027643eee1..c6f7c85c0b 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 @@ -29,8 +29,8 @@ + text="{{language.name}}"> +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.controller.js index df97d67f5d..650b1b8438 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.controller.js @@ -18,7 +18,7 @@ $scope.model.disableSubmitButton = !firstSelected; if (language.isMandatory) { - angular.forEach($scope.model.languages, function (lang) { + $scope.model.languages.forEach(function (lang) { if (lang !== language) { lang.unpublish = true; lang.disabled = language.unpublish; 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 254187bdd1..5806bb8f02 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 @@ -30,8 +30,8 @@ model="language.unpublish" on-change="vm.changeSelection(language)" text="{{language.name}}" - disabled="language.disabled" - /> + disabled="language.disabled"> +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html index 59e6fcd21c..f87c88a467 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html @@ -31,6 +31,7 @@ diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html index 4c53ac5d17..b1cafafb0d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html @@ -10,13 +10,11 @@
        - + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.html index 9b59d48ab9..2715e11b15 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.html @@ -1,11 +1,15 @@ diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js index 95e595a97a..c3137360e2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js @@ -56,10 +56,9 @@ function memberPickerController($scope, entityResource, iconHelper, angularHelpe }; editorService.treePicker(memberPicker); - }; - $scope.remove =function(index){ + $scope.remove = function (index) { $scope.renderModel.splice(index, 1); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.html index d968f08d71..99f7fffba8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.html @@ -10,13 +10,12 @@
        - + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.controller.js index aaf41f3083..42ce10c519 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.controller.js @@ -17,7 +17,7 @@ $scope.model.value = []; } - //add any fields that there isn't values for + // Add any fields that there isn't values for if ($scope.model.config.min > 0) { for (var i = 0; i < $scope.model.config.min; i++) { if ((i + 1) > $scope.model.value.length) { @@ -37,7 +37,7 @@ if ($scope.model.config.max <= 0 && txtBoxValue.value || $scope.model.value.length < $scope.model.config.max && txtBoxValue.value) { var newItemIndex = index + 1; $scope.model.value.splice(newItemIndex, 0, { value: "" }); - //Focus on the newly added value + // Focus on the newly added value $scope.model.value[newItemIndex].hasFocus = true; } break; @@ -47,7 +47,7 @@ var remainder = []; // Used to require an extra hit on backspace for the field to be removed - if(txtBoxValue.value === "") { + if (txtBoxValue.value === "") { backspaceHits++; } else { backspaceHits = 0; @@ -64,11 +64,11 @@ var prevItemIndex = index - 1; - //Set focus back on false as the directive only watches for true - if(prevItemIndex >= 0) { + // Set focus back on false as the directive only watches for true + if (prevItemIndex >= 0) { $scope.model.value[prevItemIndex].hasFocus = false; $timeout(function () { - //Focus on the previous value + // Focus on the previous value $scope.model.value[prevItemIndex].hasFocus = true; }); } @@ -81,12 +81,13 @@ default: } validate(); - } + }; $scope.add = function () { if ($scope.model.config.max <= 0 || $scope.model.value.length < $scope.model.config.max) { $scope.model.value.push({ value: "" }); - // focus new value + + // Focus new value var newItemIndex = $scope.model.value.length - 1; $scope.model.value[newItemIndex].hasFocus = true; } @@ -106,7 +107,7 @@ $scope.model.value = remainder; }; - $scope.showPrompt = function (idx, item){ + $scope.showPrompt = function (idx, item) { var i = $scope.model.value.indexOf(item); @@ -114,11 +115,11 @@ if (i === idx) { $scope.promptIsVisible = i; } - } + }; - $scope.hidePrompt = function(){ + $scope.hidePrompt = function () { $scope.promptIsVisible = "-1"; - } + }; function validate() { if ($scope.multipleTextboxForm) { @@ -126,10 +127,22 @@ $scope.multipleTextboxForm.mandatory.$setValidity("minCount", !invalid); } } + $timeout(function () { validate(); }); - + + // We always need to ensure we dont submit anything broken + var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { + + // Filter to items with values + $scope.model.value = $scope.model.value.filter(el => el.value.trim() !== "") || []; + }); + + // When the scope is destroyed we need to unsubscribe + $scope.$on('$destroy', function () { + unsubscribe(); + }); } angular.module("umbraco").controller("Umbraco.PropertyEditors.MultipleTextBoxController", MultipleTextBoxController); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.html index 85221c61f7..6a9826ac3c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.html @@ -2,19 +2,20 @@
        - + +
        - - + +
        - - @@ -22,11 +23,13 @@
        - Add - + +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.html index ff1969aab8..36c4f8cf84 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.html @@ -1,6 +1,6 @@ 
        -

        -

        +

        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

        @@ -17,13 +17,14 @@
        - +
        @@ -40,21 +41,21 @@ Add {{model.config.minNumber - renderModel.length}} item(s) - You can only have {{model.config.maxNumber}} items selected + You can only have {{model.config.maxNumber}} url(s) selected - Add up to {{model.config.maxNumber}} items + Add up to {{model.config.maxNumber}} url(s) - You can only have {{model.config.maxNumber}} items selected + You can only have {{model.config.maxNumber}} url(s) selected - Add at least {{model.config.minNumber}} item(s) + You need to add at least {{model.config.minNumber}} url(s)
        @@ -65,12 +66,12 @@
        - You need to add at least {{model.config.minNumber}} items + You need to add at least {{model.config.minNumber}} url(s)
        - You can only have {{model.config.maxNumber}} items selected + You can only have {{model.config.maxNumber}} url(s) selected
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js index fe9725a7d8..11a3b58c55 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js @@ -98,6 +98,8 @@ vm.wideMode = Object.toBoolean(model.config.hideLabel); vm.hasContentTypes = model.config.contentTypes.length > 0; + var cultureChanged = eventsService.on('editors.content.cultureChanged', (name, args) => updateModel()); + var labels = {}; vm.labels = labels; localizationService.localizeMany(["grid_addElement", "content_createEmpty", "actions_copy"]).then(function (data) { @@ -167,8 +169,6 @@ isDisabled: true } - - // helper to force the current form into the dirty state function setDirty() { if ($scope.$parent.$parent.propertyForm) { @@ -187,17 +187,29 @@ }; vm.openNodeTypePicker = function ($event) { - if (vm.overlayMenu || vm.nodes.length >= vm.maxItems) { + + if (vm.nodes.length >= vm.maxItems) { return; } - vm.overlayMenu = { - show: false, - style: {}, - filter: vm.scaffolds.length > 12 ? true : false, + var availableItems = []; + _.each(vm.scaffolds, function (scaffold) { + availableItems.push({ + alias: scaffold.contentTypeAlias, + name: scaffold.contentTypeName, + icon: iconHelper.convertFromLegacyIcon(scaffold.icon), + tooltip: scaffold.documentType.description + }); + }); + + const dialog = { + view: "itempicker", orderBy: "$index", view: "itempicker", event: $event, + filter: availableItems.length > 12, + size: availableItems.length > 6 ? "medium" : "small", + availableItems: availableItems, clickPasteItem: function (item) { if (item.type === "elementTypeArray") { _.each(item.data, function (entry) { @@ -206,44 +218,30 @@ } else { pasteFromClipboard(item.data); } - vm.overlayMenu.show = false; - vm.overlayMenu = null; + + overlayService.close(); }, submit: function (model) { if (model && model.selectedItem) { addNode(model.selectedItem.alias); } - vm.overlayMenu.show = false; - vm.overlayMenu = null; + + overlayService.close(); }, close: function () { - vm.overlayMenu.show = false; - vm.overlayMenu = null; + overlayService.close(); } }; - // this could be used for future limiting on node types - vm.overlayMenu.availableItems = []; - _.each(vm.scaffolds, function (scaffold) { - vm.overlayMenu.availableItems.push({ - alias: scaffold.contentTypeAlias, - name: scaffold.contentTypeName, - icon: iconHelper.convertFromLegacyIcon(scaffold.icon), - tooltip: scaffold.documentType.description - }); - }); - - if (vm.overlayMenu.availableItems.length === 0) { + if (dialog.availableItems.length === 0) { return; } - vm.overlayMenu.size = vm.overlayMenu.availableItems.length > 6 ? "medium" : "small"; - - vm.overlayMenu.pasteItems = []; + dialog.pasteItems = []; var singleEntriesForPaste = clipboardService.retriveEntriesOfType("elementType", contentTypeAliases); _.each(singleEntriesForPaste, function (entry) { - vm.overlayMenu.pasteItems.push({ + dialog.pasteItems.push({ type: "elementType", name: entry.label, data: entry.data, @@ -253,7 +251,7 @@ var arrayEntriesForPaste = clipboardService.retriveEntriesOfType("elementTypeArray", contentTypeAliases); _.each(arrayEntriesForPaste, function (entry) { - vm.overlayMenu.pasteItems.push({ + dialog.pasteItems.push({ type: "elementTypeArray", name: entry.label, data: entry.data, @@ -261,26 +259,27 @@ }); }); - vm.overlayMenu.title = labels.grid_addElement; - vm.overlayMenu.hideHeader = vm.overlayMenu.pasteItems.length > 0; + dialog.title = dialog.pasteItems.length > 0 ? labels.grid_addElement : labels.content_createEmpty; - vm.overlayMenu.clickClearPaste = function ($event) { + dialog.clickClearPaste = function ($event) { $event.stopPropagation(); $event.preventDefault(); clipboardService.clearEntriesOfType("elementType", contentTypeAliases); clipboardService.clearEntriesOfType("elementTypeArray", contentTypeAliases); - vm.overlayMenu.pasteItems = [];// This dialog is not connected via the clipboardService events, so we need to update manually. - vm.overlayMenu.hideHeader = false; + dialog.pasteItems = [];// This dialog is not connected via the clipboardService events, so we need to update manually. + dialog.overlayMenu.hideHeader = false; }; - if (vm.overlayMenu.availableItems.length === 1 && vm.overlayMenu.pasteItems.length === 0) { + if (dialog.availableItems.length === 1 && dialog.pasteItems.length === 0) { // only one scaffold type - no need to display the picker addNode(vm.scaffolds[0].contentTypeAlias); - vm.overlayMenu = null; + + dialog.close(); + return; } - vm.overlayMenu.show = true; + overlayService.open(dialog); }; vm.editNode = function (idx) { @@ -507,8 +506,7 @@ if (tab) { scaffold.variants[0].tabs.push(tab); - angular.forEach(tab.properties, - function (property) { + tab.properties.forEach(function (property) { if (_.find(notSupported, function (x) { return x === property.editor; })) { property.notSupported = true; // TODO: Not supported message to be replaced with 'content_nestedContentEditorNotSupported' dictionary key. Currently not possible due to async/timing quirk. @@ -713,6 +711,7 @@ $scope.$on("$destroy", function () { unsubscribe(); + cultureChanged(); watcher(); }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html index 896f8cf4a4..2f3856b101 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html @@ -47,13 +47,17 @@
        - + No content types are configured for this property.
        - @@ -75,12 +79,4 @@ - - -
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.controller.js index 33e2b834f3..47d1f401c7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.controller.js @@ -29,11 +29,15 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.RteController", // extend commands with properties for font-icon and if it is a custom command $scope.tinyMceConfig.commands = _.map($scope.tinyMceConfig.commands, function (obj) { var icon = getFontIcon(obj.alias); - return angular.extend(obj, { + + var objCmd = Utilities.extend(obj, { fontIcon: icon.name, isCustom: icon.isCustom, - selected: $scope.model.value.toolbar.indexOf(obj.alias) >= 0 + selected: $scope.model.value.toolbar.indexOf(obj.alias) >= 0, + icon: "mce-ico " + (icon.isCustom ? ' mce-i-custom ' : ' mce-i-') + icon.name }); + + return objCmd; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html index d70f469e6f..96de0cd040 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html @@ -2,11 +2,12 @@
        - +
        @@ -14,10 +15,12 @@
        - + +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html index ea0c2ef7bc..27c59194c1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html @@ -1,6 +1,6 @@ -
        +
        -
        +
        + +
        + + +
        + + + + + +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/relationTypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationTypes/edit.controller.js index a39b48c278..a0b2a6afa1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationTypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/relationTypes/edit.controller.js @@ -102,7 +102,7 @@ function RelationTypeEditController($scope, $routeParams, relationTypeResource, function formatDates(relations) { if (relations) { userService.getCurrentUser().then(function (currentUser) { - angular.forEach(relations, function (relation) { + relations.forEach(function (relation) { relation.timestampFormatted = dateHelper.getLocalDate(relation.createDate, currentUser.locale, 'LLL'); }); }); diff --git a/src/Umbraco.Web.UI.Client/src/views/stylesheets/infiniteeditors/richtextrule/richtextrule.html b/src/Umbraco.Web.UI.Client/src/views/stylesheets/infiniteeditors/richtextrule/richtextrule.html index cc5487d747..20c62cbd77 100644 --- a/src/Umbraco.Web.UI.Client/src/views/stylesheets/infiniteeditors/richtextrule/richtextrule.html +++ b/src/Umbraco.Web.UI.Client/src/views/stylesheets/infiniteeditors/richtextrule/richtextrule.html @@ -2,7 +2,7 @@ - + - - ' - + + diff --git a/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.controller.js b/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.controller.js index 7a3a51cf2e..de2865d843 100644 --- a/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.controller.js @@ -59,7 +59,6 @@ angular.module("umbraco").controller("Umbraco.Editors.StyleSheets.RulesControlle }; editorService.open(ruleDialog); - } function setDirty() { diff --git a/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.html b/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.html index 213499740f..8187b88152 100644 --- a/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.html +++ b/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.html @@ -9,13 +9,11 @@
        - -
        - {{rule.name}} -
        + +
        {{rule.name}}
        - Edit - Remove + +
        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 2e3bc6eb80..7b527804f5 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 @@ -549,7 +549,7 @@ var availableMasterTemplates = []; // filter out the current template and the selected master template - angular.forEach(vm.templates, function (template) { + vm.templates.forEach(function (template) { if (template.alias !== vm.template.alias && template.alias !== vm.template.masterTemplateAlias) { var templatePathArray = template.path.split(','); // filter descendant templates of current template @@ -602,7 +602,7 @@ function getMasterTemplateName(masterTemplateAlias, templates) { if (masterTemplateAlias) { var templateName = ""; - angular.forEach(templates, function (template) { + templates.forEach(function (template) { if (template.alias === masterTemplateAlias) { templateName = template.name; } diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.html b/src/Umbraco.Web.UI.Client/src/views/templates/edit.html index c5ad1b68d0..255b2c4885 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.html @@ -30,12 +30,11 @@
        - - - - +
        - +
        @@ -97,7 +102,7 @@ - + - + diff --git a/src/Umbraco.Web.UI.Client/src/views/users/group.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/group.controller.js index f996e944db..4ca4576755 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/group.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/group.controller.js @@ -185,7 +185,7 @@ * however the list to display the permissions isn't via the dictionary way so we need to format it */ function formatGranularPermissionSelection() { - angular.forEach(vm.userGroup.assignedPermissions, function (node) { + vm.userGroup.assignedPermissions.forEach(function (node) { formatGranularPermissionSelectionForNode(node); }); } @@ -193,8 +193,8 @@ function formatGranularPermissionSelectionForNode(node) { //the dictionary is assigned via node.permissions we will reformat to node.allowedPermissions node.allowedPermissions = []; - angular.forEach(node.permissions, function (permissions, key) { - angular.forEach(permissions, function (p) { + Object.values(node.permissions).forEach(function (permissions) { + permissions.forEach(function (p) { if (p.checked) { node.allowedPermissions.push(p); } @@ -299,7 +299,7 @@ } function setSectionIcon(sections) { - angular.forEach(sections, function (section) { + sections.forEach(function (section) { section.icon = "icon-section"; }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js index 2845c8df68..df2bd997b4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js @@ -269,7 +269,7 @@ submit: function (model) { // select items if (model.selection) { - angular.forEach(model.selection, function (item) { + model.selection.forEach(function (item) { if (item.id === "-1") { item.name = vm.labels.contentRoot; item.icon = "icon-folder"; @@ -298,7 +298,7 @@ submit: function (model) { // select items if (model.selection) { - angular.forEach(model.selection, function (item) { + model.selection.forEach(function (item) { if (item.id === "-1") { item.name = vm.labels.mediaRoot; item.icon = "icon-folder"; @@ -321,7 +321,7 @@ var found = false; // check if item is already in the selected list if (selection.length > 0) { - angular.forEach(selection, function (selectedItem) { + selection.forEach(function (selectedItem) { if (selectedItem.udi === item.udi) { found = true; } diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js index 31c52a344b..4b81e7c11c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js @@ -123,7 +123,7 @@ } function clearSelection() { - angular.forEach(vm.userGroups, function (userGroup) { + vm.userGroups.forEach(function (userGroup) { userGroup.selected = false; }); vm.selection = []; diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js index 2217628872..cb211834b2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js @@ -274,7 +274,7 @@ } function clearSelection() { - angular.forEach(vm.users, function (user) { + vm.users.forEach(function (user) { user.selected = false; }); vm.selection = []; @@ -305,7 +305,7 @@ vm.disableUserButtonState = "busy"; usersResource.disableUsers(vm.selection).then(function (data) { // update userState - angular.forEach(vm.selection, function (userId) { + vm.selection.forEach(function (userId) { var user = getUserFromArrayById(userId, vm.users); if (user) { user.userState = 1; @@ -326,7 +326,7 @@ vm.enableUserButtonState = "busy"; usersResource.enableUsers(vm.selection).then(function (data) { // update userState - angular.forEach(vm.selection, function (userId) { + vm.selection.forEach(function (userId) { var user = getUserFromArrayById(userId, vm.users); if (user) { user.userState = 0; @@ -345,7 +345,7 @@ vm.unlockUserButtonState = "busy"; usersResource.unlockUsers(vm.selection).then(function (data) { // update userState - angular.forEach(vm.selection, function (userId) { + vm.selection.forEach(function (userId) { var user = getUserFromArrayById(userId, vm.users); if (user) { user.userState = 0; @@ -423,14 +423,14 @@ function selectAll() { if (areAllSelected()) { vm.selection = []; - angular.forEach(vm.users, function (user) { + vm.users.forEach(function (user) { user.selected = false; }); } else { // clear selection so we don't add the same user twice vm.selection = []; // select all users - angular.forEach(vm.users, function (user) { + vm.users.forEach(function (user) { // prevent the current user to be selected if (!user.isCurrentUser) { user.selected = true; @@ -470,7 +470,7 @@ function getFilterName(array) { var name = vm.labels.all; var found = false; - angular.forEach(array, function (item) { + array.forEach(function (item) { if (item.selected) { if (!found) { name = item.name @@ -491,7 +491,7 @@ //If the selection is "ALL" then we need to unselect everything else since this is an 'odd' filter if (userState.key === "All") { - angular.forEach(vm.userStatesFilter, function (i) { + vm.userStatesFilter.forEach(function (i) { i.selected = false; }); //we can't unselect All @@ -500,7 +500,7 @@ vm.usersOptions.userStates = []; } else { - angular.forEach(vm.userStatesFilter, function (i) { + vm.userStatesFilter.forEach(function (i) { if (i.key === "All") { i.selected = false; } @@ -715,13 +715,13 @@ } function setUserDisplayState(users) { - angular.forEach(users, function (user) { + users.forEach(function (user) { user.userDisplayState = usersHelper.getUserStateFromValue(user.userState); }); } function formatDates(users) { - angular.forEach(users, function (user) { + users.forEach(function (user) { if (user.lastLoginDate) { var dateVal; var serverOffset = Umbraco.Sys.ServerVariables.application.serverTimeOffset; @@ -752,7 +752,7 @@ var firstSelectedUserGroups; - angular.forEach(users, function (user) { + users.forEach(function (user) { if (!user.selected) { return; diff --git a/src/Umbraco.Web.UI.Client/test/unit/app/propertyeditors/content-picker-controller.spec.js b/src/Umbraco.Web.UI.Client/test/unit/app/propertyeditors/content-picker-controller.spec.js index 49d8914ac6..c111421d75 100644 --- a/src/Umbraco.Web.UI.Client/test/unit/app/propertyeditors/content-picker-controller.spec.js +++ b/src/Umbraco.Web.UI.Client/test/unit/app/propertyeditors/content-picker-controller.spec.js @@ -5,11 +5,11 @@ describe('Content picker controller tests', function () { beforeEach(module('umbraco')); //inject the contentMocks service - beforeEach(inject(function ($rootScope, $controller, angularHelper, $httpBackend, entityMocks, mocksUtils, localizationMocks) { + beforeEach(inject(function ($rootScope, $controller, angularHelper, $httpBackend, entityMocks, mocksUtils, localizationMocks, userMocks) { //for these tests we don't want any authorization to occur - mocksUtils.disableAuth(); - + mocksUtils.setAuth(); + httpBackend = $httpBackend; scope = $rootScope.$new(); @@ -34,6 +34,7 @@ describe('Content picker controller tests', function () { //see /mocks/content.mocks.js for how its setup entityMocks.register(); localizationMocks.register(); + userMocks.register(); controller = $controller('Umbraco.PropertyEditors.ContentPickerController', { $scope: scope, @@ -42,7 +43,7 @@ describe('Content picker controller tests', function () { //For controller tests its easiest to have the digest and flush happen here //since its intially always the same $http calls made - + //scope.$digest resolves the promise against the httpbackend scope.$digest(); diff --git a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj index f832deea13..3e1518abdd 100644 --- a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj +++ b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj @@ -21,6 +21,12 @@ + + + + + + diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/cs.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/cs.xml index fe7e8ac638..4126d1d224 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/cs.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/cs.xml @@ -1,8 +1,8 @@ - umbraco - http://umbraco.org + Umbraco komunita + https://our.umbraco.com/documentation/Extending-Umbraco/Language-Files Kultura a názvy hostitelů @@ -11,10 +11,13 @@ Změnit typ dokumentu Kopírovat Vytvořit + Exportovat Vytvořit balíček + Vytvořit skupinu Odstranit Deaktivovat Vyprázdnit koš + Aktivovat Exportovat typ dokumentu Importovat typ dokumentu Importovat balíček @@ -28,17 +31,64 @@ Znovu načíst uzly Znovu publikovat celý web Práva + Přejmenovat + Obnovit + Nastavit oprávnění pro stránku %0% + Kam zkopírovat + Kam přesunout + do struktury stromu pod + Choose where to copy the selected item(s) + Choose where to move the selected item(s) + bylo přesunuto + bylo zkopírováno + bylo smazáno Vrátit starší verzi Odeslat k publikování Odeslat k překladu + Nastavit skupinu Seřadit Přeložit Aktualizovat + Nastavit oprávnění + Odemknout + Vytvořit šablonu obsahu + Přeposlat pozvánku + + + Obsah + Administrace + Struktura + Ostatní + + + Povolit přístup k přiřazování kultury a názvů hostitelů + Povolit přístup k zobrazení protokolu historie uzlu + Povolit přístup k zobrazení uzlu + Povolit přístup ke změně typu dokumentu daného uzlu + Povolit přístup ke kopírování uzlu + Povolit přístup k vytváření uzlů + Povolit přístup k mazání uzlů + Povolit přístup k přesunutí uzlu + Povolit přístup k nastavení a změně veřejného přístupu k uzlu + Povolit přístup k publikování uzlu + Povolit přístup k zrušení publikování uzlu + Povolit přístup ke změně oprávnění pro uzel + Povolit přístup k vrácení uzlu do předchozího stavu + Povolit přístup k odeslání uzlu ke schválení před publikováním + Povolit přístup k odeslání uzlu k překladu + Povolit přístup ke změně pořadí uzlů + Povolit přístup k překladu uzlu + Povolit přístup k uložení uzlu + Povolit přístup k vytvoření šablony obsahu + + + Obsah + Info Přístup zakázán. Přidat novou doménu - odebrat + Odebrat Neplatný uzel. Neplatný tvar domény. Doména už byla přiřazena. @@ -49,16 +99,17 @@ Doména '%0%' už byla přiřazena Doména '%0%' byla aktualizována Editace aktuálních domén + + Dědit Kultura nebo dědění kultury po nadřazeném uzlu. Vztahuje se také
        na aktivní uzel.]]>
        Domény - - Zobrazení pro - + Zrušit výběr Vybrat Dělat něco jiného Tučně @@ -77,15 +128,62 @@ Číslovaný seznam Vložit makro Vložit obrázek + Publikovat a zavřít + Publikovat s potomky Editovat vztahy + Zpět na seznam Uložit + Uložit a zavřít Uložit a publikovat + Uložit a naplánovat Uložit a odeslat ke schválení Náhled + Uložit zobrazení seznamu + Naplánovat + Náhled Náhled je deaktivován, protože není přiřazena žádná šablona Vybrat styl Zobrazit styly Vložit tabulku + Generovat modely a zavřít + Uložit a generovat modely + Zpět + Znovu + Obnovit + Smazat štítek + Zrušit + Potvrdit + Další možnosti publikování + + + Zobrazení pro + Obsah smazán + Obsah nepublikován + Obsah nepublikován pro jazyky: %0% + Obsah publikován + Obsah publikován pro jazyky: %0% + Obsah uložen + Obsah uložen pro jazyky: %0% + Obsah přesunut + Obsah zkopírován + Obsah vrácen zpět + Obsah odeslán k publikování + Obsah odeslán k publikování pro jazyky: %0% + Seřadit podřízené položky prováděné uživatelem + Kopírovat + Publikovat + Publikovat + Přesunout + Uložit + Uložit + Smazat + Nepublikovat + Nepublikovat + Vrátit zpět + Odeslat k publikování + Odeslat k publikování + Seřadit + Historie (všechny jazyky) Abyste změnili typ dokumentu pro zvolený obsah, nejprve jej vyberte ze seznamu typů platných pro tohle umístění. @@ -107,7 +205,14 @@ Nelze dokončit mapování vlastností, neboť nejméně jedna z vlastností má definováno více než jedno mapování. Jsou zobrazeny pouze alternativní typy platné pro aktuální umístění. + + Nepodařilo se vytvořit složku pod rodičem s ID %0% + Nepodařilo se vytvořit složku pod rodičem s názvem %0% + Název složky nesmí obsahovat nepovolené znaky. + Odstranění položky se nezdařilo: %0% + + Is Published O této stránce Alias (jak byste popsali obrázek přes telefon) @@ -124,45 +229,146 @@ Tato položko byla změněna po publikování Tato položka není publikována Naposledy publikováno + There are no items to show + There are no items to show in the list. + No child items have been added + No members have been added Typ média Odkaz na položky medií Skupina členů Role Typ člena + No changes have been made Nevybráno žádné datum Titulek stránky + This media item has no link + No content can be added for this item Vlastnosti Tento dokument je publikován, ale není viditelný, protože jeho rodič '%0%' publikován není + Tato jazyková verze je publikována, ale není viditelná, protože její rodič '%0%' publikován není Jejda: tento dokument je publikován, ale není v mezipaměti (vnitřní chyba) + Could not get the url + This document is published but its url would collide with content %0% + This document is published but its url cannot be routed Publikovat + Published + Published (pending changes)> Stav publikování + Publish with descendants to publish %0% and all content items underneath and thereby making their content publicly available.]]> + Publish with descendants to publish the selected languages and the same languages of content items underneath and thereby making their content publicly available.]]> Datum publikování Datum ukončení publikování Datum odebrání + Set date Třídění je aktualizováno Abyste uzly setřídili, jednoduše je přetáhněte anebo klikněte na jednu z hlaviček sloupce. Podržením "shift" nebo "control" při výběru můžete označit uzlů více. Statistika Titulek (volitelně) + Alternative text (optional) Typ Nepublikovat + Draft + Not created Naposledy změněno Datum/čas poslední změny dokumentu Odebrat soubor(y) + Click here to remove the image from the media item + Click here to remove the file from the media item URL adresa dokumentu Člen skupin(y) Není člen skupin(y) Podřízené položky Cíl + This translates to the following time on the server: + What does this mean?]]> + Are you sure you want to delete this item? + Are you sure you want to delete all items? + Property %0% uses editor %1% which is not supported by Nested Content. + No content types are configured for this property. + Add element type + Select element type + Select the group whose properties should be displayed. If left blank, the first group on the element type will be used. + Enter an angular expression to evaluate against each item for its name. Use + to display the item index + Add another text box + Remove this text box + Content root + Include drafts: also publish unpublished content items. + This value is hidden. If you need access to view this value please contact your website administrator. + This value is hidden. + What languages would you like to publish? All languages with content are saved! + What languages would you like to publish? + What languages would you like to save? + All languages with content are saved on creation! + What languages would you like to send for approval? + What languages would you like to schedule? + Select the languages to unpublish. Unpublishing a mandatory language will unpublish all languages. + Published Languages + Unpublished Languages + Unmodified Languages + These languages haven't been created + Ready to Publish? + Ready to Save? + Send for approval + Select the date and time to publish and/or unpublish the content item. + Create new + Paste from clipboard + This item is in the Recycle Bin + + + Vytvořit novou šablonu obsahu z '%0%' + Prázdná + Vybrat obsahovou šablonu + Šablona obsahu byla vytvořena + Šablona obsahu byla vytvořena z '%0%' + Již existuje jiná šablona obsahu se stejným názvem + Šablona obsahu je předdefinovaný obsah, který si editor může vybrat jako základ pro vytváření nového obsahu Klikněte pro nahrání + nebo kliknutím sem vyberte soubory + Sem můžete přetáhnout a nahrát soubory. + Tento soubor nelze nahrát, nemá povolený typ souboru + Maximální velikost souboru je + Nejvyšší složka médií + Nepodařilo se přesunout média + Nadřazené a cílové složky nemohou být stejné + Médium se nepodařilo zkopírovat + Nepodařilo se vytvořit složku pod nadřazeným id %0% + Nepodařilo se přejmenovat složku s id %0% + Přetáhněte své soubory do oblasti + + + Vytvořit nového člena + Všichni členové + Členské skupiny nemají žádné další vlastnosti pro úpravy. Kde chcete vytvořit nový %0% Vytvořit položku pod + Vyberte typ dokumentu, pro který chcete vytvořit šablonu obsahu + Zadejte název složky Vyberte typ a titulek "typy dokumentů".]]> + Typy dokumentů v části Nastavení.]]> + Vybraná stránka ve stromu obsahu neumožňuje vytváření žádných stránek pod ní. + Oprávnění k úpravám pro tento typ dokumentu + Vytvořit nový typ dokumentu + Typy dokumentů v části Nastavení změnou možnosti Povolit jako root v části Oprávnění.]]> "typy medií".]]> + Vybraná média ve stromu neumožňuje vytváření pod nimi žádná další média. + Upravit oprávnění pro tento typ média + Typ dokumentu bez šablony + Nová složka + Nový datový typ + Nový skript JavaScript + Nová prázdná částečná šablona + Nové makro pro částečnou šablonu + Nová částečná šablona ze snippetu + Nové makro částečné šablony ze snippetu + Nové makro pro částečnou šablonu (bez makra) + Nový soubor stylů - stylopis + Nový soubor stylů Rich Text editoru Prohlédnout svůj web @@ -174,35 +380,42 @@ Vítejte - Stay - Discard changes - You have unsaved changes - Are you sure you want to navigate away from this page? - you have unsaved changes + Zůstat zde + Zahodit změny + Máte neuložené změny + Opravdu chcete opustit tuto stránku? Máte neuložené změny. + Publikování zviditelní vybrané položky na webu. + Zrušení publikování odstraní vybrané položky a všechny jejich potomky z webu. + Zrušení publikování odstraní tuto stránku a všechny její potomky z webu. + Máte neuložené změny. Provedením změn typu dokumentu změny zahodíte. - Done - Deleted %0% item - Deleted %0% items - Deleted %0% out of %1% item - Deleted %0% out of %1% items - Published %0% item - Published %0% items - Published %0% out of %1% item - Published %0% out of %1% items - Unpublished %0% item - Unpublished %0% items - Unpublished %0% out of %1% item - Unpublished %0% out of %1% items - Moved %0% item - Moved %0% items - Moved %0% out of %1% item - Moved %0% out of %1% items - Copied %0% item - Copied %0% items - Copied %0% out of %1% item - Copied %0% out of %1% items + Hotovo + Smazána %0% položka + Smazáno %0% položek + Smazána %0% z %1% položek + Smazáno %0% z %1% položek + Publikována %0% položka + Publikováno %0% položek + Publikována %0% z %1% položek + Publikováno %0% z %1% položek + Zrušeno publikování %0% položky + Zrušeno publikování %0% položek + Zrušeno publikování %0% z %1% položek + Zrušeno publikování %0% z %1% položek + Přesunuta %0% položka + Přesunuto %0% položek + Přesunuta %0% z %1% položek + Přesunuto %0% z %1% položek + Zkopírována %0% položka + Zkopírováno %0% položek + Zkopírována %0% z %1% položek + Zkopírováno %0% z %1% položek + Titulek odkazu + Odkaz + Kotva / dotaz Název Spravovat názvy hostitelů Zavřít toto okno @@ -213,6 +426,7 @@ Vyjmout Editovat položku slovníku Editovat jazyk + Edit selected media Vložit místní odkaz Vložit znak Vložit grafický titulek @@ -220,14 +434,20 @@ Vložit odkaz Kliknout pro přidání makra Vložit tabulku + Tím se odstraní jazyk + Změna kultury jazyka může být náročná operace a bude mít za následek opětovné sestavení mezipaměti obsahu a indexů Naposledy editováno Odkaz Místní odkaz: Při používání místních odkazů vložte znak "#" před odkaz Otevřít v novém okně? + Nastavení makra Toto makro nemá žádné vlastnosti, které by bylo možno editovat Vložit Editovat oprávnění pro + Nastavit oprávnění pro + Nastavit oprávnění pro %0% pro skupinu %1% + Vyberte skupiny uživatelů, pro které chcete nastavit oprávnění Položky koše jsou nyní mazány. Nezavírejte, prosím, toto okno, dokud operace probíhá Koš je nyní prázdný Odebrání položek z koše způsobí jejich trvalé odstranění @@ -243,21 +463,109 @@ Klikněte na obrázek pro zobrazení v plné velikosti Vybrat položku Zobrazit položku mezipaměti + Navázat na originál + Včetně potomků + Nejpřátelštější komunita + Odkaz na stránku + Otevře propojený dokument v novém okně nebo na kartě + Odkaz na média + Vybrat počáteční uzel obsahu + Vybrat média + Vybrat typ média + Vybrat ikonu + Vybrat položku + Vybrat odkaz + Vybrat makro + Vybrat obsah + Vybrat typ obsahu + Vybrat počáteční uzel média + Vybrat člena + Vybrat skupinu členů + Vybrat typ člena + Vybrat uzel + Vybrat sekce + Vybrat uživatele + Nebyly nalezeny žádné ikony + Pro toto makro neexistují žádné parametry + K dispozici nejsou žádná makra + Externí poskytovatelé přihlášení + Podrobnosti o výjimce + Stacktrace + Vnitřní výjimka + Propojit se + Odpojit se + účet + Vybrat editora + Vybrat snippet + Tímto odstraníte uzel a všechny jeho jazyky. Pokud chcete smazat pouze jeden jazyk, měli byste zrušit publikování uzlu v tomto jazyce. + + + Nejsou žádné položky ve slovníku. %0%' níže.
        Můžete přidat další jazyky v nabídce 'jazyky' nalevo.]]>
        Název jazyka + + Přehled slovníku + + + Konfigurovaní vyhledávače + Zobrazuje vlastnosti a nástroje pro libovolný konfigurovaný vyhledávač (např. pro víceindexový vyhledávač) + Hodnoty pole + Stav + Stav indexu a jeho čitelnost + Indexery + Informace o indexu + Uvádí vlastnosti indexu + Spravovat indexy Examine + Umožňuje zobrazit podrobnosti každého indexu a poskytuje některé nástroje pro správu indexů + Znovu vytvořit index + V závislosti na tom, kolik obsahu je na vašem webu, může to chvíli trvat.
        Nedoporučuje se znovu vytvářet index v době vysokého provozu na webu nebo při úpravách obsahu editory. + ]]> +
        + Vyhledávače + Prohledat index a zobrazit výsledky + Nástroje + Nástroje pro správu indexu + pole + Index nelze číst a bude nutné jej znovu sestavit + Proces trvá déle, než se očekávalo, zkontrolujte Umbraco log a zkontrolujte, zda během této operace nedošlo k chybám + Tento index nelze znovu sestavit, protože nemá přiřazen + IIndexPopulator Zadejte Vaše uživatelské jméno Zadejte Vaše heslo + Potvrďte heslo Pojmenujte %0%... Zadejte jméno... + Zadejte e-mail... + Zadejte uživatelské jméno... + Popisek... + Zadejte popis... Pište pro vyhledání... Pište pro filtrování... + Pište pro vložení štítků (po každém stiskněte klávesu Enter)... + Vložte svůj e-mail + Vložte zprávu... + Vaše uživatelské jméno je obvykle váš e-mail + #hodnota or ?klíč=hodnota + Vložte alias... + Generování aliasu... + Vytvořit vlastní zobrazení seznamu + Odebrat vlastní zobrazení seznamu + Typ obsahu, typ média nebo typ člena s tímto aliasem již existuje + + + Přejmenováno + Sem zadejte nový název složky + %0% přejmenováno na %1% Přidat předlohu @@ -271,6 +579,15 @@ Související stylopisy Zobrazit jmenovku Šířka a výška + Všechny typy vlastností a údaje o nich + použití tohoto datového typu bude trvale smazáno, potvrďte, že je chcete odstranit + Ano, smazat + a všechny typy vlastností a data vlastností používající tento typ dat + Vyberte složku, kterou chcete přesunout + do stromové struktury níže + byla přesunuta pod + %0% vymažete vlastnosti a jejich data z následujících položek]]> + Rozumím, že tato akce odstraní vlastnosti a data založená na tomto datovém typu Vaše data byla uložena, ale než budete moci publikovat tuto stránku, je třeba odstranit některé chyby: @@ -286,10 +603,12 @@ %0% není ve správném formátu + Ze serveru byla přijata chyba Použití daného typu souboru bylo zakázáno adminitrátorem UPOZORNĚNÍ! I když CodeMirror je dle konfigurace povolený, je zakázaný v Internet Exploreru, protože není dost stabilní. Vyplňte, prosím, alias i název nového typu vlastností! Vyskytl se problém při čtení/zápisu do určeného souboru nebo adresáře + Chyba při načítání skriptu částečné šablony (soubor: %0%) Uveďte, prosím, titulek Vyberte, prosím, typ Chystáte se obrázek zvětšit více, než je jeho původní rozměr. Opravdu chcete pokračovat? @@ -298,34 +617,43 @@ Žádne aktivní styly nejsou dostupné Umístěte, prosím, kurzor nalevo od těch dvou buňek, které chcete sloučit Nemužete rozdělit buňku, která nebyla sloučená. + Tato vlastnost je neplatná + Volby O... Akce Akce Přidat Alias + Vše Jste si jistí? + Zpět + Zpět na přehled Okraj o Zrušit Okraj buňky Vybrat + Vyčistit Zavřít Zavřít okno Komentovat Potvrdit + Omezit Zachovat proporce + Obsah Pokračovat Kopírovat Vytvořit - Databáse + Databáze Datum Výchozí Odstranit Odstraněno Odstraňování... Vzhled + Slovník Rozměry Dolů Stáhnout @@ -334,55 +662,85 @@ Prvky Email Chyba + Pole Najít + První + Focal point + Obecné + Skupiny + Skupina Výška Nápověda + Skrýt + Historie Ikona + Id Import + Zahrnout podsložky do vyhledávání + Info Vnitřní okraj Vložit Instalovat + Neplatné Vyrovnat + Popisek Jazyk + Poslední Rozvržení + Odkazy Nahrávání Zamčeno Přihlášení Odhlášení Odhlášení Makro + Povinné + Zpráva Přesunout Název Nový Následující Ne z + Vypnuto OK Otevřít + Zapnuto nebo + Seřadit podle Heslo Cesta Moment, prosím... Předchozí Vlastnosti + Obnovit Email pro obdržení formulářových dat Koš + Váš koš je prázdný + Znovu načíst Zbývající + Odebrat Přejmenovat Obnovit Povinné + Načíst Zopakovat Oprávnění + Plánované publikování Hledat + Litujeme, ale nemůžeme najít to, co hledáte. + Nebyly přidány žádné položky Server + Nastavení Zobrazit Zobrazit stránku při odeslání Rozměr Seřadit - Submit - - Typ - Pro hledání pište... + Stav + Potvrdit + Zadejte + Pište pro vyhledávání... + pod Nahoru Aktualizovat Povýšit @@ -397,18 +755,57 @@ Ano Složka Výsledky hledání - Reorder - I am done reordering + Přesunout + Skončil jsem s přesouváním + Náhled + Změnit heslo + na + Seznam + Ukládám... + aktuální + Vložené + vybrané + Další + Články + Videa + Vyčistit + Instalování + + + Modrá + + + Přidat skupinu + Přidat vlastnost + Přidat editor + Přidat šablonu + Přidat vnořený uzel + Přidat potomka + Upravit datový typ + Navigace v sekcích + Klávesové zkratky + zobrazit klávesové zkratky + Přepnout zobrazení seznamu + Přepnout povolení jako root + Okomentovat/Odkomentovat řádky + Odebrat řádek + Kopírovat řádky nahoru + Kopírovat řádky dolů + Přesunout řádky nahoru + Přesunout řádky dolů + Obecný + Editor + Přepnout povolení jazykových verzí - Background color - Bold - Text color + Barva pozadí + Tučně + Barva písma Font Text - Page + Stránka Instalátor se nemůže připojit k databázi. @@ -441,7 +838,7 @@ Heslo výchozího uživatele bylo úspěšně změněno od doby instalace!

        Netřeba nic dalšího dělat. Klikněte na Následující pro pokračování.]]> Heslo je změněno! Mějte skvělý start, sledujte naše uváděcí videa - Kliknutím na tlačítko následující (nebo modifikováním umbracoConfigurationStatus v souboru web.config) přijímáte licenci tohoto software tak, jak je uvedena v poli níže. Upozorňujeme, že tato distribuce umbraca se skládá ze dvou různých licencí, open source MIT licence pro framework a umbraco freeware licence, která pokrývá UI. + Kliknutím na tlačítko následující (nebo modifikováním umbracoConfigurationStatus v souboru web.config) přijímáte licenci tohoto software tak, jak je uvedena v poli níže. Upozorňujeme, že tato distribuce Umbraca se skládá ze dvou různých licencí, open source MIT licence pro framework a umbraco freeware licence, která pokrývá UI. Není nainstalováno. Dotčené soubory a složky Další informace o nastavování oprávnění pro umbraco zde @@ -515,8 +912,8 @@ Stiskněte "následující" pro spuštění průvodce.]]> - Kód kultury - Název kultury + Kód jazyka + Název jazyka Byli jste nečinní a odhlášení proběhne automaticky za @@ -531,8 +928,100 @@ Šťastný bláznivý pátek Šťastnou kočkobotu přihlašte se níže + Přihlásit se pomocí Relace vypršela © 2001 - %0%
        umbraco.org

        ]]>
        + Zapomenuté heslo? + Na uvedenou adresu bude zaslán e-mail s odkazem pro obnovení hesla + Pokud odpovídá našim záznamům, bude na zadanou adresu zaslán e-mail s pokyny k obnovení hesla + Zobrazit heslo + Skrýt heslo + Vrátit se na přihlašovací obrazovku + Zadejte nové heslo + Vaše heslo bylo aktualizováno + Odkaz, na který jste klikli, je neplatný nebo jeho platnost vypršela + Umbraco: Resetování hesla + + + + + + + + + + + +
        + + + + + +
        + +
        + +
        +
        + + + + + + +
        +
        +
        + + + + +
        + + + + +
        +

        + Vyžadováno resetování hesla +

        +

        + Vaše uživatelské jméno pro přihlášení do back-office Umbraco je: %0% +

        +

        + + + + + + +
        + + Kliknutím na tento odkaz obnovíte své heslo + +
        +

        +

        Pokud nemůžete kliknout na odkaz, zkopírujte a vložte tuto adresu URL do okna prohlížeče:

        + + + + +
        + + %1% + +
        +

        +
        +
        +


        +
        +
        + + + ]]>
        Ovládací panel @@ -555,6 +1044,7 @@ Upravte vaše oznámení pro %0% + Nastavení oznámení bylo uloženo pro - Hi %0%

        + Následující jazyky byly změněny %0% + Ahoj %0%

        Toto je automatická zpráva informující Vás, že úloha '%1%' byla provedena na stránce '%2%' @@ -595,14 +1086,68 @@

        Mějte hezký den!

        Zdraví umbraco robot

        ]]>
        + Byly změněny následující jazyky:

        + %0% + ]]>
        [%0%] Upozornění o %1% na %2% Upozornění + Akce + Vytvořeno + Vytvořit balíček a výběrem balíčku. Balíčky umbraco mají obvykle přípony ".umb" nebo ".zip". ]]> + Tím se balíček odstraní + Přetáhněte sem pro nahrání + Zahrnout všechny podřízené uzly + nebo kliknutím sem vyberte soubor balíčku + Nahrát balíček + Nainstalujte místní balíček výběrem ze svého počítače. Instalujte pouze balíčky ze zdrojů, které znáte a kterým důvěřujete + Nahrát další balíček + Zrušit a nahrát další balíček + Přijímám + podmínky použití + Cesta k souboru + Absolutní cesta k souboru (ie: /bin/umbraco.bin) + Nainstalováno + Nainstalované balíčky + Instalovat místní + Dokončit + Tento balíček nemá žádné zobrazení konfigurace + Zatím nebyly vytvořeny žádné balíčky + Nemáte nainstalované žádné balíčky + Balíčky v pravém horním rohu obrazovky.]]> + Akce balíčku + Web autora + Obsah balíčku + Soubory balíčku + URL ikony + Nainstalovat balíček + Licence + URL licence + Vlastnosti balíčku + Hledat balíčky + Výsledky pro + Nemohli jsme nic najít + Zkuste prosím vyhledat jiný balíček nebo procházet jednotlivé kategorie + Oblíbené + Nové + + karma body + Informace + Vlastník + Přispěvatelé + Vytvořeno + Aktuální verze + .NET verze + Počet stažení + Počet lajků + kompatibilita + Tento balíček je kompatibilní s následujícími verzemi Umbraco, jak ohlásili členové komunity. Plnou kompatibilitu nelze zaručit u verzí hlášených pod 100% + Externí zdroje Autor Dokumentace Meta data balíčku @@ -621,6 +1166,17 @@ Upozornění: všechny dokumenty, media atd. závislé na položkách, které odstraníte, přestanou pracovat a mohou vést k nestabilitě systému, takže odinstalovávejte opatrně. Jste-li na pochybách, kontaktujte autora balíčku.]]>
        Verze balíčku + Upgradování z verze + Balíček je již nainstalován + Tento balíček nelze nainstalovat, vyžaduje minimální verzi Umbraco + Odinstalovávám... + Stahuji... + Importuji... + Instaluji... + Restartuji, prosím čekejte... + Vše je hotovo, váš prohlížeč se nyní obnoví, prosím čekejte... + Klepnutím na tlačítko „Dokončit“ dokončete instalaci a znovu načtěte stránku. + Nahrávám balíček... Vložit s úplným formatováním (nedoporučeno) @@ -629,9 +1185,9 @@ Vložit, ale odstranit formátování (doporučeno) - Ochrana prostřednictvím rolí - použijte členské skupiny umbraca.]]> - Musíte vytvořit členskou skupinu před tím, než můžete použít autentizaci prostřednictvím rolí + Ochrana prostřednictvím rolí + použijte členské skupiny umbraca.]]> + Musíte vytvořit členskou skupinu před tím, než můžete použít autentizaci prostřednictvím rolí Chybová stránka Použita, když jsou lidé přihlášení, ale nemají přístup Vyberte, jak omezit přístup k této stránce @@ -640,16 +1196,28 @@ Přihlašovací stránka Vyberte stránku, která obsahuje přihlašovací formulář Odstranit ochranu + %0%?]]> Vyberte stránky, které obsahují přihlašovací formulář a chybová hlášení Vyberte role, které mají přístup k této stránce + %0%]]> + %0%]]> + Ochrana konkrétních členů + Pokud si přejete udělit přístup konkrétním členům Nastavte přihlašovací jmého a heslo pro tuto stránku Jednouživatelská ochrana Jestliže chcete nastavit jenom jednoduchou ochranu prostřednictvím uživatelského jména a hesla + Nedostatečná uživatelská oprávnění k publikování všech potomků + + @@ -659,7 +1227,9 @@ - Zahrnout nepublikované podřízené stránky + + + Ověření se nezdařilo pro požadovaný jazyk '% 0%'. Tento jazyk byl uložen, ale nezveřejněn. Probíhá publikování - počkejte, prosím... %0% ze %1% stránek bylo publikováno... %0% byla publikována @@ -668,23 +1238,49 @@ ok pro publikování %0% a tedy zveřejnění jejího obsahu.

        Můžete publikovat tuto stránku a všechny její podstránky zatrhnutím publikovat všchny podstránky níže. ]]>
        + Zahrnout nepublikované podřízené stránky Nenakonfigurovali jste žádné schválené barvy + + Můžete vybrat pouze položky typu (typů): %0% + Vybrali jste aktuálně odstraněnou položku obsahu nebo položku v koši + Vybrali jste aktuálně odstraněné položky obsahu nebo položky v koši + + + Smazaná položka + Vybrali jste aktuálně odstraněnou položku média nebo položku v koši + Vybrali jste aktuálně odstraněné položky médií nebo položky médií v koši + V koši + + zadejte externí odkaz + zvolte interní stránku + Nadpis + Odkaz + Otevřít v novém okně + zadejte titulek + Zadejte odkaz + Přidat vnější odkaz Přidat vnitřní odkaz Přidat - Nadpis Vnitřní stránka URL Posunout dolů Posunout nahoru - Otevřít v novém okně Odebrat odkaz + + Zrušit oříznutí + Uložit oříznutí + Přidat nové oříznutí + Hotovo + Vrátit změny + + Vyberte verzi, kterou chcete porovnat s aktuální verzí Současná verze Červený text nebude ve vybrané verzi zobrazen, zelený znamená přidaný].]]> Dokument byl vrácen na starší verzi @@ -697,20 +1293,29 @@ Editovat skriptovací soubor - Domovník Obsah + Formuláře + Média + Členové + Balíčky + Nastavení + Překlad + Uživatelé + + Domovník Kurýr Vývojář Průvodce nastavením Umbraca - Media - Členové Zpravodaje - Nastavení Statistiky - Překlad - Uživatelé Nápověda + + Příručky + Nejlepší videopříručky Umbraco + Navštívit our.umbraco.com + Navštívit umbraco.tv + Výchozí šablona Pro importování typu dokumentu vyhledejte soubor ".udt" ve svém počítači tak, že kliknete na tlačítko "Prohledat" a pak kliknete na "Import" (na následující obrazovce budete vyzváni k potvrzení) @@ -726,16 +1331,25 @@ Tento typ obsahu používá jako nadřazený typ obsahu. Záložky z nadřazených typů obsahu nejsou zobrazeny a mohou byt editovány pouze na nadřazených typech obsahu samotných Na této záložce nejsou definovány žádné vlastnosti. Pro vytvoření nové vlastnosti klikněte na odkaz "přidat novou vlastnost" nahoře. + Vytvořit odpovídající šablonu + Přidat ikonu - Sort order - Creation date + Řazení + Datum vytvoření Třídění bylo ukončeno. Abyste nastavili, jak mají být položky seřazeny, přetáhněte jednotlivé z nich nahoru či dolů. Anebo klikněte na hlavičku sloupce pro setřídění celé kolekce + Tato položka nemá vnořené položky k seřazení - Publikování bylo zrušeno doplňkem třetí strany + Validace + Před uložením položky je nutné opravit chyby + Chyba + Uloženo + Nedostatečná uživatelská oprávnění, operace nemohla být dokončena + Zrušeno + Operace byla zrušena doplňkem třetí strany Typ vlastnosti už existuje Typ vlastnosti vytvořen Datový typ: %1%]]> @@ -749,108 +1363,332 @@ Stylopis byl uložen bez chyb Datový typ byl uložen Položka slovníku byla uložena - Publikování se nezdařilo, protože nadřazená stránka není publikována Obsah byl publikován a je viditelný na webu + %0% dokumentů zveřejněných a viditelných na webu + %0% zveřejněných a viditelných na webu + %0% dokumentů zveřejněných pro jazyky %1% a viditelných na webu Obsah byl uložen Nezapomeňte na publikování, aby se změny projevily + Načasování publikování bylo aktualizováno + %0% uloženo Odeslat ke schválení Změny byly odeslány ke schválení - Medium bylo uloženo - Medium bylo uloženo bez chyb + %0% změn bylo odesláno ke schválení + Médium bylo uloženo + Médium bylo uloženo bez chyb Člen byl uložen + Skupina členů byla uložena Vlastnost stylopisu byla uložena Stylopis byl uložen Šablona byla uložena Chyba při ukládání uživatele (zkontrolujte log) Uživatel byl uložen Typ uživatele byl uložen + Skupina uživatelů byla uložena + Jazyky a názvy hostitelů byly uloženy + Při ukládání jazyků a názvů hostitelů došlo k chybě Soubor nebyl uložen soubor nemohl být uložen. Zkontrolujte, prosím, oprávnění k souboru Soubor byl uložen Soubor byl uložen bez chyb Jazyk byl uložen + Typ média byl uložen + Typ člena byl uložen + Skupina členů byla uložena Šablona nebyla uložena Ujistěte se, prosím, že nemáte 2 šablony se stejným aliasem Šablona byla uložena Šablona byla uložena bez chyb! Publikování obsahu bylo zrušeno + Varianta obsahu %0% nebyla publikována + Povinný jazyk '%0%' nebyl publikován. Všechny jazyky pro tuto položku obsahu nejsou nyní publikovány. Částečný pohled byl uložen Částečný pohled byl uložen bez chyb! Částečný pohled nebyl uložen Při ukládání souboru došlo k chybě. + Oprávnění byla uložena pro + Smazáno %0% skupin uživatelů + %0% bylo smazáno + Povoleno %0% uživatelů + Zakázáno %0% uživatelů + %0% je nyní povoleno + %0% je nyní zakázáno + Skupiny uživatelů byly nastaveny + Odemčeno %0% uživatelů + %0% je nyný odemčeno + Člen byl exportován do souboru + Při exportu člena došlo k chybě + Uživatel %0% byl smazán + Pozvat uživatele + Pozvánka byla znovu odeslána na %0% + Dokument nelze publikovat, protože %0% není publikována + Ověření pro jazyk '%0%' se nezdařilo + Typ dokumentu byl exportován do souboru + Při exportu typu dokumentu došlo k chybě + Datum vydání nemůže být v minulosti + Nelze naplánovat publikování dokumentu, protože %0% není publikována + Dokument nelze naplánovat na publikování, protože „%0%“ má datum zveřejnění později než nepovinný jazyk + Datum vypršení platnosti nemůže být v minulosti + Datum vypršení nemůže být před datem vydání + + Publikování bylo zrušeno doplňkem třetí strany + Publikování se nezdařilo, protože nadřazená stránka není publikována - Používá CSS syntaxi např.: h1, .redHeader, .blueTex + Přidat styl + Upravit styl + Styly Rich Text editoru + Definujte styly, které by měly být k dispozici v editoru formátovaného textu pro tuto šablonu stylů Editovat stylopis Editovat vlastnost stylopisu Název, který identifikuje vlastnost stylu v editoru formátovaného textu Náhled + Jak bude text vypadat v Rich Text editoru. + CSS identifikátor nebo třída + Používá syntaxi CSS, např. "h1" nebo ".redHeader" Styly + CSS, který by měl být použit v editoru RTF, např. "color:red;" + Kód + Rich Text editor + + Používá CSS syntaxi např.: h1, .redHeader, .blueTex + Nepodařilo se odstranit šablonu s ID %0% Editovat šablonu + Sekce Vložit obsahovou oblast Vložit zástupce obsahové oblasti + Vložit + Vyberte, co chcete vložit do své šablony Vložit položku slovníku + Položka slovníku je zástupný symbol pro překladatelný text, což usnadňuje vytváření návrhů pro vícejazyčné webové stránky. Vložit makro + + Makro je konfigurovatelná součást, která je skvělá pro opakovaně použitelné části návrhu, kde potřebujete předat parametry, jako jsou galerie, formuláře a seznamy. + Vložit pole stránky umbraco + Zobrazuje hodnotu pojmenovaného pole z aktuální stránky s možnostmi upravit hodnotu nebo alternativní hodnoty. + Částečná šablona + + Částečná šablona je samostatný soubor šablony, který lze vykreslit uvnitř jiné šablony. Je to skvělé pro opakované použití nebo pro oddělení složitých šablon. + Nadřazená šablona - Rychlá příručka k šablonovým značkám umbraca + Žádný master + Vykreslit podřízenou šablonu + @RenderBody(). + ]]> + Definujte pojmenovanou sekci + @section {...}. Ta může být vykreslena v konkrétní oblasti nadřazené šablony pomocí @RenderSection. + ]]> + Vykreslit pojmenovanou sekci + @RenderSection(name). Tím se vykreslí oblast podřízené šablony, která je zabalena do odpovídající definice @section[name] {...}. + ]]> + Název sekce + Sekce je povinná + @section, jinak se zobrazí chyba. + ]]> + Tvůrce dotazů + položky vráceny, do + zkopírovat do schránky + Chci + veškerý obsah + obsah typu "%0%" + z(e) + můj web + kde + a + je + není + před + před (včetně zvoleného datumu) + po + po (včetně zvoleného datumu) + rovná se + nerovná se + obsahuje + neobsahuje + větší než + větší nebo rovno + menší než + menší nebo rovno + Id + Název + Datum vytvoření + Datum poslední aktualizace + řadit podle + vzestupně + sestupně Šablona + + Rychlá příručka k šablonovým značkám umbraca - Image - Macro - Choose type of content - Choose a layout - Add a row - Add content - Drop content - Settings applied - This content is not allowed here - This content is allowed here - Click to embed - Click to insert image - Image caption... - Write here... - Grid Layouts - Layouts are the overall work area for the grid editor, usually you only need one or two different layouts - Add Grid Layout - Adjust the layout by setting column widths and adding additional sections - Row configurations - Rows are predefined cells arranged horizontally - Add row configuration - Adjust the row by setting cell widths and adding additional cells - Columns - Total combined number of columns in the grid layout - Settings - Configure what settings editors can change - Styles - Configure what styling editors can change - Allow all editors - Allow all row configurations + Obrázek + Makro + Vybrat typ obsahu + Vybrat rozvržení + Přidat řádek + Přidat obsah + Zahodit obsah + Nastavení aplikováno + Tento obsah zde není povolen + Tento obsah je zde povolen + Klepněte pro vložení + Klepnutím vložíte obrázek + Titulek obrázku... + Zde pište... + Rozvržení mřížky + Rozvržení je celková pracovní oblast pro editor mřížky, obvykle potřebujete pouze jedno nebo dvě různá rozvržení + Přidat rozvržení mřížky + Upravte rozvržení nastavením šířky sloupců a přidáním dalších sekcí + Konfigurace řádků + Řádky jsou předdefinované buňky uspořádané vodorovně + Přidat konfiguraci řádku + Upravte řádek nastavením šířky buněk a přidáním dalších buněk + Sloupce + Celkový počet sloupců v rozvržení mřížky + Nastavení + Nakonfigurujte, jaká nastavení mohou editoři změnit + Styly + Nakonfigurujte, co mohou editoři stylů změnit + Povolit všechny editory + Povolit všechny konfigurace řádků + Maximální počet položek + Nechte prázdné nebo nastavte na 0 pro neomezené + Nastavit jako výchozí + Vyberat navíc + Zvolit výchozí + jsou přidány + Varování + Odstraňujete konfiguraci řádku + + Odstranění názvu konfigurace řádku povede ke ztrátě dat pro veškerý existující obsah založený na této konfiguraci. + + + + Složení + Skupina + Nepřidali jste žádné skupiny + Přidat skupinu + Zděděno od + Přidat vlastnost + Požadovaný popisek + Povolit zobrazení seznamu + Nakonfiguruje položku obsahu tak, aby zobrazovala seznam svých potomků a seznam potomků, které je možné prohledávat, potomci se nebudou zobrazovat ve stromu + Povolené šablony + Vyberte, kteří editoři šablon mohou používat obsah tohoto typu + Povolit jako root + Povolit editorům vytvářet obsah tohoto typu v kořenovém adresáři stromu obsahu. + Povolené typy podřízených uzlů + Povolit vytváření obsahu zadaných typů pod obsahem tohoto typu. + Vybrat podřízený uzel + Zdědí záložky a vlastnosti z existujícího typu dokumentu. Nové záložky budou přidány do aktuálního typu dokumentu nebo sloučeny, pokud existuje záložka se stejným názvem. + Tento typ obsahu se používá ve složení, a proto jej nelze poskládat. + Nejsou k dispozici žádné typy obsahu, které lze použít jako složení. + Odebráním složení odstraníte všechna související data vlastností. Jakmile uložíte typ dokumentu, již není cesta zpět. + Vytvořit nové + Použít existující + Nastavení editoru + Konfigurace + Ano, smazat + bylo přesunuto pod + bylo zkopírováno pod + Vybrat složku, kterou chcete přesunout + Vybrat složku, kterou chcete kopírovat + ve stromové struktuře níže + Všechny typy dokumentů + Všechny dokumenty + Všechny média + použití tohoto typu dokumentu bude trvale smazáno, prosím potvrďte, že je chcete také odstranit. + použití tohoto typu média bude trvale smazáno, potvrďte, že je chcete také odstranit. + použití tohoto typu člena bude trvale smazáno, potvrďte, že je chcete také odstranit + a všechny dokumenty používající tento typ + a všechny mediální položky používající tento typ + a všichni členové používající tento typ + Člen může upravovat + Povolit editaci této vlastnosti členem na jeho stránce profilu + Obsahuje citlivá data + Skrýt tuto hodnotu vlastnosti před editory obsahu, kteří nemají přístup k prohlížení citlivých informací + Zobrazit v profilu člena + Povolit zobrazení této vlastnosti na stránce profilu člena + záložka nemá žádné řazení + Kde se toto složení používá? + Toto složení se v současnosti používá ve složení následujících typů obsahu: + Povolit různé jazyky + Povolit editorům vytvářet obsah tohoto typu v různých jazycích. + Povolit různé jazyky + Typ prvku + Je typ prvku + Typ prvku je určen k použití například ve vnořeném obsahu, nikoli ve stromu. + Jakmile byl typ dokumentu použit k vytvoření jedné nebo více položek obsahu, nelze jej změnit na typ prvku. + To neplatí pro typ prvku + V této vlastnosti jste provedli změny. Opravdu je chcete zahodit? + + + Přidat jazyk + Povinný jazyk + Před publikováním uzlu je nutné vyplnit vlastnosti v tomto jazyce. + Výchozí jazyk + Web Umbraco může mít nastaven pouze jeden výchozí jazyk. + Přepnutí výchozího jazyka může mít za následek chybějící výchozí obsah. + Nahradit nepřeložený obsah za + Žádné nahrazení nepřeloženého jazyka + Chcete-li povolit automatické zobrazení vícejazyčného obsahu v jiném jazyce, pokud není v požadovaném jazyce přeložen, vyberte jej zde. + Nahrazujicí jazyk + žádný + + + Přidat parametr + Upravit parametr + Zadejte název makra + Parametry + Definujte parametry, které by měly být k dispozici při použití tohoto makra. + Vyberte soubor makra pro částečnou šablonu + + + Stavební modely + to může chvíli trvat, nebojte se + Generované modely + Modely nelze vygenerovat + Generování modelů selhalo, viz výjimka v logu Umbraca + Přidat záložní pole + Náhradní pole + Přidat výchozí hodnotu + Výchozí hodnota Alternativní pole Alternativní text Velká a malá písmena Kódování Vybrat pole - Konvertovat + Konvertovat + Ano, převést konce řádků Nahrazuje nové řádky html tagem &lt;br&gt; Vlastní pole Ano, pouze datum + Formát a kódování Formátovat jako datum + Naformátuje hodnotu jako datum nebo datum s časem podle aktivního jazyka HTML kódování Nahradí speciální znaky jejich HTML ekvivalentem. Bude vloženo za hodnotou pole Bude vloženo před hodnotou pole Malá písmena + Upravit výstup Nic + Ukázka výstupu Vložit za polem Vložit před polem Rekurzivní + Ano, udělej to rekurzivní + Oddělovač Standardní pole Velká písmena Kódování URL @@ -861,7 +1699,7 @@ Podrobnosti překladu - Stáhnout xml DTD + Stáhnout XML DTD Pole Zahrnout podstránky Žádní uživatelé překladatelé nebyli nalezeni. Vytvořte, prosím, překladatele před tím, než začnete posílat obsah k překladu Stránka '%0%' byla poslána k překladu @@ -892,6 +1730,9 @@ Nahrát xml překladu + Obsah + Šablony obsahu + Média Prohlížeč mezipaměti Koš Vytvořené balíčky @@ -909,8 +1750,11 @@ Role Typy členů Typy dokumentů + Typy vztahů/vazeb Balíčky Balíčky + Částečné šablony + Makra částečných šablon Instalovat z úložiště Instalovat Runway Moduly Runway @@ -918,9 +1762,14 @@ Skripty Stylopisy Šablony - Oprávnění Uživatele - Typy Uživatelů + Prohlížeč logu Uživatelé + Nastavení + Šablony + Třetí strana + + Oprávnění uživatele + Typy uživatelů Nová aktualizace je připrvena @@ -929,23 +1778,46 @@ Chyba při kontrole aktualizace. Zkontrolujte, prosím, trasovací zásobník pro další informace + Přístupy + Na základě přiřazených skupin a počátečních uzlů má uživatel přístup k následujícím uzlům + Přiřadit přístup Administrátor Pole kategorie + Uživatel byl vytvořen Změnit heslo + Změnit fotku Změnit heslo + nebyl uzamčen + Heslo nebylo změněno Potvrdit heslo Můžete změnit své heslo pro přístup do administrace Umbraca vyplněním formuláře níže a kliknutím na tlačítko 'Změnit Heslo' Kanál obsahu + Vytvořit dalšího uživatele + Vytvořte nové uživatele a udělte mu přístup do Umbraco. Po vytvoření nového uživatele bude vygenerováno heslo, které s ním můžete sdílet. Popis Deaktivovat uživatele Typ dokumentu Editor Výtah + Neúspěšné pokusy o přihlášení + Přejít na uživatelský profil + Přidáním skupin přidělte přístup a oprávnění + Pozvat dalšího uživatele + Pozvěte nové uživatele, a poskytněte jim přístup do Umbraco. Uživatelům bude zaslán e-mail s pozvánkou a s informacemi o tom, jak se přihlásit do Umbraco. Pozvánky mají platnost 72 hodin. Jazyk + Nastavte jazyk, který uvidíte v nabídkách a dialogových oknech + Poslední datum uzamčení + Poslední přihlášení + Heslo bylo naposledy změněno Přihlašovací jméno Úvodní uzel v knihovně medií + Omezte knihovnu médií na konkrétní počáteční uzel + Úvodní uzly v knihovně medií + Omezte knihovnu médií na konkrétní počáteční uzly Sekce Deaktivovat přistup k Umbracu + se dosud nepřihlásil + Staré heslo Heslo Resetovat heslo Vyše heslo bylo změněno! @@ -959,13 +1831,526 @@ Nahradit oprávnění podřízených uzlů Nyní měníte oprávnění pro stránky: Vyberte stránky, pro které chcete měnit oprávnění + Odebrat fotografii + Výchozí oprávnění + Upřesnění oprávnění + Nastavte oprávnění pro konkrétní uzly + Profil Prohledat všechny podřízené uzly + Přidejte sekce, do kterých mají uživatelé přístup + Vybrat skupiny uživatelů + Nebyl vybrán žádný počáteční uzel + Nebyly vybrány žádné počáteční uzly Úvodní uzel v obsahu + Omezte strom obsahu na konkrétní počáteční uzel + Úvodní uzly obsahu + Omezte strom obsahu na konkrétní počáteční uzly + Uživatel byl naposledy aktualizován + byl vytvořen + Nový uživatel byl úspěšně vytvořen. Pro přihlášení do Umbraco použijte heslo níže. + Správa uživatelů Uživatelské jméno Oprávnění uživatele + Uživatelská skupina + byl pozván + Novému uživateli byla zaslána pozvánka s informacemi, jak se přihlásit do Umbraco. + Dobrý den, vítejte v Umbraco! Za pouhou 1 minutu budete moci používat Umbraco. Jenom od vás potřebujeme, abyste si nastavili heslo a přidali obrázek pro svůj avatar. + Vítejte v Umbraco! Vaše pozvánka bohužel vypršela. Obraťte se na svého správce a požádejte jej, aby jí znovu odeslal. + Nahrání vaší fotografie usnadní ostatním uživatelům, aby vás poznali. Kliknutím na kruh výše nahrajte svou fotku. Spisovatel + Změnit Váš profil Vaše nedávná historie Relace vyprší za + Pozvat uživatele + Vytvořit uživatele + Odeslat pozvánku + Zpět na seznam uživatelů + Umbraco: Pozvánka + + + + + + + + + + + +
        + + + + + +
        + +
        + +
        +
        + + + + + + +
        +
        +
        + + + + +
        + + + + +
        +

        + Zdravím Vás, %0%, +

        +

        + Byli jste pozváni %1% do CMS Umbraco. +

        +

        + Zpráva od %1%: +
        + %2% +

        + + + + + + +
        + + + + + + +
        + + Kliknutím na tento odkaz přijměte pozvání + +
        +
        +

        Pokud nemůžete kliknout na odkaz, zkopírujte a vložte tuto adresu URL do okna prohlížeče:

        + + + + +
        + + %3% + +
        +

        +
        +
        +


        +
        +
        + + ]]>
        + Pozvat + Zasílám pozvání... + Smazat uživatele + Opravdu chcete smazat tento uživatelský účet? + Vše + Aktivní + Zakázané + Uzamčeno + Pozváno + Neaktivní + Jméno (A-Z) + Jméno (Z-A) + Nejnovější + Nejstarší + Poslední přihlášení + Nebyly přidány žádné skupiny uživatelů + + + Validace + Ověřit jako e-mailovou adresu + Ověřit jako číslo + Ověřit jako URL + ...nebo zadat vlastní ověření + Pole je povinné + Zadat chybovou zprávu pro vlastní validaci (volitelné) + Zadat regulární výraz + Zadat chybovou zprávu pro vlastní validaci (volitelné) + Musíte přidat alespoň + Můžete jen mít + položky + vybrané položky + Neplatné datum + Není číslo + Neplatný e-mail + Hodnota nemůže být nulová + Hodnota nemůže být prázdná + Hodnota je neplatná, neodpovídá správnému vzoru + Vlastní ověření + %1% více.]]> + %1% příliš mnoho.]]> + + + + Hodnota je nastavena na doporučenou hodnotu: '%0%'. + Hodnota byla nastavena na '%1%' pro XPath '%2%' v konfiguračním souboru '%3%'. + Očekávaná hodnota '%1%' pro '%2%' v konfiguračním souboru '%3%', ale nalezeno '%0%'. + Nalezena neočekávaná hodnota '%0%' pro '%2%' v konfiguračním souboru '%3%'. + + Vlastní chyby jsou nastaveny na '%0%'. + Vlastní chyby jsou aktuálně nastaveny na '%0%'. Před nasazením se doporučuje nastavit na '%1%'. + Vlastní chyby byly úspěšně nastaveny na '%0%'. + MacroErrors jsou nastaveny na '%0%'. + MakroErrors jsou nastaveny na '%0%', což zabrání úplnému načtení některých nebo všech stránek na vašem webu, pokud dojde k chybám v makrech. Náprava nastaví hodnotu na '%1%'. + MakroErrors jsou nyní nastaveny na '%0%'. + + Try Skip IIS Custom Errors je nastaveno na '%0%' a používáte verzi IIS '%1%'. + Try Skip IIS Custom Errors je aktuálně nastaveno na '%0%'. Doporučuje se nastavit %1% pro vaši verzi služby IIS (%2%). + Try Skip IIS Custom Errors úspěšně nastaveno na '%0%'. + + Soubor neexistuje: '%0%'. + '% 0%' v konfiguračním souboru '% 1%'.]]> + Došlo k chybě, zkontrolujte ji v logu: %0%. + Databáze - Databázové schéma je pro tuto verzi Umbraco správné + Bylo zjištěno %0% problémů se schématem vaší databáze (podrobnosti najdete v logu) + Při ověřování databázového schématu vůči aktuální verzi Umbraco byly zjištěny některé chyby. + Certifikát vašeho webu je platný. + Chyba ověření certifikátu: '%0%' + Platnost SSL certifikátu vašeho webu vypršela. + Platnost certifikátu SSL vašeho webu vyprší za %0% dní. + Chyba při pingování adresy URL %0% - '%1%' + Aktuálně prohlížíte web pomocí schématu HTTPS. + AppSetting 'Umbraco.Core.UseHttps' je v souboru web.config nastaven na 'false'. Jakmile vstoupíte na tento web pomocí schématu HTTPS, mělo by být nastaveno na 'true'. + AppSetting 'Umbraco.Core.UseHttps' je v souboru web.config nastaven na '%0%', vaše cookies %1% jsou označeny jako zabezpečené. + V souboru web.config se nepodařilo aktualizovat nastavení 'Umbraco.Core.UseHttps'. Chyba: %0% + + Povolit HTTPS + Nastaví nastavení umbracoSSL na true v appSettings v souboru web.config. + AppSetting 'Umbraco.Core.UseHttps' je nyní nastaveno na 'true' v souboru web.config, vaše cookies budou označeny jako zabezpečené. + Fix + Nelze opravit kontrolu pro porovnání hodnot pomocí 'ShouldNotEqual'. + Nelze opravit kontrolu pro porovnání hodnot pomocí 'ShouldEqual' s poskytnutou hodnotou. + Hodnota k opravě nebyla poskytnuta. + Režim kompilace ladění je zakázán. + Režim ladění je aktuálně povolen. Před spuštěním webu se doporučuje toto nastavení deaktivovat. + Režim ladění byl úspěšně deaktivován. + Režim sledování je deaktivován. + Režim sledování je aktuálně povolen. Před spuštěním se doporučuje toto nastavení deaktivovat. + Režim sledování byl úspěšně deaktivován. + Všechny složky mají nastavena správná oprávnění. + + %0%.]]> + %0%. Pokud nejsou psány, není třeba podniknout žádné kroky.]]> + Všechny soubory mají nastavena správná oprávnění. + + %0%.]]> + %0%. Pokud nejsou psány, není třeba podniknout žádné kroky.]]> + X-Frame-Options, které určuje, zda může být obsah webu zobrazen na jiném webu pomocí IFRAME.]]> + X-Frame-Options, které určuje, zda může být obsah webu zobrazen na jiném webu pomocí IFRAME.]]> + Nastavit záhlaví v Konfiguraci + Přidá hodnotu do sekce httpProtocol/customHeaders do web.config, aby se zabránilo tomu, že web může být zobrazen na jiném webu pomocí IFRAME. + Do souboru web.config bylo přidáno nastavení pro vytvoření záhlaví, které zabrání jinému webu, zobrazit tento web pomocí IFRAME. + Nelze aktualizovat soubor web.config. Chyba: %0% + X-Content-Type-Options použitá k ochraně před zranitelnostmi čichání MIME.]]> + X-Content-Type-Options použité k ochraně před zranitelnostmi čichání MIME nebyly nalezeny.]]> + Přidá hodnotu do sekce httpProtocol/customHeaders v souboru web.config, která chrání před zranitelnostmi MIME. + Do souboru web.config bylo přidáno nastavení pro vytvoření záhlaví, které chrání před zranitelnostmi MIME. + Strict-Transport-Security, také známo jako HSTS-header, bylo nalezeno.]]> + Strict-Transport-Security nebylo nalezeno.]]> + Do sekce httpProtocol/customHeaders v souboru web.config přidá záhlaví 'Strict-Transport-Security' s hodnotou 'max-age = 10886400'. Tuto opravu použijte pouze v případě, že vaše domény budou spuštěny s https po dobu příštích 18 týdnů (minimálně). + Do vašeho souboru web.config bylo přidáno záhlaví HSTS. + X-XSS-Protection bylo nalezeno.]]> + X-XSS-Protection bylo nalezeno.]]> + Přidá záhlaví 'X-XSS-Protection' s hodnotou '1; mode=block' do sekce httpProtocol/customHeaders v souboru web.config. + Záhlaví X-XSS-Protection bylo přidáno do vašeho souboru web.config. + + %0%.]]> + Nebyly nalezeny žádné hlavičky odhalující informace o technologii webových stránek. + V souboru Web.config nelze najít system.net/mailsettings. + V části system.net/mailsettings v souboru web.config není hostitel nakonfigurován. + Nastavení SMTP jsou správně nakonfigurována a služba funguje jak má. + Server SMTP konfigurovaný s hostitelem '%0%' a portem '%1%' nelze nalézt. Zkontrolujte prosím, zda jsou nastavení SMTP v souboru Web.config a v sekci system.net/mailsettings správná. + %0%.]]> + %0%.]]> +

        Výsledky plánovaných kontrol Umbraco Health Checks provedených na %0% v %1% jsou následující:

        %2%]]>
        + Stav Umbraco Health Check: %0% + Zkontrolovat všechny skupiny + Zkontrolovat skupinu + + Kontrola vyhodnocuje různé oblasti vašeho webu z hlediska nastavení osvědčených postupů, konfigurace, potenciálních problémů atd. Problémy lze snadno vyřešit stisknutím tlačítka. Můžete přidat své vlastní kontroly, podívejte se na dokumentaci pro více informací o vlastních kontrolách.

        + ]]> +
        + + + Zakázat sledování URL + Povolit sledování URL + Jazyk + Originální URL + Přesměrováno na + Správa URL přesměrování + Na tuto položku obsahu přesměrovávají následující adresy URL: + Nebyla provedena žádná přesměrování + Jakmile bude publikovaná stránka přejmenována nebo přesunuta, bude automaticky provedeno přesměrování na novou stránku. + Opravdu chcete odstranit přesměrování z '%0%' na '%1%'? + Přesměrování bylo odstraněno. + Chyba při odebírání URL přesměrování. + Toto odstraní přesměrování + Opravdu chcete zakázat sledování URL adres? + Sledování URL adres je nyní zakázáno. + Při deaktivaci sledování URL adres došlo k chybě, další informace naleznete v logu. + Sledování URL adres je nyní povoleno. + Chyba při povolení sledování URL adres, další informace lze nalézt v logu. + + + Žádné položky ze slovníku na výběr + + + %0% znaků.]]> + %1% je moc.]]> + + + Obsah s ID: {0} v koši souvisí s původním nadřazeným obsahem s ID: {1} + Média s ID: {0} v koši souvisí s původním nadřazeným médiem s ID: {1} + Tuto položku nelze automaticky obnovit + Neexistuje žádné místo, kde lze tuto položku automaticky obnovit. Položku můžete přesunout ručně pomocí stromu níže. + byla obnovena pod + + + Směr + Nadřazený s potomkem + Obousměrný + Nadřazená + Potomek + Počet + Vazby + Vytvořeno + Komentář + Název + Žádné vazby pro tento typ vazby. + Typ vazby + Vazby + + + Začínáme + Správa přesměrování + Obsah + Vítejte + Správa Examine + Stav publikování + Tvůrce modelů + Health Check + Profilování + Začínáme + Instalovat Umbraco formuláře + + + Jít zpět + Aktivní rozvržení: + Skočit do + skupina + prošlo + varování + selhalo + návrh + Kontrola prošla + Kontrola selhala + Otevřít hledání v backoffice + Otevřít/zavřít nápovědu backoffice + Otevřít/zavřít možnosti vašeho profilu + Otevřít kontextové menu pro + Aktuální jazyk + Přepnout jazyk na + Vytvořit novou složku + Částečná šablona + Makro částečné šablony + Člen + Datový typ + Prohledat přesměrování + Prohledat skupiny uživatelů + Prohledat uživatele + Vytvořit položku + Vytvořit + Upravit + Název + + + Závislosti + Tento datový typ nemá žádné závislosti. + Použito v dokumentových typech + Žádné vazby na typy dokumentů. + Použito v typech médií + Žádné vazby na typy médií. + Použito v typech členů + Žádné vazby na typy členů. + Použito v + Použito v dokumentech + Použito ve členech + Použito v médiích + + + Úrovně logování + Uložená vyhledávání + Celkem položek + Časové razítko + Úroveň + Stroj + Zpráva + Výjimka + Vlastnosti + Vyhledat na Googlu + Vyhledat zprávu na Googlu + Vyhledat na Bing + Vyhledat zprávu na Bing + Prohledat naše Umbraco + Vyhledat tuto zprávu na našich fórech a dokumentech Umbraco + Vyhledat Our Umbraco na Googlu + Prohledat Our Umbraco fóra pomocí Googlu + Prohledat Umbraco Source + Vyhledat ve zdrojovém kódu Umbraco na Github + Prohledat Umbraco Issues + Prohledat Umbraco Issues na Github + Smazat toto vyhledávání + Najít logy s ID požadavku + Najít logy se jmenným prostorem + Najít logy s názvem stroje + Otevřít + + + Kopírovat %0% + %0% z %1% + Odebrat všechny položky + + + Otevřít akce vlastností + + + Čekejte + Stav obnovení + Cache paměť + + + + Znovu načíst + Cache databáze + + Znovuvytvoření může být náročné. Použijte jej, když nestačí obnovení stránky, a domníváte se, že mezipaměť databáze nebyla správně vygenerována - což by naznačovalo možný kritický problém Umbraco. + ]]> + + Obnovit + Internals + + nebudete muset používat. + ]]> + + Sběr + Stav publikované mezipaměti + Mezipaměti + + + Profilování výkonu + + Umbraco aktuálně běží v režimu ladění. To znamená, že můžete použít vestavěný profiler výkonu k vyhodnocení výkonu při vykreslování stránek.

        Pokud chcete aktivovat profiler pro konkrétní vykreslení stránky, jednoduše při požadavku na stránku jednoduše přidejte umbDebug=true do URL.

        Pokud chcete, aby byl profiler ve výchozím nastavení aktivován pro všechna vykreslení stránky, můžete použít přepínač níže. Ve vašem prohlížeči nastaví soubor cookie, který automaticky aktivuje profiler. Jinými slovy, profiler bude ve výchozím nastavení aktivní pouze ve vašem prohlížeči, ne v ostatních.

        + ]]> +
        + Ve výchozím stavu aktivovat profiler + Přátelské připomenutí + + + Nikdy byste neměli nechat produkční web běžet v režimu ladění. Režim ladění je vypnut nastavením debug="false" na elementu compilation v souboru web.config. +

        + ]]> +
        + + + Umbraco v současné době neběží v režimu ladění, takže nemůžete použít vestavěný profiler. Takto by to mělo být pro produkční web. +

        +

        + Režim ladění je zapnut nastavením debug="true" na elementu compilation v souboru web.config. +

        + ]]> +
        + + + Hodiny tréninkových videí Umbraco jsou blíž než si myslíte + + Chcete ovládnout Umbraco? Stačí strávit pár minut sledování jednoho z těchto videí o používání Umbraco. Nebo navštivte umbraco.tv , kde najdete ještě více videí o Umbraco

        + ]]> +
        + Chcete-li začít + + + Začněte zde + Tato část obsahuje stavební bloky pro váš web Umbraco. Podle níže uvedených odkazů se dozvíte více o práci s položkami v části Nastavení + Zjistit více + + v sekci Dokumentace v Our Umbraco + ]]> + + + fóru komunity + ]]> + + + výuková videa (některá jsou zdarma, jiná vyžadují předplatné) + ]]> + + + nástrojích zvyšujících produktivitu a komerční podpoře + ]]> + + + školení a certifikace + ]]> + + + + Vítejte v přátelském CMS + Děkujeme, že jste si vybrali Umbraco - myslíme si, že by to mohl být začátek něčeho krásného. I když se to může zpočátku zdát ohromující, udělali jsme hodně pro to, aby byla křivka učení co nejhladší a nejrychlejší. + + + Umbraco formuláře + Vytvářejte formuláře pomocí intuitivního rozhraní drag and drop. Od jednoduchých kontaktních formulářů, které odesílají e-maily, až po pokročilé dotazníky, které se integrují do systémů CRM. Vaši klienti to budou milovat!
        diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml index fef9c1cf82..6242d72146 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml @@ -472,6 +472,7 @@ Vælg medlemstype Vælg node Vælg sektioner + Vælg bruger Vælg brugere Ingen ikoner blev fundet Der er ingen parametre for denne makro @@ -1784,8 +1785,10 @@ Mange hilsner fra Umbraco robotten Brugt af + Slet gemte søgning Log type - Gemte søgninger + Gem søgning + Indtast et navn for din søgebetingelse Samlet resultat Dato Type diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/de.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/de.xml index 529074f24d..86b1d6c130 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/de.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/de.xml @@ -4,10 +4,6 @@ The Umbraco community https://our.umbraco.com/documentation/Extending-Umbraco/Language-Files - - - - Kulturen und Hostnamen Protokoll diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml index d72179fc75..481d20f777 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml @@ -499,6 +499,7 @@ Select member type Select node Select sections + Select user Select users No icons were found There are no parameters for this macro @@ -2047,7 +2048,10 @@ To manage your website, simply open the Umbraco back office and start adding con Enter a custom validation error message (optional) You need to add at least You can only have + Add up to items + url(s) + url(s) selected items selected Invalid date Not a number @@ -2265,6 +2269,9 @@ To manage your website, simply open the Umbraco back office and start adding con Name Add new row View more options + Has translation + Missing translation + Dictionary items References @@ -2281,32 +2288,36 @@ To manage your website, simply open the Umbraco back office and start adding con Used in Media - Log Levels - Saved Searches - Total Items - Timestamp - Level - Machine - Message - Exception - Properties - Search With Google - Search this message with Google - Search With Bing - Search this message with Bing - Search Our Umbraco - Search this message on Our Umbraco forums and docs - Search Our Umbraco with Google - Search Our Umbraco forums using Google - Search Umbraco Source - Search within Umbraco source code on Github - Search Umbraco Issues - Search Umbraco Issues on Github - Delete this search - Find Logs with Request ID - Find Logs with Namespace - Find Logs with Machine Name - Open + Delete Saved Search + Log Levels + Saved Searches + Save Search + Enter a friendly name for your search query + Filter Search + Total Items + Timestamp + Level + Machine + Message + Exception + Properties + Search With Google + Search this message with Google + Search With Bing + Search this message with Bing + Search Our Umbraco + Search this message on Our Umbraco forums and docs + Search Our Umbraco with Google + Search Our Umbraco forums using Google + Search Umbraco Source + Search within Umbraco source code on Github + Search Umbraco Issues + Search Umbraco Issues on Github + Delete this search + Find Logs with Request ID + Find Logs with Namespace + Find Logs with Machine Name + Open Copy %0% @@ -2316,6 +2327,7 @@ To manage your website, simply open the Umbraco back office and start adding con Open Property Actions + Close Property Actions Wait diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml index 41efb12f51..9113e94e62 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml @@ -503,6 +503,7 @@ Select member type Select node Select sections + Select user Select users No icons were found There are no parameters for this macro @@ -673,6 +674,7 @@ Continue Copy Create + Crop section Database Date Default @@ -2063,7 +2065,10 @@ To manage your website, simply open the Umbraco back office and start adding con Enter a custom validation error message (optional) You need to add at least You can only have + Add up to items + url(s) + url(s) selected items selected Invalid date Not a number @@ -2285,6 +2290,9 @@ To manage your website, simply open the Umbraco back office and start adding con Name Add new row View more options + Has translation + Missing translation + Dictionary items References @@ -2301,8 +2309,12 @@ To manage your website, simply open the Umbraco back office and start adding con Used in Media + Delete Saved Search Log Levels Saved Searches + Save Search + Enter a friendly name for your search query + Filter Search Total Items Timestamp Level @@ -2336,6 +2348,7 @@ To manage your website, simply open the Umbraco back office and start adding con Open Property Actions + Close Property Actions Wait diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/fr.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/fr.xml index b5d1c8feb2..b83ee4f9fe 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/fr.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/fr.xml @@ -12,8 +12,8 @@ Copier Créer Exporter - Créer un groupe Créer un package + Créer un groupe Supprimer Désactiver Vider la corbeille @@ -30,17 +30,21 @@ Dépublier Rafraîchir Republier le site tout entier + Renommer Récupérer Spécifiez les permissions pour la page %0% + Choisissez où copier Choisissez où déplacer dans l'arborescence ci-dessous + a été déplacé vers + a été copié vers + a été supprimé Permissions Version antérieure Envoyer pour publication Envoyer pour traduction Spécifier le groupe Trier - Envoyer pour publication Traduire Mettre à jour Spécifier les permissions @@ -65,6 +69,7 @@ Permettre de déplacer un noeud Permettre de définir et modifier l'accès public à un noeud Permettre de publier un noeud + Permettre d'annuler la publication d'un noeud Permettre de modifier les permissions pour un noeud Permettre de revenir à une situation antérieure Permettre d'envoyer un noeud pour approbation avant publication @@ -74,6 +79,10 @@ Permettre de sauvegarder un noeud Permettre la création d'un Modèle de Contenu + + Contenu + Info + Permission refusée. Ajouter un nouveau domaine @@ -88,15 +97,15 @@ Domaine '%0%' déjà assigné Domaine '%0%' mis à jour Editer les domaines actuels + + Hériter Culture ou hériter de la culture des noeuds parents. S'appliquera aussi
        au noeud courant, à moins qu'un domaine ci-dessous soit aussi d'application.]]>
        Domaines - - Aperçu pour - Vider la sélection Choisir @@ -117,25 +126,66 @@ Liste numérique Insérer une macro Insérer une image + Publier et fermer + Publier avec les descendants Editer les relations Retourner à la liste Sauver + Sauver et fermer Sauver et publier Sauver et planifier Sauver et envoyer pour approbation Sauver la mise en page de la liste + Planifier Prévisualiser + Prévisualiser La prévisualisation est désactivée car aucun modèle n'a été assigné. Choisir un style Afficher les styles Insérer un tableau + Générer les modèles et fermer Sauver et générer les modèles Défaire Refaire + Restaurer + Supprimer un tag + Annuler + Confirmer + Options de publication supplémentaires + + + Aperçu pour + Contenu supprimé + Contenu dé-publié + Contenu dé-publié pour les langues : %0% + Contenu publié + Contenu publié pour les langues : %0% + Contenu sauvegardé + Contenu sauvegardé pour les langues : %0% + Contenu déplacé + Contenu copié + Contenu restauré + Contenu envoyé pour publication + Contenu envoyé pour publication pour les langues : %0% + Ordonnancement des sous-éléments réalisé par l'utilisateur + Copier + Publier + Publier + Déplacer + Sauvegarder + Sauvegarder + Supprimer + Annuler publication + Annuler publication + Restaurer + Envoyer pour publication + Envoyer pour publication + Ordonner + Historique (toutes variantes) Pour changer le type de document du contenu séléctionné, faites d'abord un choix dans la liste des types valides à cet endroit. - Puis modifiez si nécessaire la correspondance des propriétés du type actuel vers le nouveau, et cliquez sur Sauver. + Puis confirmez et/ou modifiez la correspondance des propriétés du type actuel vers le nouveau, et cliquez sur Sauver. Le contenu a été republié. Propriété actuelle Type actuel @@ -153,6 +203,12 @@ Impossible de terminer la correspondance des propriétés car une ou plusieurs propriétés ont plus d'une correspondance définie. Seuls les types de documents valides à cet endroit sont affichés. + + Echec de la création d'un dossier sous le parent avec l'ID %0% + Echec de la création d'un dossier sous le parent avec le nom %0% + Le nom du dossier ne peut pas contenir de caractères illégaux. + Echec de la suppression de l'élément : %0% + A été publié A propos de cette page @@ -184,15 +240,20 @@ Aucune date choisie Titre de la page Ce média n'a pas de lien + Aucun contenu ne peut être ajouté pour cet élément Propriétés Ce document est publié mais n'est pas visible car son parent '%0%' n'est pas publié - Oups : ce document est publié mais n'est pas présent dans le cache (erreur interne Umbraco) + Cette culture est publiée mais n'est pas visible car elle n'est pas publiée pour le parent '%0%' + Ce document est publié mais n'est pas présent dans le cache Oups: impossible d'obtenir cet url (erreur interne - voir fichier log) - Oups: ce document est publié mais son url entrerait en collision avec le contenu %0% + Ce document est publié mais son url entrerait en collision avec le contenu %0% + Ce document est publié mais son url ne peut pas être routé Publier Publié Publié (changements en cours) Statut de publication + Publier avec ses descendants pour publier %0% et tous les éléments de contenu en-dessous, rendant de ce fait leur contenu accessible publiquement.]]> + Publier avec ses descendants pour publier les langues sélectionnées et les mêmes langues des éléments de contenu en-dessous, rendant de ce fait leur contenu accessible publiquement.]]> Publié le Dépublié le Supprimer la date @@ -205,6 +266,7 @@ Type Dépublier Dépublié + Non créé Dernière édition Date/heure à laquelle ce document a été édité Supprimer le(s) fichier(s) @@ -215,13 +277,35 @@ Cible Ceci se traduit par l'heure suivante sur le serveur : Qu'est-ce que cela signifie?]]> - Etes-vous certain(e) de vouloir supprimer cet éléménent? + Etes-vous certain(e) de vouloir supprimer cet élément? + Etes-vous certain(e) de vouloir supprimer tous les éléments? La propriété %0% utilise l'éditeur %1% qui n'est pas supporté par Nested Content. + Aucun type de contenu n'est configuré pour cette propriété. + Ajouter un type d'élément + Sélectionner un type d'élément Ajouter un autre champ texte Enlever ce champ texte Racine du contenu + Inclure les brouillons : publier également les éléments de contenu non publiés. Cette valeur est masquée. Si vous avez besoin de pouvoir accéder à cette valeur, veuillez prendre contact avec l'administrateur du site web. Cette valeur est masquée. + Quelles langues souhaitez-vous publier? Toutes les langues ayant du contenu ont été sauvegardées! + Quelles langues souhaitez-vous publier? + Quelles langues souhaitez-vous sauvegarder? + Toutes les langues avec du contenu sont sauvegardées lors de la création! + Quells langues souhaitez-vous envoyer pour approbation? + Quelles langues souhaitez-vous planifier? + Sélectionnez les langues à dépublier. La dépublication d'une langue obligatoire provoquera la dépublication de toutes les langues. + Langues publiées + Langues non publiées + Langues non modifiées + Ces langues n'ont pas été créées + Prêt.e à publier? + Prêt.e à sauvegarder? + Envoyer pour approbation + Sélectionnez la date et l'heure de publication/dépublication de l'élément de contenu. + Créer nouveau + Copier du clipboard Créer un nouveau Modèle de Contenu à partir de '%0%' @@ -235,22 +319,38 @@ Cliquez pour télécharger ou cliquez ici pour choisir un fichier + Vous pouvez faire glisser des fichiers ici pour télécharger. Ce fichier ne peut pas ête chargé, il n'est pas d'un type de fichier autorisé. La taille maximum de fichier est Racine du média + Echec du déplacement du média + Les dossiers parent et destination ne peuvent pas être identiques + Echec de la copie du media + Echec de la création d'un dossier sous le parent avec l'id %0% + Echec du changement de nom du dossier avec l'id %0% + Glissez et déposez vos fichiers dans la zone Créer un nouveau membre Tous les membres + Les groupes de membres n'ont pas de propriétés supplémentaires modifiables. Où voulez-vous créer le nouveau %0% Créer un élément sous Sélectionnez le type de document pour lequel vous souhaitez créer un modèle de contenu + Introduisez un nom de dossier Choisissez un type et un titre - "Types de documents".]]> - "Types de médias".]]> - Type de document sans modèle + Types de documents sous la section Paramètres, en modifiant les Types de noeuds enfants autorisés sous les Permissions.]]> + Types de documents sous la section Paramètres.]]> + La page sélectionnée dans l'arborescence de contenu n'autorise pas la création de pages sous elle. + Modifier les permissions pour ce type de document + Créer un nouveau type de document + Types de documents sous la section Paramètres, en modifiant l'option Autoriser comme racine sous les Permissions.]]> + Types de médias dans la section Paramètres, en modifiant les Types de noeuds enfants autorisés sous les Permissions.]]> + Le media sélectionné dans l'arborescence n'autorise pas la création d'un autre media sous lui. + Modifier les permissions pour ce type de media + Type de document sans modèle Nouveau répertoire Nouveau type de données Nouveau fichier javascript @@ -259,6 +359,8 @@ Nouvelle vue partielle à partir d'un snippet Nouvelle macro pour vue partielle à partir d'un snippet Nouvelle macro pour vue partielle (sans macro) + Nouveau fichier de feuille de style + Nouveau fichier de feuille de style pour l'éditeur de texte Parcourir votre site @@ -274,7 +376,10 @@ Invalider les changements Vous avez des changements en cours Etes-vous certain(e) de vouloir quitter cette page? - vous avez des changements en cours - La dépublication va supprimer du site cette page ainsi que tous ses descendants. + La publication rendra les éléments sélectionnés visibles sur le site. + La suppression de la publication supprimera du site les éléments sélectionnés et tous leurs descendants. + La suppression de la publication supprimera du site cette page ainsi que tous ses descendants. + Vous avez des modifications en cours. Modifier le Type de Document fera disparaître ces modifications. Terminé @@ -302,8 +407,8 @@ Titre du lien Lien + Ancrage / requête Nom - Gérer les noms d'hôtes Fermer cette fenêtre Êtes-vous certain(e) de vouloir supprimer Êtes-vous certain(e) de vouloir désactiver @@ -312,6 +417,7 @@ Couper Editer une entrée du Dictionnaire Modifier la langue + Modifier le media sélectionné Insérer un lien local (ancre) Insérer un caractère Insérer un entête graphique @@ -319,18 +425,21 @@ Insérer un lien Insérer une macro Insérer un tableau + Ceci supprimera la langue + Modifier la culture d'une langue peut être une opération lourde qui aura pour conséquence la réinitialisation de la cache de contenu et des index Dernière modification Lien Lien interne : Si vous utilisez des ancres, insérez # au début du lien Ouvrir dans une nouvelle fenêtre? + Paramètres de la macro Cette macro ne contient aucune propriété éditable Coller Editer les permissions pour Définir les permissions pour Définir les permissions pour %0% pour le groupe d'utilisateurs %1% Sélectionnez les groupes d'utilisateurs pour lesquels vous souhaitez définir les permissions - Les éléments dans la corbeille sont en cours de suppression. Ne fermez pas cette fenêtre avant que cette opération soit terminée. + Les éléments dans la corbeille sont en cours de suppression. Veuillez ne pas fermer cette fenêtre avant que cette opération ne soit terminée. La corbeille est maintenant vide Les éléments supprimés de la corbeille seront supprimés définitivement regexlib.com rencontre actuellement des problèmes sur lesquels nous n'avons aucun contrôle. Nous sommes sincèrement désolés pour le désagrément.]]> @@ -353,14 +462,17 @@ Lier à un media Sélectionner le noeud de base du contenu Sélectionner le media + Sélectionner le type de media Sélectionner l'icône Sélectionner l'élément Sélectionner le lien Sélectionner la macro Sélectionner le contenu + Sélectionner le type de contenu Sélectionner le noeud de base des media Sélectionner le membre Sélectionner le groupe de membres + Sélectionner le type de membre Sélectionner le noeud Sélectionner les sections Sélectionner les utilisateurs @@ -376,10 +488,14 @@ compte Sélectionner un éditeur Selectionner un snippet + Ceci supprimera le noeud et toutes ses langues. Si vous souhaitez supprimer une langue spécifique, vous devriez plutôt supprimer la publication du noeud dans cette langue-là. + + + Il n'y a pas d'éléments dans le dictionnaire. %0%' ci-dessous. + Editez les différentes versions de langues pour l'élément de dictionnaire '%0%' ci-dessous. ]]> Nom de Culture Aperçu du dictionaire + + Recherches configurées + Affiche les propriétés et les outils de chaque Recherche configurée (e.g. une recherche multi-index) + Valeurs du champ + Etat de santé + L'état de santé de l'index et s'il peut être lu + Indexeurs + Info Index + Liste les propriétés de l'index + Gérer les index d'Examine + Vous permet de voir les détails de chaque index et fournit des outils pour gérer les index + Reconstruire l'index + + Cela pourrait prendre un certain temps en fonction de la quantité de contenu présente dans votre site.
        + Il est déconseillé de reconstruire un index pendant les périodes de trafic intense sur le site web ou quand les éditeurs sont en train d'éditer du contenu. + ]]> +
        + Recherches + Rechercher dans l'index et afficher les résultats + Outils + Outils pour gérer l'index + champs + L'index ne peut pas être lu et devra être reconstruit + Le processus dure plus de temps que prévu, vérifiez les logs Umbraco afin de voir s'il y a eu des erreurs pendant cette opératon + Cet index ne peut pas être reconstruit parce qu'on ne lui a pas assigné de + IIndexPopulator + Votre nom d'utilisateur Votre mot de passe @@ -403,10 +547,18 @@ Entrez votre email Entrez un message... Votre nom d'utilisateur est généralement votre adresse email + #value ou ?key=value + Introduisez l'alias... + Génération de l'alias... + Créer un élément + Créer + Modifier + Nom Créer une liste personnalisée Supprimer la liste personnalisée + Il existe déjà un type de contenu, un tye de media ou un type de membre avec cet alias Renommé @@ -432,9 +584,11 @@ Sélectionnez le répertoire où déplacer dans l'arborescence ci-dessous a été déplacé sous + %0% supprimera les propriétés et leurs données des éléments suivants]]> + Je comprends que cette action va supprimer les propriétés et les données basées sur ce Type de Données - Vos données ont été sauvegardées, mais avant de pouvoir publier votre page, il y a des erreurs que vous devez corriger : + Vos données ont été sauvegardées, mais avant de pouvoir publier votre page, il y a des erreurs que vous devez d'abord corriger : Le Membership Provider n'autorise pas le changement des mots de passe (EnablePasswordRetrieval doit être défini à true) %0% existe déjà Des erreurs sont survenues : @@ -459,8 +613,9 @@ Noeud de départ supprimé, contactez votre administrateur Veuillez sélectionner du contenu avant de changer le style Aucun style actif disponible - Veuillez placer le curseur à gauche des deux cellules que vous voulez fusionner + Veuillez placer le curseur à la gauche des deux cellules que vous voulez fusionner Vous ne pouvez pas scinder une cellule qui n'a pas été fusionnée. + Cette propriété n'est pas valide Options @@ -472,6 +627,7 @@ Tout Êtes-vous certain(e)? Retour + Retour à l'aperçu Bord par Annuler @@ -483,6 +639,7 @@ Confirmer Conserver Conserver les proportions + Contenu Continuer Copier Créer @@ -502,16 +659,21 @@ Eléments Email Erreur + Champ Trouver Premier + Point focal Général Groupes + Groupe Hauteur Aide Cacher Historique Icône + Id Importer + Inclure les sous-dossiers dans la recherche Info Marge intérieure Insérer @@ -548,9 +710,11 @@ Un moment s'il vous plaît... Précédent Propriétés + Reconstruire Email de réception des données de formulaire Corbeille Votre corbeille est vide + Rafraîchir Restant Enlever Renommer @@ -564,6 +728,7 @@ Désolé, nous ne pouvons pas trouver ce que vous recherchez Aucun élément n'a été ajouté Serveur + Paramètres Montrer Afficher la page à l'envoi Taille @@ -572,6 +737,7 @@ Envoyer Type Rechercher... + sous Haut Mettre à jour Upgrader @@ -611,8 +777,8 @@ Parcourir les sections Raccourcis afficher les raccourcis - Passer à la vue en liste - Basculer vers l'autorisation comme racine + Activer / Désactiver la vue en liste + Activer / Désactiver l'autorisation comme racine Commenter/Décommenter les lignes Supprimer la ligne Copier les lignes vers le haut @@ -621,6 +787,7 @@ Déplacer les lignes vers le bas Général Editeur + Activer / Désactiver les variantes de culture Couleur de fond @@ -875,6 +1042,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Editez vos notifications pour %0% + Paramètres de notification enregistrés pour + Les langues suivantes ont été modifiées : %0% @@ -966,29 +1135,50 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à ]]> + Les langues suivantes ont été modifiées :

        + %0% + ]]>
        La notification [%0%] à propos de %1% a été executée sur %2% Notifications + Actions + Créé + Créer un package et localisez le package. Les packages Umbraco ont généralement une extension ".umb" ou ".zip". ]]> + Ceci va supprimer le package Déposez pour uploader + Inclure tous les noeuds enfant ou cliquez ici pour choisir les fichiers Uploader un package Installez un package local en le sélectionnant sur votre ordinateur. Installez uniquement des packages de sources fiables que vous connaissez Uploader un autre package Annuler et uploader un autre package - Licence J'accepte les conditions d'utilisation - Installer le package - Terminer + Chemin du fichier + Le chemin absolu du fichier (eg: /bin/umbraco.bin) + Installé Packages installés + Installer localement + Terminer + Ce package n'a pas de vue de configuration + Aucun package n'a encore été créé Vous n'avez aucun package installé 'Packages' en haut à droite de votre écran]]> - Chercher des packages + Actions du package + URL de l'auteur + Contenu du package + Fichiers du package + URL de l'icone + Installer le package + Licence + URL de la licence + Propriétés du package + Chercher des packages Résultats pour Nous n'avons rien pu trouver pour Veuillez essayer de chercher un autre package ou naviguez à travers les catégories @@ -1025,6 +1215,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Remarque : tous les documents, media etc. dépendant des éléments que vous supprimez vont cesser de fonctionner, ce qui peut provoquer une instabilité du système, désinstallez donc avec prudence. En cas de doute, contactez l'auteur du package.]]> Version du package + Mise à jour à partir de la version Package déjà installé Ce package ne peut pas être installé, il nécessite au minimum la version Umbraco %0% Désinstallation... @@ -1043,24 +1234,29 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Coller, mais supprimer le formatage (recommandé) - Protection basée sur les rôles - via les groupes de membres Umbraco.]]> - Vous devez créer un groupe avant de pouvoir utiliser l'authentification basée sur les rôles + Protection basée sur les groupes + Si vous souhaitez donner accès à tous les utilisateurs de groupes de membres spécifiques + Vous devez créer un groupe de membres avant de pouvoir utiliser la protection basée sur les groupes Page d'erreur Utilisé pour les personnes connectées, mais qui n'ont pas accès - Choisissez comment restreindre l'accès à cette page - %0% est maintenant protégée - Protection supprimée de %0% + %0%]]> + %0% est maintenant protégée]]> + %0% supprimée]]> Page de connexion Choisissez la page qui contient le formulaire de connexion - Supprimer la protection + Supprimer la protection... + %0%?]]> Choisissez les pages qui contiennent le formulaire de connexion et les messages d'erreur - Choisissez les rôles qui ont accès à cette page - Définissez l'identifiant et le mot de passe pour cette page - Protection utilisateur unique - Si vous souhaitez mettre en place une protection simple utilisant un identifiant et un mot de passe uniques + %0%]]> + %0%]]> + Protection pour des membres spécifiques + Si vous souhaitez donner accès à des membres spécifiques + Permissions utilisateur insuffisantes pour publier tous les documents enfants. + @@ -1076,7 +1272,8 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à - Inclure les pages enfant non publiées + + La validation a échoué pour la langue obligatoire '%0%'. Cette langue a été sauvegardée mais pas publiée. Publication en cours - veuillez patienter... %0% pages sur %1% ont été publiées... %0% a été publié @@ -1090,12 +1287,15 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Vous n'avez configuré aucune couleur approuvée + Vous pouvez uniquement sélectionner des éléments du(des) type(s) : %0% Vous avez choisi un élément de contenu actuellement supprimé ou dans la corbeille Vous avez choisi des éléments de contenu actuellement supprimés ou dans la corbeille + Elément supprimé Vous avez choisi un élément media actuellement supprimé ou dans la corbeille Vous avez choisi des éléments media actuellement supprimés ou dans la corbeille + Mis dans la corbeille introduire un lien externe @@ -1108,11 +1308,13 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Réinitialiser - Définir le recadrage Sauvegarder le recadrage Ajouter un nouveau recadrage + Terminé + Annuler les modifications + Sélectionnez une version à comparer avec la version actuelle Version actuelle Le texte en Rouge signifie qu'il a été supprimé de la version choisie, vert signifie ajouté]]> Le document a été restauré à une version antérieure @@ -1125,20 +1327,14 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Editer le fichier de script - Concierge Contenu - Courier - Développeur - Assistant de configuration Umbraco + Formulaires Medias Membres - Newsletters + Packages Configuration - Statistiques Traduction Utilisateurs - Aide - Formulaires Les meilleurs tutoriels vidéo Umbraco @@ -1158,14 +1354,16 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Ce type de contenu utilise en tant que type de contenu de base. Les onglets du type de contenu de base ne sont pas affichés et peuvent seulement être modifiés à partir du type de contenu de base lui-même. Aucune propriété définie dans cet onglet. Cliquez sur le lien "Ajouter une nouvelle propriété" en-haut pour créer une nouvelle propriété. + Créer le template correspondant Ajouter une icône Ordre de tri Date de création Tri achevé. - Faites glisser les différents éléments vers le haut ou vers le bas pour définir la manière dont ils doivent être organisés. Ou cliquez sur les entêtes de colonnes pour trier la collection complète d'éléments + Faites glisser les différents éléments vers le haut ou vers le bas pour définir la manière dont ils doivent être organisés. Ou cliquez sur les en-têtes de colonnes pour trier la collection complète d'éléments + Ce noeud n'a aucun noeud enfant à trier Validation @@ -1175,7 +1373,6 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Permissions utilisateur insuffisantes, l'opération n'a pas pu être complétée Annulation L'opération a été annulée par une extension tierce - La publication a été annulée par une extension tierce. Le type de propriété existe déjà Type de propriété créé Type de données : %1%]]> @@ -1189,16 +1386,22 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Feuille de style sauvegardée sans erreurs Type de données sauvegardé Elément de dictionnaire sauvegardé - La publication a échoué car la page parent n'est pas publiée Contenu publié et visible sur le site + %0% documents publiés et visibles sur le site web + %0% publié et visible sur le site web + %0% documents publiés pour la langue %1% et visibles sur le site web Contenu sauvegardé N'oubliez pas de publier pour rendre les modifications visibles + Un planning de publication a été mis à jour + %0% sauvegardé Envoyer pour approbation Les modifications ont été envoyées pour approbation + %0% modifications ont été envoyées pour approbation Media sauvegardé Media sauvegardé sans erreurs Membre sauvegardé + Groupe de membres sauvegardé Propriété de feuille de style sauvegardée Feuille de style sauvegardée Modèle sauvegardé @@ -1213,11 +1416,14 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Langue sauvegardée Type de média sauvegardé Type de membre sauvegardé + Groupe de membres sauvegardé Modèle non sauvegardé Assurez-vous de ne pas avoir 2 modèles avec le même alias. Modèle sauvegardé Modèle sauvegardé sans aucune erreurs ! Contenu publié + Variation de contenu %0% dépubliée + La langue obligatoire '%0%' a été dépubliée. Toutes les langues pour cet éléménent de contenu sont maintenant dépubliées. Vue partielle sauvegardée Vue partielle sauvegardée sans erreurs ! Vue partielle non sauvegardée @@ -1237,16 +1443,35 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à L'utilisateur %0% a été supprimé Inviter l'utilisateur L'invitation a été envoyée à nouveau à %0% + Impossible de publier le document car la langue obligatoire '%0%' n'est pas publiée + La validation a échoué pour la langue '%0%' + Le Type de Document a été exporté dans le fichier + Une erreur est survenue durant l'export du type de document + La date de publication ne peut pas être dans le passé + Impossible de planifier la publication du document car la langue obligatoire '%0%' n'est pas publiée + Impossible de planifier la publication du document car la langue obligatoire '%0%' a une date de publication postérieure à celle d'une langue non obligatoire + La date d'expiration ne peut pas être dans le passé + La date d'expiration ne peut pas être antérieure à la date de publication - Utilise la syntaxe CSS. Ex : h1, .redHeader, .blueTex + Ajouter un style + Modifier un style + Styles pour l'éditeur de texte + Definir les styles qui doivent êtres disponibles dans l'éditeur de texte pour cette feuille de style Editer la feuille de style Editer la propriété de feuille de style Donner un nom pour identifier la propriété dans le Rich Text Editor Prévisualiser + L'apparence qu'aura le text dans l'éditeur de texte. + Sélecteur + Utilise la syntaxe CSS. Ex : "h1" ou ".redHeader" Styles + Le CSS qui devrait être appliqué dans l'éditeur de texte, e.g. "color:red;" + Code + Editeur de Texte + Echec de la suppression du modèle avec l'ID %0% Editer le modèle Sections Insérer une zone de contenu @@ -1293,6 +1518,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Générateur de requêtes éléments trouvés, en + copier dans le clipboard Je veux tout le contenu le contenu du type "%0%" @@ -1363,7 +1589,9 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Compositions - Vous n'avez pas ajouté d'onglet + Groupe + Vous n'avez pas ajouté de groupe + Ajouter un groupe Hérité de Ajouter une propriété Label requis @@ -1371,7 +1599,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Configure l'élément de contenu de manière à afficher ses éléments enfants sous forme d'une liste que l'on peut trier et filtrer, les enfants ne seront pas affichés dans l'arborescence Modèles autorisés Sélectionnez les modèles que les éditeurs sont autorisés à utiliser pour du contenu de ce type. - Autorisé comme racine + Autoriser comme racine Autorisez les éditeurs à créer du contenu de ce type à la racine de l'arborescence de contenu. Types de noeuds enfants autorisés Autorisez la création de contenu des types spécifiés sous le contenu de ce type-ci @@ -1379,6 +1607,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Hériter des onglets et propriétés d'un type de document existant. De nouveaux onglets seront ajoutés au type de document actuel, ou fusionnés s'il existe un onglet avec un nom sililaire. Ce type de contenu est utilisé dans une composition, et ne peut donc pas être lui-même un composé. Il n'y a pas de type de contenu disponible à utiliser dans une composition. + La suppression d'une composition supprimera les données de toutes les propriétés associées. Une fois que vous sauvegardez le type de document, il n'y a plus moyen de faire marche arrière. Editeurs disponibles Réutiliser Configuration de l'éditeur @@ -1407,6 +1636,35 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à l'onglet n'a pas d'ordre de tri Où cette composition est-elle utilisée? Cette composition est actuellement utilisée dans la composition des types de contenu suivants : + Permettre une variation par culture + Permettre aux éditeurs de créer du contenu de ce type dans différentes langues. + Permettre une variation par culture + Type de l'Elément + Est un Type d'Elément + Un Type d'Elément est destiné à être utilisé par exemple dans Nested Content, et pas dans l'arborescence. + Ceci n'est pas d'application pour un Type d'Elément + Vous avez apporté des modifications à cette propriété. Etes-vous certain.e de vouloir les annuler? + + + Ajouter une langue + Langue obligatoire + Les propriétés doivent être remplies dans cette langue avant que le noeud ne puisse être publié. + Langue par défaut + Un site Umbraco ne peut avoir qu'une seule langue par défaut définie. + Changer la langue par défaut peut amener à ce que du contenu par défaut soit manquant. + Retombe sur + Pas de langue alternative + Pour permettre à un site multi-langue de retomber sur une autre langue dans le cas où il n'existe pas dans la langue demandée, sélectionnez-là ici. + Langue alternative + aucune + + + Ajouter un paramètre + Modifier le paramètre + Introduire le nom de la macro + Paramètres + Définir les paramètres qui devraient être disponibles lorsque l'on utilise cette macro. + Sélectionner le fichier de vue partielle de la macro Fabrication des modèles @@ -1427,7 +1685,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Choisir un champ Convertir les sauts de ligne Oui, convertir les sauts de ligne - Remplace les sauts de ligne avec des balises &lt;br&gt; + Remplace les sauts de ligne avec des balises 'br' Champs particuliers Oui, la date seulement Format et encodage @@ -1449,7 +1707,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Champs standards Majuscules Encode pour URL - Formatera les caractères spéciaux de manière à ce qu'ils soient reconnus dans une URL + Formatera les caractères spéciaux dans les URL Sera seulement utilisé si toutes les valeurs des champs ci-dessus sont vides Ce champ sera utilisé seulement si le champ initial est vide Oui, avec l'heure. Séparateur: @@ -1519,14 +1777,17 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Scripts Feuilles de style Modèles + Visualisation des Log Utilisateurs - Analytique + Configuration + Modélisation + Parties Tierces Nouvelle mise à jour disponible %0% est disponible, cliquez ici pour télécharger Aucune connexion au serveur - Erreur lors de la recherche de mises à jour. Veuillez vérifier le stack trace pour obtenir plus d'informations sur l'erreur. + Erreur lors de la recherche de mises à jour. Veuillez vérifier le stack trace pour obtenir plus d'informations. Accès @@ -1554,7 +1815,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Voir le profil de l'utilisateur Ajouter des groupes pour donner les accès et permissions Inviter un autre utilisateur - Inviter de nouveaux utilisateurs pour leur donner accès à Umbraco. Un email d'invitation sera envoyé à chaque utilisateur avec des informations concernant la connexion à Umbraco. + Inviter de nouveaux utilisateurs pour leur donner accès à Umbraco. Un email d'invitation sera envoyé à chaque utilisateur avec des informations concernant la connexion à Umbraco. Les invitations sont valables pendant 72 heures. Langue Spécifiez la langue dans laquelle vous souhaitez voir les menus et dialogues Date du dernier bloquage @@ -1606,7 +1867,8 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à a été invité Une invitation a été envoyée au nouvel utilisateur avec les détails concernant la connexion à Umbraco. Bien le bonjour et bienvenue dans Umbraco! Vous serez prêt.e dans moins d'1 minute, vous devez encore simplement configurer votre mot de passe et ajouter une photo pour votre avatar. - Chargez une photo afin que les autres utilisateurs puissent vous reconnaître facilement. + Bienvenue dans Umbraco! Malheureusement, votre invitation a expiré. Veuillez contacter votre administrateur et demandez-lui de vous l'envoyer à nouveau. + Chargez une photo afin que les autres utilisateurs puissent vous reconnaître facilement. Cliquez sur le cercle ci-dessus pour charger votre photo. Rédacteur Modifier Votre profil @@ -1712,6 +1974,17 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Nouvel envoi de l'invitation en cours... Supprimer l'Utilisateur Etes-vous certain(e) de vouloir supprimer le compte de cet utilisateur? + Tous + Actif + Désactivé + Bloqué + Invité + Inactif + Nom (A-Z) + Nom (Z-A) + Plus récent + Plus ancien + Dernière connexion Validation @@ -1720,7 +1993,9 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Valider comme Url ...ou introduisez une validation spécifique Champ obligatoire + Introduisez un message d'erreur de validation personnalisé (optionnel) Introduisez une expression régulière + Introduisez un message d'erreur de validation personnalisé (optionnel) Vous devez ajouter au moins Vous ne pouvez avoir que éléments @@ -1728,6 +2003,12 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Date non valide Pas un nombre Email non valide + La valeur ne peut pas être null + La valeur ne peut pas être vide + Valeur non valide, elle ne correspond pas au modèle correct + Validation personnalisée + %1% supplémentaires.]]> + %1% en trop.]]>