diff --git a/src/Umbraco.Core/CompositionExtensions.cs b/src/Umbraco.Core/CompositionExtensions.cs index e1c7ad44678a..828a577c3462 100644 --- a/src/Umbraco.Core/CompositionExtensions.cs +++ b/src/Umbraco.Core/CompositionExtensions.cs @@ -203,6 +203,28 @@ public static void SetServerMessenger(this Composition composition, IServerMesse composition.RegisterUnique(_ => registrar); } + /// + /// Sets the database server messenger options. + /// + /// The composition. + /// A function creating the options. + /// Use DatabaseServerRegistrarAndMessengerComposer.GetDefaultOptions to get the options that Umbraco would use by default. + public static void SetDatabaseServerMessengerOptions(this Composition composition, Func factory) + { + composition.RegisterUnique(factory); + } + + /// + /// Sets the database server messenger options. + /// + /// The composition. + /// Options. + /// Use DatabaseServerRegistrarAndMessengerComposer.GetDefaultOptions to get the options that Umbraco would use by default. + public static void SetDatabaseServerMessengerOptions(this Composition composition, DatabaseServerMessengerOptions options) + { + composition.RegisterUnique(_ => options); + } + /// /// Sets the short string helper. /// diff --git a/src/Umbraco.Core/ContentExtensions.cs b/src/Umbraco.Core/ContentExtensions.cs index f802c2d0d991..a7d40b0b7d03 100644 --- a/src/Umbraco.Core/ContentExtensions.cs +++ b/src/Umbraco.Core/ContentExtensions.cs @@ -7,6 +7,7 @@ using System.Xml.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using NPoco.Expressions; using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -52,8 +53,8 @@ public static ContentStatus GetStatus(this IContent content, string culture = nu return ContentStatus.Unpublished; } - - + + #endregion /// @@ -134,9 +135,14 @@ public static IEnumerable GetPropertiesForGroup(this IContentBase cont /// /// Sets the posted file value of a property. /// - /// This really is for FileUpload fields only, and should be obsoleted. For anything else, - /// you need to store the file by yourself using Store and then figure out - /// how to deal with auto-fill properties (if any) and thumbnails (if any) by yourself. + public static void SetValue(this IContentBase content, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, string propertyTypeAlias, string filename, HttpPostedFileBase postedFile, string culture = null, string segment = null) + { + content.SetValue(contentTypeBaseServiceProvider, propertyTypeAlias, postedFile.FileName, postedFile.InputStream, culture, segment); + } + + /// + /// Sets the posted file value of a property. + /// public static void SetValue(this IContentBase content, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null) { if (filename == null || filestream == null) return; diff --git a/src/Umbraco.Core/UriExtensions.cs b/src/Umbraco.Core/UriExtensions.cs index 083ca90cc4b0..1198b26e0fcb 100644 --- a/src/Umbraco.Core/UriExtensions.cs +++ b/src/Umbraco.Core/UriExtensions.cs @@ -23,21 +23,21 @@ public static class UriExtensions /// /// /// There are some special routes we need to check to properly determine this: - /// + /// /// If any route has an extension in the path like .aspx = back office - /// + /// /// These are def back office: /// /Umbraco/BackOffice = back office /// /Umbraco/Preview = back office /// If it's not any of the above, and there's no extension then we cannot determine if it's back office or front-end /// so we can only assume that it is not back office. This will occur if people use an UmbracoApiController for the backoffice /// but do not inherit from UmbracoAuthorizedApiController and do not use [IsBackOffice] attribute. - /// + /// /// These are def front-end: /// /Umbraco/Surface = front-end /// /Umbraco/Api = front-end /// But if we've got this far we'll just have to assume it's front-end anyways. - /// + /// /// internal static bool IsBackOfficeRequest(this Uri url, string applicationPath, IGlobalSettings globalSettings) { @@ -152,9 +152,9 @@ internal static bool IsClientSideRequest(this Uri url) var toInclude = new[] {".aspx", ".ashx", ".asmx", ".axd", ".svc"}; return toInclude.Any(ext.InvariantEquals) == false; } - catch (ArgumentException ex) + catch (ArgumentException) { - Current.Logger.Error(typeof(UriExtensions), ex, "Failed to determine if request was client side"); + Current.Logger.Debug(typeof(UriExtensions), "Failed to determine if request was client side (invalid chars in path \"{Path}\"?)", url.LocalPath); return false; } } diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs index ab576171f4e4..de641a99a2d3 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentTests.cs @@ -10,6 +10,7 @@ using Umbraco.Web.PublishedCache; using Umbraco.Core.Composing; using Moq; +using Newtonsoft.Json; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; @@ -32,6 +33,8 @@ public class PublishedContentTests : PublishedContentTestBase protected override void Compose() { base.Compose(); + _publishedSnapshotAccessorMock = new Mock(); + Composition.RegisterUnique(_publishedSnapshotAccessorMock.Object); Composition.RegisterUnique(f => new PublishedModelFactory(f.GetInstance().GetTypes())); Composition.RegisterUnique(); @@ -87,6 +90,7 @@ protected override TypeLoader CreateTypeLoader(IAppPolicyCache runtimeCache, IGl } private readonly Guid _node1173Guid = Guid.NewGuid(); + private Mock _publishedSnapshotAccessorMock; protected override string GetXmlContent(int templateId) { @@ -792,6 +796,91 @@ public void IsDescendantOrSelf() Assert.IsTrue(customDoc3.IsDescendantOrSelf(customDoc3)); } + [Test] + public void SiblingsAndSelf() + { + // Structure: + // - Root : 1046 (no parent) + // -- Level1.1: 1173 (parent 1046) + // --- Level1.1.1: 1174 (parent 1173) + // --- Level1.1.2: 117 (parent 1173) + // --- Level1.1.3: 1177 (parent 1173) + // --- Level1.1.4: 1178 (parent 1173) + // --- Level1.1.5: 1176 (parent 1173) + // -- Level1.2: 1175 (parent 1046) + // -- Level1.3: 4444 (parent 1046) + var root = GetNode(1046); + var level1_1 = GetNode(1173); + var level1_1_1 = GetNode(1174); + var level1_1_2 = GetNode(117); + var level1_1_3 = GetNode(1177); + var level1_1_4 = GetNode(1178); + var level1_1_5 = GetNode(1176); + var level1_2 = GetNode(1175); + var level1_3 = GetNode(4444); + + _publishedSnapshotAccessorMock.Setup(x => x.PublishedSnapshot.Content.GetAtRoot()).Returns(new []{root}); + + CollectionAssertAreEqual(new []{root}, root.SiblingsAndSelf()); + + CollectionAssertAreEqual( new []{level1_1, level1_2, level1_3}, level1_1.SiblingsAndSelf()); + CollectionAssertAreEqual( new []{level1_1, level1_2, level1_3}, level1_2.SiblingsAndSelf()); + CollectionAssertAreEqual( new []{level1_1, level1_2, level1_3}, level1_3.SiblingsAndSelf()); + + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_3, level1_1_4, level1_1_5}, level1_1_1.SiblingsAndSelf()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_3, level1_1_4, level1_1_5}, level1_1_2.SiblingsAndSelf()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_3, level1_1_4, level1_1_5}, level1_1_3.SiblingsAndSelf()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_3, level1_1_4, level1_1_5}, level1_1_4.SiblingsAndSelf()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_3, level1_1_4, level1_1_5}, level1_1_5.SiblingsAndSelf()); + + } + + [Test] + public void Siblings() + { + // Structure: + // - Root : 1046 (no parent) + // -- Level1.1: 1173 (parent 1046) + // --- Level1.1.1: 1174 (parent 1173) + // --- Level1.1.2: 117 (parent 1173) + // --- Level1.1.3: 1177 (parent 1173) + // --- Level1.1.4: 1178 (parent 1173) + // --- Level1.1.5: 1176 (parent 1173) + // -- Level1.2: 1175 (parent 1046) + // -- Level1.3: 4444 (parent 1046) + var root = GetNode(1046); + var level1_1 = GetNode(1173); + var level1_1_1 = GetNode(1174); + var level1_1_2 = GetNode(117); + var level1_1_3 = GetNode(1177); + var level1_1_4 = GetNode(1178); + var level1_1_5 = GetNode(1176); + var level1_2 = GetNode(1175); + var level1_3 = GetNode(4444); + + _publishedSnapshotAccessorMock.Setup(x => x.PublishedSnapshot.Content.GetAtRoot()).Returns(new []{root}); + + CollectionAssertAreEqual(new IPublishedContent[0], root.Siblings()); + + CollectionAssertAreEqual( new []{level1_2, level1_3}, level1_1.Siblings()); + CollectionAssertAreEqual( new []{level1_1, level1_3}, level1_2.Siblings()); + CollectionAssertAreEqual( new []{level1_1, level1_2}, level1_3.Siblings()); + + CollectionAssertAreEqual( new []{ level1_1_2, level1_1_3, level1_1_4, level1_1_5}, level1_1_1.Siblings()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_3, level1_1_4, level1_1_5}, level1_1_2.Siblings()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_4, level1_1_5}, level1_1_3.Siblings()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_3, level1_1_5}, level1_1_4.Siblings()); + CollectionAssertAreEqual( new []{level1_1_1, level1_1_2, level1_1_3, level1_1_4}, level1_1_5.Siblings()); + + } + + private void CollectionAssertAreEqual(IEnumerable expected, IEnumerable actual) + where T: IPublishedContent + { + var e = expected.Select(x => x.Id); + var a = actual.Select(x => x.Id); + CollectionAssert.AreEquivalent(e, a, $"\nExpected:\n{string.Join(", ", e)}\n\nActual:\n{string.Join(", ", a)}"); + } [Test] public void FragmentProperty() diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/localization/localize.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/localization/localize.directive.js index c3093eee9e14..df3770056e30 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/localization/localize.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/localization/localize.directive.js @@ -32,16 +32,27 @@ angular.module("umbraco.directives") restrict: 'E', scope:{ key: '@', - tokens: '=' + tokens: '=', + watchTokens: '@' }, replace: true, link: function (scope, element, attrs) { var key = scope.key; - var tokens = scope.tokens ? scope.tokens : null; - localizationService.localize(key, tokens).then(function(value){ - element.html(value); + scope.text = ""; + + // A render function to be able to update tokens as values update. + function render() { + element.html(localizationService.tokenReplace(scope.text, scope.tokens || null)); + } + + localizationService.localize(key).then(function(value){ + scope.text = value; + render(); }); + if (scope.watchTokens === 'true') { + scope.$watch("tokens", render, true); + } } }; }) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js index 9ee83dc2ba3f..c027e0778ee6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js @@ -62,8 +62,8 @@ function valPropertyMsg(serverValidationManager) { if (!watcher) { watcher = scope.$watch("currentProperty.value", function (newValue, oldValue) { - - if (!newValue || angular.equals(newValue, oldValue)) { + + if (angular.equals(newValue, oldValue)) { return; } @@ -78,10 +78,12 @@ function valPropertyMsg(serverValidationManager) { // based on other errors. We'll also check if there's no other validation errors apart from valPropertyMsg, if valPropertyMsg // is the only one, then we'll clear. - if ((errCount === 1 && angular.isArray(formCtrl.$error.valPropertyMsg)) || (formCtrl.$invalid && angular.isArray(formCtrl.$error.valServer))) { + if (errCount === 0 || (errCount === 1 && angular.isArray(formCtrl.$error.valPropertyMsg)) || (formCtrl.$invalid && angular.isArray(formCtrl.$error.valServer))) { scope.errorMsg = ""; formCtrl.$setValidity('valPropertyMsg', true); - stopWatch(); + } else if (showValidation && scope.errorMsg === "") { + formCtrl.$setValidity('valPropertyMsg', false); + scope.errorMsg = getErrorMsg(); } }, true); } @@ -152,6 +154,7 @@ function valPropertyMsg(serverValidationManager) { showValidation = true; if (hasError && scope.errorMsg === "") { scope.errorMsg = getErrorMsg(); + startWatch(); } else if (!hasError) { scope.errorMsg = ""; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/localization.service.js b/src/Umbraco.Web.UI.Client/src/common/services/localization.service.js index 2a9afdfa9405..ea2ad732631f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/localization.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/localization.service.js @@ -43,16 +43,11 @@ angular.module('umbraco.services') var entry = dictionary[value]; if (entry) { - if (tokens) { - for (var i = 0; i < tokens.length; i++) { - entry = entry.replace("%" + i + "%", tokens[i]); - } - } - return entry; + return service.tokenReplace(entry, tokens); } return "[" + value + "]"; } - + var service = { // array to hold the localized resource string entries dictionary: [], @@ -127,7 +122,29 @@ angular.module('umbraco.services') } return value; }, - + + + /** + * @ngdoc method + * @name umbraco.services.localizationService#tokenReplace + * @methodOf umbraco.services.localizationService + * + * @description + * Helper to replace tokens + * @param {String} value the text-string to manipulate + * @param {Array} tekens An array of tokens values + * @returns {String} Replaced test-string + */ + tokenReplace: function (text, tokens) { + if (tokens) { + for (var i = 0; i < tokens.length; i++) { + text = text.replace("%" + i + "%", tokens[i]); + } + } + return text; + }, + + /** * @ngdoc method * @name umbraco.services.localizationService#localize @@ -146,8 +163,7 @@ angular.module('umbraco.services') */ localize: function (value, tokens) { return service.initLocalizedResources().then(function (dic) { - var val = _lookup(value, tokens, dic); - return val; + return _lookup(value, tokens, dic); }); }, diff --git a/src/Umbraco.Web.UI.Client/src/common/services/notifications.service.js b/src/Umbraco.Web.UI.Client/src/common/services/notifications.service.js index 2575b05bb6d9..c123ac6cea03 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/notifications.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/notifications.service.js @@ -85,17 +85,17 @@ angular.module('umbraco.services') nArray.push(item); if(!item.sticky) { - $timeout(function() { - var found = _.find(nArray, function(i) { - return i.id === item.id; - }); - - if (found) { - var index = nArray.indexOf(found); - nArray.splice(index, 1); - } - - }, 7000); + $timeout( + function() { + var found = _.find(nArray, function(i) { + return i.id === item.id; + }); + if (found) { + var index = nArray.indexOf(found); + nArray.splice(index, 1); + } + } + , 10000); } return item; diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index 8c0df988d1b0..4a441ec1912a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -137,6 +137,7 @@ @import "components/umb-iconpicker.less"; @import "components/umb-insert-code-box.less"; @import "components/umb-packages.less"; +@import "components/umb-logviewer.less"; @import "components/umb-package-local-install.less"; @import "components/umb-panel-group.less"; @import "components/umb-lightbox.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/notifications/umb-notifications.less b/src/Umbraco.Web.UI.Client/src/less/components/notifications/umb-notifications.less index 9e16eca414b8..7f04fef9a928 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/notifications/umb-notifications.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/notifications/umb-notifications.less @@ -22,7 +22,14 @@ font-size: 14px; border: none; position: relative; - margin-bottom: 0; + border-radius: 10px; + margin: 10px; + + .close { + top: 0; + right: -6px; + opacity: 0.4; + } } .umb-notifications__notification.-extra-padding { 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 new file mode 100644 index 000000000000..f7aa0e455871 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-logviewer.less @@ -0,0 +1,42 @@ +/* PACKAGE DETAILS */ + +.umb-logviewer { + display: flex; + flex-flow: row wrap; +} + +@sidebarwidth: 350px; // Width of sidebar. Ugly hack because of old version of Less + +.umb-logviewer__main-content { + flex: 1 1 auto; + margin-right: 20px; + width: calc(~'100%' - ~'@{sidebarwidth}' - ~'20px'); // Make sure that the main content area doesn't gets affected by inline styling + min-width: 500px; + + .btn-link { + text-align: left; + } +} + +.umb-logviewer__sidebar { + flex: 0 0 @sidebarwidth; +} + +@media (max-width: 768px) { + + .umb-logviewer { + flex-direction: column; + } + + .umb-logviewer__main-content { + flex: 1 1 auto; + width: 100%; + margin-bottom: 30px; + margin-right: 0; + } + + .umb-logviewer__sidebar { + flex: 1 1 auto; + width: 100%; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/less/modals.less b/src/Umbraco.Web.UI.Client/src/less/modals.less index 771be1bc2aeb..51f87d09dda8 100644 --- a/src/Umbraco.Web.UI.Client/src/less/modals.less +++ b/src/Umbraco.Web.UI.Client/src/less/modals.less @@ -52,7 +52,17 @@ bottom: 0px; left: 0px; right: 0px; - position: absolute;; + position: absolute; +} + +.--notInFront .umb-modalcolumn::after { + content: ''; + position: absolute; + top: 0; + bottom: 0; + right: 0; + left: 0; + background: rgba(0,0,0,.4); } /* re-align loader */ diff --git a/src/Umbraco.Web.UI.Client/src/less/properties.less b/src/Umbraco.Web.UI.Client/src/less/properties.less index 916f1b5a3af7..e14bb5c0d699 100644 --- a/src/Umbraco.Web.UI.Client/src/less/properties.less +++ b/src/Umbraco.Web.UI.Client/src/less/properties.less @@ -16,6 +16,75 @@ border-left: 1px solid @gray-10; } +.date-wrapper__date .flatpickr-input > a { + + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + 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; + } + } +} + +//----- VARIANTS SCHEDULED PUBLISH ------ + +.date-wrapper-mini { + display: flex; + flex-direction: row; +} + +.date-wrapper-mini__date { + display: flex; + + margin-left: 5px; + margin-top: 5px; + margin-bottom: 10px; + + &:first-of-type { + margin-left: 0; + } +} + +.date-wrapper-mini__date .flatpickr-input > a { + + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + padding: 1px 15px; + box-sizing: border-box; + min-width: 180px; + + 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; + } + } +} + //------------------- HISTORY ------------------ .history { @@ -71,4 +140,4 @@ .history-line { display: none; } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web.UI.Client/src/less/variables.less b/src/Umbraco.Web.UI.Client/src/less/variables.less index 6400ae032193..55be161cf8d5 100644 --- a/src/Umbraco.Web.UI.Client/src/less/variables.less +++ b/src/Umbraco.Web.UI.Client/src/less/variables.less @@ -112,7 +112,7 @@ @blueExtraDark: #1b264f;// added 2019 @blueLight: #ADD8E6; @blueNight: #162335;// added 2019 -@orange: #f79c37;// updated 2019 +//@orange: #f79c37;// updated 2019 @pink: #D93F4C;// #C3325F;// update 2019 @pinkLight: #f5c1bc;// added 2019 @pinkRedLight: #ff8a89;// added 2019 @@ -199,6 +199,16 @@ .turquoise{color: @turquoise;} .turquoise-d1{color: @turquoise-d1;} +.text-warning { + color: @orange; +} +.text-error { + color: @red; +} +.text-success { + color: @green; +} + //icon colors for tree icons .color-red, .color-red i{color: @red-d1 !important;} diff --git a/src/Umbraco.Web.UI.Client/src/views/components/grid/grid-rte.html b/src/Umbraco.Web.UI.Client/src/views/components/grid/grid-rte.html index f3b854a0621c..889c4133d53a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/grid/grid-rte.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/grid/grid-rte.html @@ -1,3 +1,3 @@ -
-
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html b/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html index 2bf290b75242..8cdc4a0abc59 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html @@ -27,7 +27,7 @@ {{vm.variants[0].releaseDateFormatted}} - + Set date
@@ -59,7 +59,7 @@ {{vm.variants[0].expireDateFormatted}} - + Set date @@ -84,8 +84,8 @@
-
- +
+
-
+
+
-
Publish:  {{variant.releaseDateFormatted}}
@@ -123,7 +123,7 @@ {{variant.releaseDateFormatted}} - + Set date
@@ -134,7 +134,7 @@
-
+
Unpublish:  {{variant.expireDateFormatted}}
@@ -149,7 +149,7 @@ {{variant.expireDateFormatted}} - + Set date
@@ -182,24 +182,6 @@
-
-
-

-
- -
-
-
- {{ variant.language.name }} -
-
- - - -
-
-
-
-
diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/content/redirecturls.html b/src/Umbraco.Web.UI.Client/src/views/dashboard/content/redirecturls.html index 98a8294e80bc..0f0889750102 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/content/redirecturls.html +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/content/redirecturls.html @@ -13,7 +13,8 @@ type="button" size="s" action="vm.disableUrlTracker($event)" - label-key="redirectUrls_disableUrlTracker"> + label-key="redirectUrls_disableUrlTracker" + button-style="white"> + label-key="redirectUrls_enableUrlTracker" + button-style="success"> diff --git a/src/Umbraco.Web.UI.Client/src/views/logviewer/overview.html b/src/Umbraco.Web.UI.Client/src/views/logviewer/overview.html index 67d89e5ee701..a46853f97e0a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/logviewer/overview.html +++ b/src/Umbraco.Web.UI.Client/src/views/logviewer/overview.html @@ -1,4 +1,4 @@ -
+
@@ -24,8 +24,8 @@
-
-
+
+
@@ -68,7 +68,7 @@
-
+
@@ -95,4 +95,4 @@
-
\ No newline at end of file +
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 e5a97114587a..c23c2cd212bf 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 @@ -1,953 +1,954 @@ angular.module("umbraco") .controller("Umbraco.PropertyEditors.GridController", - function ( - $scope, - localizationService, - gridService, - $timeout, - umbRequestHelper, - angularHelper, - $element, - eventsService - ) { - - // Grid status variables - var placeHolder = ""; - var currentForm = angularHelper.getCurrentForm($scope); - - $scope.currentRow = null; - $scope.currentCell = null; - $scope.currentToolsControl = null; - $scope.currentControl = null; - $scope.openRTEToolbarId = null; - $scope.hasSettings = false; - $scope.showRowConfigurations = true; - $scope.sortMode = false; - $scope.reorderKey = "general_reorder"; - - // ********************************************* - // Sortable options - // ********************************************* - - var draggedRteSettings; - - $scope.sortableOptionsRow = { - distance: 10, - cursor: "move", - placeholder: "ui-sortable-placeholder", - handle: ".umb-row-title-bar", - helper: "clone", - forcePlaceholderSize: true, - tolerance: "pointer", - zIndex: 999999999999999999, - scrollSensitivity: 100, - cursorAt: { - top: 40, - left: 60 - }, - - sort: function (event, ui) { - /* prevent vertical scroll out of the screen */ - var max = $(".umb-grid").width() - 150; - if (parseInt(ui.helper.css("left")) > max) { - ui.helper.css({ "left": max + "px" }); - } - if (parseInt(ui.helper.css("left")) < 20) { - ui.helper.css({ "left": 20 }); - } - }, - - start: function (e, ui) { - - // Fade out row when sorting - ui.item[0].style.display = "block"; - ui.item[0].style.opacity = "0.5"; - - draggedRteSettings = {}; - ui.item.find(".mceNoEditor").each(function () { - // remove all RTEs in the dragged row and save their settings - var id = $(this).attr("id"); - draggedRteSettings[id] = _.findWhere(tinyMCE.editors, { id: id }).settings; - // tinyMCE.execCommand("mceRemoveEditor", false, id); - }); - }, + function ( + $scope, + localizationService, + gridService, + umbRequestHelper, + angularHelper, + $element, + eventsService + ) { + + // Grid status variables + var placeHolder = ""; + var currentForm = angularHelper.getCurrentForm($scope); + + $scope.currentRow = null; + $scope.currentCell = null; + $scope.currentToolsControl = null; + $scope.currentControl = null; + $scope.openRTEToolbarId = null; + $scope.hasSettings = false; + $scope.showRowConfigurations = true; + $scope.sortMode = false; + $scope.reorderKey = "general_reorder"; - stop: function (e, ui) { + // ********************************************* + // Sortable options + // ********************************************* - // Fade in row when sorting stops - ui.item[0].style.opacity = "1"; + var draggedRteSettings; + + $scope.sortableOptionsRow = { + distance: 10, + cursor: "move", + placeholder: "ui-sortable-placeholder", + handle: ".umb-row-title-bar", + helper: "clone", + forcePlaceholderSize: true, + tolerance: "pointer", + zIndex: 999999999999999999, + scrollSensitivity: 100, + cursorAt: { + top: 40, + left: 60 + }, + + sort: function (event, ui) { + /* prevent vertical scroll out of the screen */ + var max = $(".umb-grid").width() - 150; + if (parseInt(ui.helper.css("left")) > max) { + ui.helper.css({ "left": max + "px" }); + } + if (parseInt(ui.helper.css("left")) < 20) { + ui.helper.css({ "left": 20 }); + } + }, - // reset all RTEs affected by the dragging - ui.item.parents(".umb-column").find(".mceNoEditor").each(function () { - var id = $(this).attr("id"); - draggedRteSettings[id] = draggedRteSettings[id] || _.findWhere(tinyMCE.editors, { id: id }).settings; - tinyMCE.execCommand("mceRemoveEditor", false, id); - tinyMCE.init(draggedRteSettings[id]); - }); - currentForm.$setDirty(); - } - }; - - var notIncludedRte = []; - var cancelMove = false; - var startingArea; - - $scope.sortableOptionsCell = { - distance: 10, - cursor: "move", - placeholder: "ui-sortable-placeholder", - handle: ".umb-control-handle", - helper: "clone", - connectWith: ".umb-cell-inner", - forcePlaceholderSize: true, - tolerance: "pointer", - zIndex: 999999999999999999, - scrollSensitivity: 100, - cursorAt: { - top: 45, - left: 90 - }, - - sort: function (event, ui) { - - /* prevent vertical scroll out of the screen */ - var position = parseInt(ui.item.parent().offset().left) + parseInt(ui.helper.css("left")) - parseInt($(".umb-grid").offset().left); - var max = $(".umb-grid").width() - 220; - if (position > max) { - ui.helper.css({ "left": max - parseInt(ui.item.parent().offset().left) + parseInt($(".umb-grid").offset().left) + "px" }); - } - if (position < 0) { - ui.helper.css({ "left": 0 - parseInt(ui.item.parent().offset().left) + parseInt($(".umb-grid").offset().left) + "px" }); - } - }, - - over: function (event, ui) { - - var area = event.target.getScope_HackForSortable().area; - var allowedEditors = area.allowed; - - if (($.inArray(ui.item[0].getScope_HackForSortable().control.editor.alias, allowedEditors) < 0 && allowedEditors) || - (startingArea != area && area.maxItems != '' && area.maxItems > 0 && area.maxItems < area.controls.length + 1)) { + start: function (e, ui) { - $scope.$apply(function () { - event.target.getScope_HackForSortable().area.dropNotAllowed = true; + // Fade out row when sorting + ui.item[0].style.display = "block"; + ui.item[0].style.opacity = "0.5"; + + draggedRteSettings = {}; + ui.item.find(".umb-rte").each(function (key, value) { + // remove all RTEs in the dragged row and save their settings + var rteId = value.id; + draggedRteSettings[rteId] = _.findWhere(tinyMCE.editors, { id: rteId }).settings; }); + }, + + stop: function (e, ui) { + + // Fade in row when sorting stops + ui.item[0].style.opacity = "1"; - ui.placeholder.hide(); - cancelMove = true; + // reset all RTEs affected by the dragging + ui.item.parents(".umb-column").find(".umb-rte").each(function (key, value) { + var rteId = value.id; + draggedRteSettings[rteId] = draggedRteSettings[rteId] || _.findWhere(tinyMCE.editors, { id: rteId }).settings; + tinyMCE.execCommand("mceRemoveEditor", false, rteId); + tinyMCE.init(draggedRteSettings[rteId]); + }); + currentForm.$setDirty(); } - else { - if (event.target.getScope_HackForSortable().area.controls.length == 0){ + }; + + var notIncludedRte = []; + var cancelMove = false; + var startingArea; + $scope.sortableOptionsCell = { + distance: 10, + cursor: "move", + uiFloating: true, + placeholder: "ui-sortable-placeholder", + handle: ".umb-control-handle", + helper: "clone", + connectWith: ".umb-cell-inner", + forcePlaceholderSize: true, + tolerance: "pointer", + zIndex: 999999999999999999, + scrollSensitivity: 100, + cursorAt: { + top: 45, + left: 90 + }, + + sort: function (event, ui) { + + /* prevent vertical scroll out of the screen */ + var position = parseInt(ui.item.parent().offset().left) + parseInt(ui.helper.css("left")) - parseInt($(".umb-grid").offset().left); + var max = $(".umb-grid").width() - 220; + if (position > max) { + ui.helper.css({ "left": max - parseInt(ui.item.parent().offset().left) + parseInt($(".umb-grid").offset().left) + "px" }); + } + if (position < 0) { + ui.helper.css({ "left": 0 - parseInt(ui.item.parent().offset().left) + parseInt($(".umb-grid").offset().left) + "px" }); + } + }, + + over: function (event, ui) { + + var area = event.target.getScope_HackForSortable().area; + var allowedEditors = area.allowed; + + if (($.inArray(ui.item[0].getScope_HackForSortable().control.editor.alias, allowedEditors) < 0 && allowedEditors) || + (startingArea != area && area.maxItems != '' && area.maxItems > 0 && area.maxItems < area.controls.length + 1)) { $scope.$apply(function () { - event.target.getScope_HackForSortable().area.dropOnEmpty = true; + event.target.getScope_HackForSortable().area.dropNotAllowed = true; }); + ui.placeholder.hide(); - } else { - ui.placeholder.show(); + cancelMove = true; } - cancelMove = false; - } - }, - - out: function(event, ui) { - $scope.$apply(function () { - var dropArea = event.target.getScope_HackForSortable().area; - dropArea.dropNotAllowed = false; - dropArea.dropOnEmpty = false; - }); - }, + else { + if (event.target.getScope_HackForSortable().area.controls.length == 0) { - update: function (event, ui) { - /* add all RTEs which are affected by the dragging */ - if (!ui.sender) { - if (cancelMove) { - ui.item.sortable.cancel(); - } - ui.item.parents(".umb-cell.content").find(".mceNoEditor").each(function () { - if ($.inArray($(this).attr("id"), notIncludedRte) < 0) { - notIncludedRte.splice(0, 0, $(this).attr("id")); + $scope.$apply(function () { + event.target.getScope_HackForSortable().area.dropOnEmpty = true; + }); + ui.placeholder.hide(); + } else { + ui.placeholder.show(); } + cancelMove = false; + } + }, + + out: function (event, ui) { + $scope.$apply(function () { + var dropArea = event.target.getScope_HackForSortable().area; + dropArea.dropNotAllowed = false; + dropArea.dropOnEmpty = false; }); - } - else { - $(event.target).find(".mceNoEditor").each(function () { - if ($.inArray($(this).attr("id"), notIncludedRte) < 0) { - notIncludedRte.splice(0, 0, $(this).attr("id")); + }, + + update: function (event, ui) { + /* add all RTEs which are affected by the dragging */ + if (!ui.sender) { + if (cancelMove) { + ui.item.sortable.cancel(); } - }); - } - currentForm.$setDirty(); - }, + ui.item.parents(".umb-cell-content").find(".umb-rte").each(function (key, value) { + var v1 = value.id; - start: function (event, ui) { - //Get the starting area for reference - var area = event.target.getScope_HackForSortable().area; - startingArea = area; + if ($.inArray(v1, notIncludedRte) < 0) { + notIncludedRte.splice(0, 0, v1); + } + }); + } + else { + $(event.target).find(".umb-rte").each(function () { + if ($.inArray($(this).attr("id"), notIncludedRte) < 0) { + notIncludedRte.splice(0, 0, $(this).attr("id")); + } + }); + } + currentForm.$setDirty(); + }, - // fade out control when sorting - ui.item[0].style.display = "block"; - ui.item[0].style.opacity = "0.5"; + start: function (event, ui) { + //Get the starting area for reference + var area = event.target.getScope_HackForSortable().area; + startingArea = area; - // reset dragged RTE settings in case a RTE isn't dragged - draggedRteSettings = undefined; - ui.item[0].style.display = "block"; - ui.item.find(".mceNoEditor").each(function () { - notIncludedRte = []; - var editors = _.findWhere(tinyMCE.editors, { id: $(this).attr("id") }); + // fade out control when sorting + ui.item[0].style.display = "block"; + ui.item[0].style.opacity = "0.5"; - // save the dragged RTE settings - if(editors) { - draggedRteSettings = editors.settings; + // reset dragged RTE settings in case a RTE isn't dragged + draggedRteSettings = undefined; + ui.item[0].style.display = "block"; + ui.item.find(".umb-rte").each(function (key, value) { + notIncludedRte = []; + var rteId = value.id; - // remove the dragged RTE - tinyMCE.execCommand("mceRemoveEditor", false, $(this).attr("id")); + var editors = _.findWhere(tinyMCE.editors, { id: rteId }); - } + // save the dragged RTE settings + if (editors) { + draggedRteSettings = editors.settings; - }); - }, + // remove the dragged RTE + tinyMCE.execCommand("mceRemoveEditor", false, rteId); - stop: function (event, ui) { + } - // Fade in control when sorting stops - ui.item[0].style.opacity = "1"; + }); + }, - ui.item.offsetParent().find(".mceNoEditor").each(function () { - if ($.inArray($(this).attr("id"), notIncludedRte) < 0) { - // add all dragged's neighbouring RTEs in the new cell - notIncludedRte.splice(0, 0, $(this).attr("id")); - } - }); - $timeout(function () { - // reconstruct the dragged RTE (could be undefined when dragging something else than RTE) - if (draggedRteSettings !== undefined) { - tinyMCE.init(draggedRteSettings); - } + stop: function (event, ui) { + // Fade in control when sorting stops + ui.item[0].style.opacity = "1"; - _.forEach(notIncludedRte, function (id) { - // reset all the other RTEs - if (draggedRteSettings === undefined || id !== draggedRteSettings.id) { - var rteSettings = _.findWhere(tinyMCE.editors, { id: id }).settings; - tinyMCE.execCommand("mceRemoveEditor", false, id); - tinyMCE.init(rteSettings); + ui.item.offsetParent().find(".umb-rte").each(function (key, value) { + var rteId = value.id; + if ($.inArray(rteId, notIncludedRte) < 0) { + // add all dragged's neighbouring RTEs in the new cell + notIncludedRte.splice(0, 0, rteId); } }); - }, 500, false); - - $scope.$apply(function () { - var cell = event.target.getScope_HackForSortable().area; - cell.hasActiveChild = hasActiveChild(cell, cell.controls); - cell.active = false; - }); - } + // reconstruct the dragged RTE (could be undefined when dragging something else than RTE) + if (draggedRteSettings !== undefined) { + tinyMCE.init(draggedRteSettings); + } - }; + _.forEach(notIncludedRte, function (id) { + // reset all the other RTEs + if (draggedRteSettings === undefined || id !== draggedRteSettings.id) { + var rteSettings = _.findWhere(tinyMCE.editors, { id: id }).settings; + tinyMCE.execCommand("mceRemoveEditor", false, id); + tinyMCE.init(rteSettings); + } + }); - $scope.toggleSortMode = function() { - $scope.sortMode = !$scope.sortMode; - if($scope.sortMode) { - $scope.reorderKey = "general_reorderDone"; - } else { - $scope.reorderKey = "general_reorder"; - } - }; + $scope.$apply(function () { - $scope.showReorderButton = function() { - if($scope.model.value && $scope.model.value.sections) { - for(var i = 0; $scope.model.value.sections.length > i; i++) { - var section = $scope.model.value.sections[i]; - if(section.rows && section.rows.length > 0) { - return true; - } + var cell = event.target.getScope_HackForSortable().area; + cell.hasActiveChild = hasActiveChild(cell, cell.controls); + cell.active = false; + }); } - } - }; - - // ********************************************* - // Add items overlay menu - // ********************************************* - $scope.openEditorOverlay = function(event, area, index, key) { - var title = ""; - localizationService.localize("grid_insertControl").then(function(value){ - title = value; - $scope.editorOverlay = { - view: "itempicker", - filter: area.$allowedEditors.length > 15, - title: title, - availableItems: area.$allowedEditors, - event: event, - show: true, - submit: function(model) { - if (model.selectedItem) { - $scope.addControl(model.selectedItem, area, index); - $scope.editorOverlay.show = false; - $scope.editorOverlay = null; - } - } - }; - }); - }; - // ********************************************* - // Template management functions - // ********************************************* + }; - $scope.addTemplate = function (template) { - $scope.model.value = angular.copy(template); + $scope.toggleSortMode = function () { + $scope.sortMode = !$scope.sortMode; + if ($scope.sortMode) { + $scope.reorderKey = "general_reorderDone"; + } else { + $scope.reorderKey = "general_reorder"; + } + }; - //default row data - _.forEach($scope.model.value.sections, function (section) { - $scope.initSection(section); - }); - }; + $scope.showReorderButton = function () { + if ($scope.model.value && $scope.model.value.sections) { + for (var i = 0; $scope.model.value.sections.length > i; i++) { + var section = $scope.model.value.sections[i]; + if (section.rows && section.rows.length > 0) { + return true; + } + } + } + }; + // ********************************************* + // Add items overlay menu + // ********************************************* + $scope.openEditorOverlay = function (event, area, index, key) { + var title = ""; + localizationService.localize("grid_insertControl").then(function (value) { + title = value; + $scope.editorOverlay = { + view: "itempicker", + filter: area.$allowedEditors.length > 15, + title: title, + availableItems: area.$allowedEditors, + event: event, + show: true, + submit: function (model) { + if (model.selectedItem) { + $scope.addControl(model.selectedItem, area, index); + $scope.editorOverlay.show = false; + $scope.editorOverlay = null; + } + } + }; + }); + }; - // ********************************************* - // Row management function - // ********************************************* + // ********************************************* + // Template management functions + // ********************************************* - $scope.clickRow = function(index, rows) { - rows[index].active = true; - }; + $scope.addTemplate = function (template) { + $scope.model.value = angular.copy(template); - $scope.clickOutsideRow = function(index, rows) { - rows[index].active = false; - }; + //default row data + _.forEach($scope.model.value.sections, function (section) { + $scope.initSection(section); + }); + }; - function getAllowedLayouts(section) { - var layouts = $scope.model.config.items.layouts; + // ********************************************* + // Row management function + // ********************************************* - //This will occur if it is a new section which has been - // created from a 'template' - if (section.allowed && section.allowed.length > 0) { - return _.filter(layouts, function (layout) { - return _.indexOf(section.allowed, layout.name) >= 0; - }); - } - else { + $scope.clickRow = function (index, rows) { + rows[index].active = true; + }; + $scope.clickOutsideRow = function (index, rows) { + rows[index].active = false; + }; - return layouts; - } - } + function getAllowedLayouts(section) { - $scope.addRow = function (section, layout, isInit) { + var layouts = $scope.model.config.items.layouts; - //copy the selected layout into the rows collection - var row = angular.copy(layout); + //This will occur if it is a new section which has been + // created from a 'template' + if (section.allowed && section.allowed.length > 0) { + return _.filter(layouts, function (layout) { + return _.indexOf(section.allowed, layout.name) >= 0; + }); + } + else { - // Init row value - row = $scope.initRow(row); - // Push the new row - if (row) { - section.rows.push(row); - } - if (!isInit) { - currentForm.$setDirty(); + return layouts; + } } - $scope.showRowConfigurations = false; + $scope.addRow = function (section, layout, isInit) { - eventsService.emit("grid.rowAdded", { scope: $scope, element: $element, row: row }); + //copy the selected layout into the rows collection + var row = angular.copy(layout); - }; + // Init row value + row = $scope.initRow(row); - $scope.removeRow = function (section, $index) { - if (section.rows.length > 0) { - section.rows.splice($index, 1); - $scope.currentRow = null; - $scope.openRTEToolbarId = null; - currentForm.$setDirty(); - } + // Push the new row + if (row) { + section.rows.push(row); + } + if (!isInit) { + currentForm.$setDirty(); + } - if(section.rows.length === 0) { - $scope.showRowConfigurations = true; - } - }; + $scope.showRowConfigurations = false; - var shouldApply = function(item, itemType, gridItem) { - if (item.applyTo === undefined || item.applyTo === null || item.applyTo === "") { - return true; - } + eventsService.emit("grid.rowAdded", { scope: $scope, element: $element, row: row }); - if (typeof (item.applyTo) === "string") { - return item.applyTo === itemType; - } + }; - if (itemType === "row") { - if (item.applyTo.row === undefined) { - return false; + $scope.removeRow = function (section, $index) { + if (section.rows.length > 0) { + section.rows.splice($index, 1); + $scope.currentRow = null; + $scope.openRTEToolbarId = null; + currentForm.$setDirty(); } - if (item.applyTo.row === null || item.applyTo.row === "") { - return true; - } - var rows = item.applyTo.row.split(','); - return _.indexOf(rows, gridItem.name) !== -1; - } else if (itemType === "cell") { - if (item.applyTo.cell === undefined) { - return false; + + if (section.rows.length === 0) { + $scope.showRowConfigurations = true; } - if (item.applyTo.cell === null || item.applyTo.cell === "") { + }; + + var shouldApply = function (item, itemType, gridItem) { + if (item.applyTo === undefined || item.applyTo === null || item.applyTo === "") { return true; } - var cells = item.applyTo.cell.split(','); - var cellSize = gridItem.grid.toString(); - return _.indexOf(cells, cellSize) !== -1; - } - } - - $scope.editGridItemSettings = function (gridItem, itemType) { - - placeHolder = "{0}"; - - var styles, config; - if (itemType === 'control') { - styles = null; - config = angular.copy(gridItem.editor.config.settings); - } else { - styles = _.filter(angular.copy($scope.model.config.items.styles), function (item) { return shouldApply(item, itemType, gridItem); }); - config = _.filter(angular.copy($scope.model.config.items.config), function (item) { return shouldApply(item, itemType, gridItem); }); - } - if(angular.isObject(gridItem.config)){ - _.each(config, function(cfg){ - var val = gridItem.config[cfg.key]; - if(val){ - cfg.value = stripModifier(val, cfg.modifier); - } - }); - } + if (typeof (item.applyTo) === "string") { + return item.applyTo === itemType; + } - if(angular.isObject(gridItem.styles)){ - _.each(styles, function(style){ - var val = gridItem.styles[style.key]; - if(val){ - style.value = stripModifier(val, style.modifier); + if (itemType === "row") { + if (item.applyTo.row === undefined) { + return false; } - }); + if (item.applyTo.row === null || item.applyTo.row === "") { + return true; + } + var rows = item.applyTo.row.split(','); + return _.indexOf(rows, gridItem.name) !== -1; + } else if (itemType === "cell") { + if (item.applyTo.cell === undefined) { + return false; + } + if (item.applyTo.cell === null || item.applyTo.cell === "") { + return true; + } + var cells = item.applyTo.cell.split(','); + var cellSize = gridItem.grid.toString(); + return _.indexOf(cells, cellSize) !== -1; + } } - $scope.gridItemSettingsDialog = {}; - $scope.gridItemSettingsDialog.view = "views/propertyeditors/grid/dialogs/config.html"; - $scope.gridItemSettingsDialog.title = "Settings"; - $scope.gridItemSettingsDialog.styles = styles; - $scope.gridItemSettingsDialog.config = config; + $scope.editGridItemSettings = function (gridItem, itemType) { - $scope.gridItemSettingsDialog.show = true; + placeHolder = "{0}"; - $scope.gridItemSettingsDialog.submit = function(model) { + var styles, config; + if (itemType === 'control') { + styles = null; + config = angular.copy(gridItem.editor.config.settings); + } else { + styles = _.filter(angular.copy($scope.model.config.items.styles), function (item) { return shouldApply(item, itemType, gridItem); }); + config = _.filter(angular.copy($scope.model.config.items.config), function (item) { return shouldApply(item, itemType, gridItem); }); + } - var styleObject = {}; - var configObject = {}; + if (angular.isObject(gridItem.config)) { + _.each(config, function (cfg) { + var val = gridItem.config[cfg.key]; + if (val) { + cfg.value = stripModifier(val, cfg.modifier); + } + }); + } - _.each(model.styles, function(style){ - if(style.value){ - styleObject[style.key] = addModifier(style.value, style.modifier); - } - }); - _.each(model.config, function (cfg) { - if (cfg.value) { - configObject[cfg.key] = addModifier(cfg.value, cfg.modifier); - } - }); + if (angular.isObject(gridItem.styles)) { + _.each(styles, function (style) { + var val = gridItem.styles[style.key]; + if (val) { + style.value = stripModifier(val, style.modifier); + } + }); + } - gridItem.styles = styleObject; - gridItem.config = configObject; - gridItem.hasConfig = gridItemHasConfig(styleObject, configObject); + $scope.gridItemSettingsDialog = {}; + $scope.gridItemSettingsDialog.view = "views/propertyeditors/grid/dialogs/config.html"; + $scope.gridItemSettingsDialog.title = "Settings"; + $scope.gridItemSettingsDialog.styles = styles; + $scope.gridItemSettingsDialog.config = config; - currentForm.$setDirty(); + $scope.gridItemSettingsDialog.show = true; - $scope.gridItemSettingsDialog.show = false; - $scope.gridItemSettingsDialog = null; - }; + $scope.gridItemSettingsDialog.submit = function (model) { - $scope.gridItemSettingsDialog.close = function(oldModel) { - $scope.gridItemSettingsDialog.show = false; - $scope.gridItemSettingsDialog = null; - }; + var styleObject = {}; + var configObject = {}; - }; + _.each(model.styles, function (style) { + if (style.value) { + styleObject[style.key] = addModifier(style.value, style.modifier); + } + }); + _.each(model.config, function (cfg) { + if (cfg.value) { + configObject[cfg.key] = addModifier(cfg.value, cfg.modifier); + } + }); - function stripModifier(val, modifier) { - if (!val || !modifier || modifier.indexOf(placeHolder) < 0) { - return val; - } else { - var paddArray = modifier.split(placeHolder); - if(paddArray.length == 1){ - if (modifier.indexOf(placeHolder) === 0) { - return val.slice(0, -paddArray[0].length); - } else { - return val.slice(paddArray[0].length, 0); - } + gridItem.styles = styleObject; + gridItem.config = configObject; + gridItem.hasConfig = gridItemHasConfig(styleObject, configObject); + + currentForm.$setDirty(); + + $scope.gridItemSettingsDialog.show = false; + $scope.gridItemSettingsDialog = null; + }; + + $scope.gridItemSettingsDialog.close = function (oldModel) { + $scope.gridItemSettingsDialog.show = false; + $scope.gridItemSettingsDialog = null; + }; + + }; + + function stripModifier(val, modifier) { + if (!val || !modifier || modifier.indexOf(placeHolder) < 0) { + return val; } else { - if (paddArray[1].length === 0) { - return val.slice(paddArray[0].length); + var paddArray = modifier.split(placeHolder); + if (paddArray.length == 1) { + if (modifier.indexOf(placeHolder) === 0) { + return val.slice(0, -paddArray[0].length); + } else { + return val.slice(paddArray[0].length, 0); + } + } else { + if (paddArray[1].length === 0) { + return val.slice(paddArray[0].length); + } + return val.slice(paddArray[0].length, -paddArray[1].length); } - return val.slice(paddArray[0].length, -paddArray[1].length); } } - } - var addModifier = function(val, modifier){ - if (!modifier || modifier.indexOf(placeHolder) < 0) { - return val; - } else { - return modifier.replace(placeHolder, val); - } - }; + var addModifier = function (val, modifier) { + if (!modifier || modifier.indexOf(placeHolder) < 0) { + return val; + } else { + return modifier.replace(placeHolder, val); + } + }; - function gridItemHasConfig(styles, config) { + function gridItemHasConfig(styles, config) { + + if (_.isEmpty(styles) && _.isEmpty(config)) { + return false; + } else { + return true; + } - if(_.isEmpty(styles) && _.isEmpty(config)) { - return false; - } else { - return true; } - } + // ********************************************* + // Area management functions + // ********************************************* - // ********************************************* - // Area management functions - // ********************************************* + $scope.clickCell = function (index, cells, row) { + cells[index].active = true; + row.hasActiveChild = true; + }; - $scope.clickCell = function(index, cells, row) { - cells[index].active = true; - row.hasActiveChild = true; - }; + $scope.clickOutsideCell = function (index, cells, row) { + cells[index].active = false; + row.hasActiveChild = hasActiveChild(row, cells); + }; - $scope.clickOutsideCell = function(index, cells, row) { - cells[index].active = false; - row.hasActiveChild = hasActiveChild(row, cells); - }; + $scope.cellPreview = function (cell) { + if (cell && cell.$allowedEditors) { + var editor = cell.$allowedEditors[0]; + return editor.icon; + } else { + return "icon-layout"; + } + }; - $scope.cellPreview = function (cell) { - if (cell && cell.$allowedEditors) { - var editor = cell.$allowedEditors[0]; - return editor.icon; - } else { - return "icon-layout"; - } - }; + // ********************************************* + // Control management functions + // ********************************************* + $scope.clickControl = function (index, controls, cell) { + controls[index].active = true; + cell.hasActiveChild = true; + }; - // ********************************************* - // Control management functions - // ********************************************* - $scope.clickControl = function (index, controls, cell) { - controls[index].active = true; - cell.hasActiveChild = true; - }; + $scope.clickOutsideControl = function (index, controls, cell) { + controls[index].active = false; + cell.hasActiveChild = hasActiveChild(cell, controls); + }; - $scope.clickOutsideControl = function (index, controls, cell) { - controls[index].active = false; - cell.hasActiveChild = hasActiveChild(cell, controls); - }; + function hasActiveChild(item, children) { - function hasActiveChild(item, children) { + var activeChild = false; - var activeChild = false; + for (var i = 0; children.length > i; i++) { + var child = children[i]; - for(var i = 0; children.length > i; i++) { - var child = children[i]; + if (child.active) { + activeChild = true; + } + } - if(child.active) { - activeChild = true; + if (activeChild) { + return true; } - } - if(activeChild) { - return true; } - } + var guid = (function () { + function s4() { + return Math.floor((1 + Math.random()) * 0x10000) + .toString(16) + .substring(1); + } + return function () { + return s4() + s4() + "-" + s4() + "-" + s4() + "-" + + s4() + "-" + s4() + s4() + s4(); + }; + })(); - var guid = (function () { - function s4() { - return Math.floor((1 + Math.random()) * 0x10000) - .toString(16) - .substring(1); - } - return function () { - return s4() + s4() + "-" + s4() + "-" + s4() + "-" + - s4() + "-" + s4() + s4() + s4(); + $scope.setUniqueId = function (cell, index) { + return guid(); }; - })(); - $scope.setUniqueId = function (cell, index) { - return guid(); - }; + $scope.addControl = function (editor, cell, index, initialize) { - $scope.addControl = function (editor, cell, index, initialize) { + initialize = (initialize !== false); - initialize = (initialize !== false); + var newControl = { + value: null, + editor: editor, + $initializing: initialize + }; + + if (index === undefined) { + index = cell.controls.length; + } + + newControl.active = true; + + //populate control + $scope.initControl(newControl, index + 1); + + cell.controls.push(newControl); + + eventsService.emit("grid.itemAdded", { scope: $scope, element: $element, cell: cell, item: newControl }); - var newControl = { - value: null, - editor: editor, - $initializing: initialize }; - if (index === undefined) { - index = cell.controls.length; - } + $scope.addTinyMce = function (cell) { + var rte = $scope.getEditor("rte"); + $scope.addControl(rte, cell); + }; - newControl.active = true; + $scope.getEditor = function (alias) { + return _.find($scope.availableEditors, function (editor) { return editor.alias === alias; }); + }; - //populate control - $scope.initControl(newControl, index + 1); + $scope.removeControl = function (cell, $index) { + $scope.currentControl = null; + cell.controls.splice($index, 1); + }; - cell.controls.push(newControl); + $scope.percentage = function (spans) { + return ((spans / $scope.model.config.items.columns) * 100).toFixed(8); + }; - eventsService.emit("grid.itemAdded", { scope: $scope, element: $element, cell: cell, item: newControl }); - }; + $scope.clearPrompt = function (scopedObject, e) { + scopedObject.deletePrompt = false; + e.preventDefault(); + e.stopPropagation(); + }; - $scope.addTinyMce = function (cell) { - var rte = $scope.getEditor("rte"); - $scope.addControl(rte, cell); - }; + $scope.togglePrompt = function (scopedObject) { + scopedObject.deletePrompt = !scopedObject.deletePrompt; + }; - $scope.getEditor = function (alias) { - return _.find($scope.availableEditors, function (editor) { return editor.alias === alias; }); - }; + $scope.hidePrompt = function (scopedObject) { + scopedObject.deletePrompt = false; + }; - $scope.removeControl = function (cell, $index) { - $scope.currentControl = null; - cell.controls.splice($index, 1); - }; - - $scope.percentage = function (spans) { - return ((spans / $scope.model.config.items.columns) * 100).toFixed(8); - }; - - - $scope.clearPrompt = function (scopedObject, e) { - scopedObject.deletePrompt = false; - e.preventDefault(); - e.stopPropagation(); - }; - - $scope.togglePrompt = function (scopedObject) { - scopedObject.deletePrompt = !scopedObject.deletePrompt; - }; - - $scope.hidePrompt = function (scopedObject) { - scopedObject.deletePrompt = false; - }; - - $scope.toggleAddRow = function() { - $scope.showRowConfigurations = !$scope.showRowConfigurations; - }; - - - // ********************************************* - // Initialization - // these methods are called from ng-init on the template - // so we can controll their first load data - // - // intialization sets non-saved data like percentage sizing, allowed editors and - // other data that should all be pre-fixed with $ to strip it out on save - // ********************************************* - - // ********************************************* - // Init template + sections - // ********************************************* - $scope.initContent = function () { - var clear = true; - - //settings indicator shortcut - if (($scope.model.config.items.config && $scope.model.config.items.config.length > 0) || ($scope.model.config.items.styles && $scope.model.config.items.styles.length > 0)) { - $scope.hasSettings = true; - } + $scope.toggleAddRow = function () { + $scope.showRowConfigurations = !$scope.showRowConfigurations; + }; - //ensure the grid has a column value set, - //if nothing is found, set it to 12 - if (!$scope.model.config.items.columns){ - $scope.model.config.items.columns = 12; - } else if (angular.isString($scope.model.config.items.columns)) { - $scope.model.config.items.columns = parseInt($scope.model.config.items.columns); - } - if ($scope.model.value && $scope.model.value.sections && $scope.model.value.sections.length > 0 && $scope.model.value.sections[0].rows && $scope.model.value.sections[0].rows.length > 0) { + // ********************************************* + // Initialization + // these methods are called from ng-init on the template + // so we can controll their first load data + // + // intialization sets non-saved data like percentage sizing, allowed editors and + // other data that should all be pre-fixed with $ to strip it out on save + // ********************************************* - if ($scope.model.value.name && angular.isArray($scope.model.config.items.templates)) { + // ********************************************* + // Init template + sections + // ********************************************* + $scope.initContent = function () { + var clear = true; - //This will occur if it is an existing value, in which case - // we need to determine which layout was applied by looking up - // the name - // TODO: We need to change this to an immutable ID!! + //settings indicator shortcut + if (($scope.model.config.items.config && $scope.model.config.items.config.length > 0) || ($scope.model.config.items.styles && $scope.model.config.items.styles.length > 0)) { + $scope.hasSettings = true; + } - var found = _.find($scope.model.config.items.templates, function (t) { - return t.name === $scope.model.value.name; - }); + //ensure the grid has a column value set, + //if nothing is found, set it to 12 + if (!$scope.model.config.items.columns) { + $scope.model.config.items.columns = 12; + } else if (angular.isString($scope.model.config.items.columns)) { + $scope.model.config.items.columns = parseInt($scope.model.config.items.columns); + } + + if ($scope.model.value && $scope.model.value.sections && $scope.model.value.sections.length > 0 && $scope.model.value.sections[0].rows && $scope.model.value.sections[0].rows.length > 0) { - if (found && angular.isArray(found.sections) && found.sections.length === $scope.model.value.sections.length) { + if ($scope.model.value.name && angular.isArray($scope.model.config.items.templates)) { - //Cool, we've found the template associated with our current value with matching sections counts, now we need to - // merge this template data on to our current value (as if it was new) so that we can preserve what is and isn't - // allowed for this template based on the current config. + //This will occur if it is an existing value, in which case + // we need to determine which layout was applied by looking up + // the name + // TODO: We need to change this to an immutable ID!! - _.each(found.sections, function (templateSection, index) { - angular.extend($scope.model.value.sections[index], angular.copy(templateSection)); + var found = _.find($scope.model.config.items.templates, function (t) { + return t.name === $scope.model.value.name; }); - } - } + if (found && angular.isArray(found.sections) && found.sections.length === $scope.model.value.sections.length) { - _.forEach($scope.model.value.sections, function (section, index) { + //Cool, we've found the template associated with our current value with matching sections counts, now we need to + // merge this template data on to our current value (as if it was new) so that we can preserve what is and isn't + // allowed for this template based on the current config. - if (section.grid > 0) { - $scope.initSection(section); + _.each(found.sections, function (templateSection, index) { + angular.extend($scope.model.value.sections[index], angular.copy(templateSection)); + }); - //we do this to ensure that the grid can be reset by deleting the last row - if (section.rows.length > 0) { - clear = false; } - } else { - $scope.model.value.sections.splice(index, 1); } - }); - } else if ($scope.model.config.items.templates && $scope.model.config.items.templates.length === 1) { - $scope.addTemplate($scope.model.config.items.templates[0]); - clear = false; - } - if (clear) { - $scope.model.value = undefined; - } - }; + _.forEach($scope.model.value.sections, function (section, index) { - $scope.initSection = function (section) { - section.$percentage = $scope.percentage(section.grid); + if (section.grid > 0) { + $scope.initSection(section); - section.$allowedLayouts = getAllowedLayouts(section); + //we do this to ensure that the grid can be reset by deleting the last row + if (section.rows.length > 0) { + clear = false; + } + } else { + $scope.model.value.sections.splice(index, 1); + } + }); + } else if ($scope.model.config.items.templates && $scope.model.config.items.templates.length === 1) { + $scope.addTemplate($scope.model.config.items.templates[0]); + clear = false; + } - if (!section.rows || section.rows.length === 0) { - section.rows = []; - if(section.$allowedLayouts.length === 1){ - $scope.addRow(section, section.$allowedLayouts[0], true); + if (clear) { + $scope.model.value = undefined; } - } else { - _.forEach(section.rows, function (row, index) { - if (!row.$initialized) { - var initd = $scope.initRow(row); + }; - //if init fails, remove - if (!initd) { - section.rows.splice(index, 1); - } else { - section.rows[index] = initd; - } + $scope.initSection = function (section) { + section.$percentage = $scope.percentage(section.grid); + + section.$allowedLayouts = getAllowedLayouts(section); + + if (!section.rows || section.rows.length === 0) { + section.rows = []; + if (section.$allowedLayouts.length === 1) { + $scope.addRow(section, section.$allowedLayouts[0], true); } - }); + } else { + _.forEach(section.rows, function (row, index) { + if (!row.$initialized) { + var initd = $scope.initRow(row); + + //if init fails, remove + if (!initd) { + section.rows.splice(index, 1); + } else { + section.rows[index] = initd; + } + } + }); - // if there is more than one row added - hide row add tools - $scope.showRowConfigurations = false; - } - }; + // if there is more than one row added - hide row add tools + $scope.showRowConfigurations = false; + } + }; - // ********************************************* - // Init layout / row - // ********************************************* - $scope.initRow = function (row) { - - //merge the layout data with the original config data - //if there are no config info on this, splice it out - var original = _.find($scope.model.config.items.layouts, function (o) { return o.name === row.name; }); + // ********************************************* + // Init layout / row + // ********************************************* + $scope.initRow = function (row) { - if (!original) { - return null; - } else { - //make a copy to not touch the original config - original = angular.copy(original); - original.styles = row.styles; - original.config = row.config; - original.hasConfig = gridItemHasConfig(row.styles, row.config); + //merge the layout data with the original config data + //if there are no config info on this, splice it out + var original = _.find($scope.model.config.items.layouts, function (o) { return o.name === row.name; }); + if (!original) { + return null; + } else { + //make a copy to not touch the original config + original = angular.copy(original); + original.styles = row.styles; + original.config = row.config; + original.hasConfig = gridItemHasConfig(row.styles, row.config); - //sync area configuration - _.each(original.areas, function (area, areaIndex) { + //sync area configuration + _.each(original.areas, function (area, areaIndex) { - if (area.grid > 0) { - var currentArea = row.areas[areaIndex]; - if (currentArea) { - area.config = currentArea.config; - area.styles = currentArea.styles; - area.hasConfig = gridItemHasConfig(currentArea.styles, currentArea.config); - } + if (area.grid > 0) { + var currentArea = row.areas[areaIndex]; - //set editor permissions - if (!area.allowed || area.allowAll === true) { - area.$allowedEditors = $scope.availableEditors; - area.$allowsRTE = true; - } else { - area.$allowedEditors = _.filter($scope.availableEditors, function (editor) { - return _.indexOf(area.allowed, editor.alias) >= 0; - }); + if (currentArea) { + area.config = currentArea.config; + area.styles = currentArea.styles; + area.hasConfig = gridItemHasConfig(currentArea.styles, currentArea.config); + } - if (_.indexOf(area.allowed, "rte") >= 0) { + //set editor permissions + if (!area.allowed || area.allowAll === true) { + area.$allowedEditors = $scope.availableEditors; area.$allowsRTE = true; + } else { + area.$allowedEditors = _.filter($scope.availableEditors, function (editor) { + return _.indexOf(area.allowed, editor.alias) >= 0; + }); + + if (_.indexOf(area.allowed, "rte") >= 0) { + area.$allowsRTE = true; + } } - } - //copy over existing controls into the new areas - if (row.areas.length > areaIndex && row.areas[areaIndex].controls) { - area.controls = currentArea.controls; + //copy over existing controls into the new areas + if (row.areas.length > areaIndex && row.areas[areaIndex].controls) { + area.controls = currentArea.controls; - _.forEach(area.controls, function (control, controlIndex) { - $scope.initControl(control, controlIndex); - }); + _.forEach(area.controls, function (control, controlIndex) { + $scope.initControl(control, controlIndex); + }); - } else { - //if empty - area.controls = []; + } else { + //if empty + area.controls = []; - //if only one allowed editor - if(area.$allowedEditors.length === 1){ - $scope.addControl(area.$allowedEditors[0], area, 0, false); + //if only one allowed editor + if (area.$allowedEditors.length === 1) { + $scope.addControl(area.$allowedEditors[0], area, 0, false); + } } - } - //set width - area.$percentage = $scope.percentage(area.grid); - area.$uniqueId = $scope.setUniqueId(); + //set width + area.$percentage = $scope.percentage(area.grid); + area.$uniqueId = $scope.setUniqueId(); - } else { - original.areas.splice(areaIndex, 1); - } - }); + } else { + original.areas.splice(areaIndex, 1); + } + }); - //replace the old row - original.$initialized = true; + //replace the old row + original.$initialized = true; - //set a disposable unique ID - original.$uniqueId = $scope.setUniqueId(); + //set a disposable unique ID + original.$uniqueId = $scope.setUniqueId(); - //set a no disposable unique ID (util for row styling) - original.id = !row.id ? $scope.setUniqueId() : row.id; + //set a no disposable unique ID (util for row styling) + original.id = !row.id ? $scope.setUniqueId() : row.id; - return original; - } + return original; + } - }; + }; - // ********************************************* - // Init control - // ********************************************* + // ********************************************* + // Init control + // ********************************************* - $scope.initControl = function (control, index) { - control.$index = index; - control.$uniqueId = $scope.setUniqueId(); + $scope.initControl = function (control, index) { + control.$index = index; + control.$uniqueId = $scope.setUniqueId(); - //error handling in case of missing editor.. - //should only happen if stripped earlier - if (!control.editor) { - control.$editorPath = "views/propertyeditors/grid/editors/error.html"; - } + //error handling in case of missing editor.. + //should only happen if stripped earlier + if (!control.editor) { + control.$editorPath = "views/propertyeditors/grid/editors/error.html"; + } - if (!control.$editorPath) { - var editorConfig = $scope.getEditor(control.editor.alias); + if (!control.$editorPath) { + var editorConfig = $scope.getEditor(control.editor.alias); - if (editorConfig) { - control.editor = editorConfig; + if (editorConfig) { + control.editor = editorConfig; - //if its an absolute path - if (control.editor.view.startsWith("/") || control.editor.view.startsWith("~/")) { - control.$editorPath = umbRequestHelper.convertVirtualToAbsolutePath(control.editor.view); + //if its an absolute path + if (control.editor.view.startsWith("/") || control.editor.view.startsWith("~/")) { + control.$editorPath = umbRequestHelper.convertVirtualToAbsolutePath(control.editor.view); + } + else { + //use convention + control.$editorPath = "views/propertyeditors/grid/editors/" + control.editor.view + ".html"; + } } else { - //use convention - control.$editorPath = "views/propertyeditors/grid/editors/" + control.editor.view + ".html"; + control.$editorPath = "views/propertyeditors/grid/editors/error.html"; } } - else { - control.$editorPath = "views/propertyeditors/grid/editors/error.html"; - } - } - }; + }; - gridService.getGridEditors().then(function (response) { - $scope.availableEditors = response.data; + gridService.getGridEditors().then(function (response) { + $scope.availableEditors = response.data; - //Localize the grid editor names - angular.forEach($scope.availableEditors, function (value, key) { - //If no translation is provided, keep using the editor name from the manifest - if (localizationService.dictionary.hasOwnProperty("grid_" + value.alias)) { - localizationService.localize("grid_" + value.alias).then(function(v){ - value.name = v; - }); - } - }); + //Localize the grid editor names + angular.forEach($scope.availableEditors, function (value, key) { + //If no translation is provided, keep using the editor name from the manifest + if (localizationService.dictionary.hasOwnProperty("grid_" + value.alias)) { + localizationService.localize("grid_" + value.alias).then(function (v) { + value.name = v; + }); + } + }); - $scope.contentReady = true; + $scope.contentReady = true; - // ********************************************* - // Init grid - // ********************************************* + // ********************************************* + // Init grid + // ********************************************* - eventsService.emit("grid.initializing", { scope: $scope, element: $element }); + eventsService.emit("grid.initializing", { scope: $scope, element: $element }); - $scope.initContent(); + $scope.initContent(); - eventsService.emit("grid.initialized", { scope: $scope, element: $element }); + eventsService.emit("grid.initialized", { scope: $scope, element: $element }); - }); + }); - //Clean the grid value before submitting to the server, we don't need - // all of that grid configuration in the value to be stored!! All of that - // needs to be merged in at runtime to ensure that the real config values are used - // if they are ever updated. - - var unsubscribe = $scope.$on("formSubmitting", function (e, args) { - - if (args.action === "save" && $scope.model.value && $scope.model.value.sections) { - _.each($scope.model.value.sections, function(section) { - if (section.rows) { - _.each(section.rows, function (row) { - if (row.areas) { - _.each(row.areas, function (area) { - - //Remove the 'editors' - these are the allowed editors, these will - // be injected at runtime to this editor, it should not be persisted - - if (area.editors) { - delete area.editors; - } - - if (area.controls) { - _.each(area.controls, function (control) { - if (control.editor) { - //replace - var alias = control.editor.alias; - control.editor = { - alias: alias - }; - } - }); - } - }); - } - }); - } - }); - } - }); + //Clean the grid value before submitting to the server, we don't need + // all of that grid configuration in the value to be stored!! All of that + // needs to be merged in at runtime to ensure that the real config values are used + // if they are ever updated. + + var unsubscribe = $scope.$on("formSubmitting", function (e, args) { + + if (args.action === "save" && $scope.model.value && $scope.model.value.sections) { + _.each($scope.model.value.sections, function (section) { + if (section.rows) { + _.each(section.rows, function (row) { + if (row.areas) { + _.each(row.areas, function (area) { + + //Remove the 'editors' - these are the allowed editors, these will + // be injected at runtime to this editor, it should not be persisted + + if (area.editors) { + delete area.editors; + } + + if (area.controls) { + _.each(area.controls, function (control) { + if (control.editor) { + //replace + var alias = control.editor.alias; + control.editor = { + alias: alias + }; + } + }); + } + }); + } + }); + } + }); + } + }); - //when the scope is destroyed we need to unsubscribe - $scope.$on("$destroy", function () { - unsubscribe(); - }); + //when the scope is destroyed we need to unsubscribe + $scope.$on("$destroy", function () { + unsubscribe(); + }); - }); + }); 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 f0171e2d00b4..068a60462c15 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 @@ -1,6 +1,6 @@
- + -
+
- {{control.editor.name}} + {{control.editor.name}}
@@ -199,25 +199,24 @@
-
- - - -
+
+ + + +
-
+
- -
+
-
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.controller.js index 60d762738fdd..4934adb5dd52 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.controller.js @@ -13,25 +13,11 @@ function textAreaController($scope) { $scope.model.maxlength = false; if ($scope.model.config && $scope.model.config.maxChars) { $scope.model.maxlength = true; - if($scope.model.value == undefined) { - $scope.model.count = ($scope.model.config.maxChars * 1); - } else { - $scope.model.count = ($scope.model.config.maxChars * 1) - $scope.model.value.length; - } } - - $scope.model.change = function() { - if ($scope.model.config && $scope.model.config.maxChars) { - if($scope.model.value == undefined) { - $scope.model.count = ($scope.model.config.maxChars * 1); - } else { - $scope.model.count = ($scope.model.config.maxChars * 1) - $scope.model.value.length; - } - if($scope.model.count < 0) { - $scope.model.value = $scope.model.value.substring(0, ($scope.model.config.maxChars * 1)); - $scope.model.count = 0; - } - } + + $scope.model.change = function () { + $scope.model.count = $scope.model.value.length; } + $scope.model.change(); } -angular.module('umbraco').controller("Umbraco.PropertyEditors.textAreaController", textAreaController); \ No newline at end of file +angular.module('umbraco').controller("Umbraco.PropertyEditors.textAreaController", textAreaController); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.html index 2fdca5d65455..1be37d92d627 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.html @@ -7,9 +7,12 @@ {{textareaFieldForm.textarea.errorMsg}} -
- {{model.count}} - characters left +
+ %0% characters left.
+
+ Maximum %0% characters, %1% too many. +
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.controller.js index 734903e46c5e..4ab827db592e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.controller.js @@ -4,39 +4,18 @@ function textboxController($scope) { if (!$scope.model.config) { $scope.model.config = {}; } - - $scope.model.maxlength = false; - if ($scope.model.config && $scope.model.config.maxChars) { - $scope.model.maxlength = true; - } - + if (!$scope.model.config.maxChars) { // 500 is the maximum number that can be stored // in the database, so set it to the max, even // if no max is specified in the config $scope.model.config.maxChars = 500; } - - if ($scope.model.maxlength) { - if ($scope.model.value === undefined) { - $scope.model.count = ($scope.model.config.maxChars * 1); - } else { - $scope.model.count = ($scope.model.config.maxChars * 1) - $scope.model.value.length; - } - } - + $scope.model.change = function () { - if ($scope.model.config && $scope.model.config.maxChars) { - if ($scope.model.value === undefined) { - $scope.model.count = ($scope.model.config.maxChars * 1); - } else { - $scope.model.count = ($scope.model.config.maxChars * 1) - $scope.model.value.length; - } - if ($scope.model.count < 0) { - $scope.model.value = $scope.model.value.substring(0, ($scope.model.config.maxChars * 1)); - $scope.model.count = 0; - } - } + $scope.model.count = $scope.model.value.length; } + $scope.model.change(); + } angular.module('umbraco').controller("Umbraco.PropertyEditors.textboxController", textboxController); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.html index 6f6ed6bdf64c..92f02b9f5b4b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.html @@ -12,9 +12,12 @@ Required -
- {{model.count}} - characters left +
+ %0% characters left.
+
+ Maximum %0% characters, %1% too many. +
+
diff --git a/src/Umbraco.Web.UI/Umbraco/Install/Views/Index.cshtml b/src/Umbraco.Web.UI/Umbraco/Install/Views/Index.cshtml index 1d397bfd012f..e74dbea21794 100644 --- a/src/Umbraco.Web.UI/Umbraco/Install/Views/Index.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Install/Views/Index.cshtml @@ -7,7 +7,7 @@ - + @@ -66,8 +66,8 @@ var Umbraco = {}; Umbraco.Sys = {}; Umbraco.Sys.ServerVariables = { - "installApiBaseUrl": "@ViewBag.InstallApiBaseUrl", - "umbracoBaseUrl": "@ViewBag.UmbracoBaseFolder" + "installApiBaseUrl": "@ViewData.GetInstallApiBaseUrl()", + "umbracoBaseUrl": "@ViewData.GetUmbracoBaseFolder()" }; diff --git a/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml index fba9a837892c..b7c1e6540cf8 100644 --- a/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/Views/AuthorizeUpgrade.cshtml @@ -51,7 +51,7 @@ @{ var externalLoginUrl = Url.Action("ExternalLogin", "BackOffice", new { - area = ViewBag.UmbracoPath, + area = ViewData.GetUmbracoPath(), //Custom redirect URL since we don't want to just redirect to the back office since this is for authing upgrades redirectUrl = Url.Action("AuthorizeUpgrade", "BackOffice") }); @@ -61,7 +61,7 @@