diff --git a/src/Umbraco.Core/Configuration/Models/RichTextEditorSettings.cs b/src/Umbraco.Core/Configuration/Models/RichTextEditorSettings.cs index 8432c8dce0..af6860412c 100644 --- a/src/Umbraco.Core/Configuration/Models/RichTextEditorSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/RichTextEditorSettings.cs @@ -8,7 +8,7 @@ namespace Umbraco.Cms.Core.Configuration.Models; public class RichTextEditorSettings { internal const string StaticValidElements = - "+a[id|style|rel|data-id|data-udi|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-s[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|reversed|start|style|type],-ul[class|style],-li[class|style],br[class],img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align|umbracoorgwidth|umbracoorgheight|onresize|onresizestart|onresizeend|rel|data-id],-sub[style|class],-sup[style|class],-blockquote[dir|style|class],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align|style],-h2[id|dir|class|align|style],-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],small[class|style],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*],figure,figcaption,video[*],audio[*],picture[*],source[*],canvas[*]"; + "+a[id|style|rel|data-id|data-udi|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-s[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|reversed|start|style|type],-ul[class|style],-li[class|style],br[class],img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align|umbracoorgwidth|umbracoorgheight|onresize|onresizestart|onresizeend|rel|data-id],-sub[style|class],-sup[style|class],-blockquote[dir|style|class],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align|style],-h2[id|dir|class|align|style],-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],small[class|style],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*],figure,figcaption,cite,video[*],audio[*],picture[*],source[*],canvas[*]"; internal const string StaticInvalidElements = "font"; diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/ro.xml b/src/Umbraco.Core/EmbeddedResources/Lang/ro.xml index 5dda77d477..62d8d7c0b6 100644 --- a/src/Umbraco.Core/EmbeddedResources/Lang/ro.xml +++ b/src/Umbraco.Core/EmbeddedResources/Lang/ro.xml @@ -15,4 +15,43 @@ Traduceri Utilizatori + + Conţinut + Șabloane de conținut + Media + Cache Browser + Cos de gunoi + Pachete create + Tipuri de date + Dicţionar + Pachete instalate + Instalare skin + Instalați trusa de pornire + Limbi + Instalați pachetul local + Macros + Tipuri media + Membrii + Grupuri de membri + Rolurile membrilor + Tipuri de membri + Tipuri de documente + Tipuri de relații + Pachete + Pachete + Vizualizări parțiale + Vizualizare parțială fișiere macro + Instalați din depozit + Instalați pista + Module piste + Fișiere de scriptare + Scripturi + Stylesheets + Șabloane + Vizualizator de jurnal + Utilizatori + Setări + Modelare + Terț + diff --git a/src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs b/src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs index f2a3afdbe3..f860bafd2c 100644 --- a/src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/ConfigurationEditorOfTConfiguration.cs @@ -1,4 +1,4 @@ -// Copyright (c) Umbraco. +// Copyright (c) Umbraco. // See LICENSE for more details. using System.Reflection; @@ -125,6 +125,7 @@ public abstract class ConfigurationEditor : ConfigurationEditor PropertyType = property.PropertyType, Description = attribute.Description, HideLabel = attribute.HideLabel, + SortOrder = attribute.SortOrder, View = attributeView, }; @@ -150,6 +151,8 @@ public abstract class ConfigurationEditor : ConfigurationEditor field.PropertyName = property.Name; field.PropertyType = property.PropertyType; + field.SortOrder = attribute.SortOrder; + if (!string.IsNullOrWhiteSpace(attribute.Key)) { field.Key = attribute.Key; @@ -182,6 +185,6 @@ public abstract class ConfigurationEditor : ConfigurationEditor } } - return fields; + return fields.OrderBy(x => x.SortOrder).ToList(); } } diff --git a/src/Umbraco.Core/PropertyEditors/ConfigurationField.cs b/src/Umbraco.Core/PropertyEditors/ConfigurationField.cs index 40bd0c0ca9..def2135bbd 100644 --- a/src/Umbraco.Core/PropertyEditors/ConfigurationField.cs +++ b/src/Umbraco.Core/PropertyEditors/ConfigurationField.cs @@ -1,4 +1,5 @@ -using System.Runtime.Serialization; +using System.Runtime.Serialization; +using Umbraco.Cms.Core.Models.ContentEditing; using Umbraco.Extensions; namespace Umbraco.Cms.Core.PropertyEditors; @@ -47,6 +48,7 @@ public class ConfigurationField HideLabel = attribute.HideLabel; Key = attribute.Key; View = attribute.View; + SortOrder = attribute.SortOrder; } /// @@ -77,6 +79,12 @@ public class ConfigurationField [DataMember(Name = "description")] public string? Description { get; set; } + /// + /// Gets or sets the sort order of the field. + /// + [DataMember(Name = "sortOrder")] + public int SortOrder { get; set; } + /// /// Gets or sets a value indicating whether to hide the label of the field. /// diff --git a/src/Umbraco.Core/PropertyEditors/ConfigurationFieldAttribute.cs b/src/Umbraco.Core/PropertyEditors/ConfigurationFieldAttribute.cs index 07433d1504..9eec779c2c 100644 --- a/src/Umbraco.Core/PropertyEditors/ConfigurationFieldAttribute.cs +++ b/src/Umbraco.Core/PropertyEditors/ConfigurationFieldAttribute.cs @@ -124,6 +124,11 @@ public class ConfigurationFieldAttribute : Attribute /// public string? View { get; } + /// + /// Gets or sets the sort order to use to render the field editor. + /// + public int SortOrder { get; set; } + /// /// Gets or sets the description of the field. /// diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index ddad88b482..c32a1a4183 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -1146,6 +1146,8 @@ public class ContentService : RepositoryService, IContentService var allLangs = _languageRepository.GetMany().ToList(); + // Change state to publishing + content.PublishedState = PublishedState.Publishing; var savingNotification = new ContentSavingNotification(content, evtMsgs); if (scope.Notifications.PublishCancelable(savingNotification)) { diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TagRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TagRepository.cs index ecc6600d4c..bc78596762 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TagRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TagRepository.cs @@ -131,7 +131,7 @@ internal class TagRepository : EntityRepositoryBase, ITagRepository var sql1 = $@"INSERT INTO cmsTags (tag, {group}, languageId) SELECT tagSet.tag, tagSet.{group}, tagSet.languageId FROM {tagSetSql} -LEFT OUTER JOIN cmsTags ON (tagSet.tag = cmsTags.tag AND tagSet.{group} = cmsTags.{group} AND COALESCE(tagSet.languageId, -1) = COALESCE(cmsTags.languageId, -1)) +LEFT OUTER JOIN cmsTags ON (tagSet.tag LIKE cmsTags.tag AND tagSet.{group} = cmsTags.{group} AND COALESCE(tagSet.languageId, -1) = COALESCE(cmsTags.languageId, -1)) WHERE cmsTags.id IS NULL"; Database.Execute(sql1); @@ -321,7 +321,7 @@ WHERE r.tagId IS NULL"; Sql sql = GetTaggedEntitiesSql(objectType, culture); sql = sql - .Where(dto => dto.Text == tag); + .WhereLike(dto => dto.Text, tag); if (group.IsNullOrWhiteSpace() == false) { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index 02f6164f64..7a681c07f4 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -941,15 +941,13 @@ const openPreviewWindow = () => { // Chromes popup blocker will kick in if a window is opened // without the initial scoped request. This trick will fix that. - // - const previewWindow = $window.open('preview/?init=true', 'umbpreview'); + + const previewWindow = $window.open(`preview/?id=${content.id}${$scope.culture ? `&culture=${$scope.culture}` : ''}`, 'umbpreview'); + + previewWindow.addEventListener('load', () => { + previewWindow.location.href = previewWindow.document.URL; + }); - // Build the correct path so both /#/ and #/ work. - let query = 'id=' + content.id; - if ($scope.culture) { - query += "#?culture=" + $scope.culture; - } - previewWindow.location.href = Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + '/preview/?' + query; } //The user cannot save if they don't have access to do that, in which case we just want to preview diff --git a/src/Umbraco.Web.UI.Client/src/common/services/keyboard.service.js b/src/Umbraco.Web.UI.Client/src/common/services/keyboard.service.js index 66babe03b8..3102a92449 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/keyboard.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/keyboard.service.js @@ -2,324 +2,329 @@ // http://www.openjs.com/scripts/events/keyboard_shortcuts/index.php function keyboardService($window, $timeout) { - - var keyboardManagerService = {}; - - var defaultOpt = { - 'type': 'keydown', - 'propagate': false, - 'inputDisabled': false, - 'target': $window.document, - 'keyCode': false - }; - // Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken - var shift_nums = { - "`": "~", - "1": "!", - "2": "@", - "3": "#", - "4": "$", - "5": "%", - "6": "^", - "7": "&", - "8": "*", - "9": "(", - "0": ")", - "-": "_", - "=": "+", - ";": ":", - "'": "\"", - ",": "<", - ".": ">", - "/": "?", - "\\": "|" - }; + var keyboardManagerService = {}; - // Special Keys - and their codes - var special_keys = { - 'esc': 27, - 'escape': 27, - 'tab': 9, - 'space': 32, - 'return': 13, - 'enter': 13, - 'backspace': 8, + var defaultOpt = { + 'type': 'keydown', + 'propagate': false, + 'inputDisabled': false, + 'target': $window.document, + 'keyCode': false + }; - 'scrolllock': 145, - 'scroll_lock': 145, - 'scroll': 145, - 'capslock': 20, - 'caps_lock': 20, - 'caps': 20, - 'numlock': 144, - 'num_lock': 144, - 'num': 144, + // Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken + var shift_nums = { + "`": "~", + "1": "!", + "2": "@", + "3": "#", + "4": "$", + "5": "%", + "6": "^", + "7": "&", + "8": "*", + "9": "(", + "0": ")", + "-": "_", + "=": "+", + ";": ":", + "'": "\"", + ",": "<", + ".": ">", + "/": "?", + "\\": "|" + }; - 'pause': 19, - 'break': 19, + // Special Keys - and their codes + var special_keys = { + 'esc': 27, + 'escape': 27, + 'tab': 9, + 'space': 32, + 'return': 13, + 'enter': 13, + 'backspace': 8, - 'insert': 45, - 'home': 36, - 'delete': 46, - 'end': 35, + 'scrolllock': 145, + 'scroll_lock': 145, + 'scroll': 145, + 'capslock': 20, + 'caps_lock': 20, + 'caps': 20, + 'numlock': 144, + 'num_lock': 144, + 'num': 144, - 'pageup': 33, - 'page_up': 33, - 'pu': 33, + 'pause': 19, + 'break': 19, - 'pagedown': 34, - 'page_down': 34, - 'pd': 34, + 'insert': 45, + 'home': 36, + 'delete': 46, + 'end': 35, - 'left': 37, - 'up': 38, - 'right': 39, - 'down': 40, + 'pageup': 33, + 'page_up': 33, + 'pu': 33, - 'f1': 112, - 'f2': 113, - 'f3': 114, - 'f4': 115, - 'f5': 116, - 'f6': 117, - 'f7': 118, - 'f8': 119, - 'f9': 120, - 'f10': 121, - 'f11': 122, - 'f12': 123 - }; + 'pagedown': 34, + 'page_down': 34, + 'pd': 34, - var isMac = navigator.platform.toUpperCase().indexOf('MAC')>=0; + 'left': 37, + 'up': 38, + 'right': 39, + 'down': 40, - // The event handler for bound element events - function eventHandler(e) { - e = e || $window.event; + 'f1': 112, + 'f2': 113, + 'f3': 114, + 'f4': 115, + 'f5': 116, + 'f6': 117, + 'f7': 118, + 'f8': 119, + 'f9': 120, + 'f10': 121, + 'f11': 122, + 'f12': 123 + }; - var code, k; + var isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0; - // Find out which key is pressed - if (e.keyCode) - { - code = e.keyCode; - } - else if (e.which) { - code = e.which; - } + // The event handler for bound element events + function eventHandler(e) { + e = e || $window.event; - var character = String.fromCharCode(code).toLowerCase(); + var code, k; - if (code === 188){character = ",";} // If the user presses , when the type is onkeydown - if (code === 190){character = ".";} // If the user presses , when the type is onkeydown - - var propagate = true; - - //Now we need to determine which shortcut this event is for, we'll do this by iterating over each - //registered shortcut to find the match. We use Find here so that the loop exits as soon - //as we've found the one we're looking for - _.find(_.keys(keyboardManagerService.keyboardEvent), function(key) { - - var shortcutLabel = key; - var shortcutVal = keyboardManagerService.keyboardEvent[key]; - - // Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked - var kp = 0; - - // Some modifiers key - var modifiers = { - shift: { - wanted: false, - pressed: e.shiftKey ? true : false - }, - ctrl: { - wanted: false, - pressed: e.ctrlKey ? true : false - }, - alt: { - wanted: false, - pressed: e.altKey ? true : false - }, - meta: { //Meta is Mac specific - wanted: false, - pressed: e.metaKey ? true : false - } - }; - - var keys = shortcutLabel.split("+"); - var opt = shortcutVal.opt; - var callback = shortcutVal.callback; - - // Foreach keys in label (split on +) - var l = keys.length; - for (var i = 0; i < l; i++) { - - var k = keys[i]; - switch (k) { - case 'ctrl': - case 'control': - kp++; - modifiers.ctrl.wanted = true; - break; - case 'shift': - case 'alt': - case 'meta': - kp++; - modifiers[k].wanted = true; - break; - } - - if (k.length > 1) { // If it is a special key - if (special_keys[k] === code) { - kp++; - } - } - else if (opt['keyCode']) { // If a specific key is set into the config - if (opt['keyCode'] === code) { - kp++; - } - } - else { // The special keys did not match - if (character === k) { - kp++; - } - else { - if (shift_nums[character] && e.shiftKey) { // Stupid Shift key bug created by using lowercase - character = shift_nums[character]; - if (character === k) { - kp++; - } - } - } - } - - } //for end - - if (kp === keys.length && - modifiers.ctrl.pressed === modifiers.ctrl.wanted && - modifiers.shift.pressed === modifiers.shift.wanted && - modifiers.alt.pressed === modifiers.alt.wanted && - modifiers.meta.pressed === modifiers.meta.wanted) { - - //found the right callback! - - // Disable event handler when focus input and textarea - if (opt['inputDisabled']) { - var elt; - if (e.target) { - elt = e.target; - } else if (e.srcElement) { - elt = e.srcElement; - } - - if (elt.nodeType === 3) { elt = elt.parentNode; } - if (elt.tagName === 'INPUT' || elt.tagName === 'TEXTAREA' || elt.hasAttribute('disable-hotkeys')) { - //This exits the Find loop - return true; - } - } - - $timeout(function () { - callback(e); - }, 1); - - if (!opt['propagate']) { // Stop the event - propagate = false; - } - - //This exits the Find loop - return true; - } - - //we haven't found one so continue looking - return false; - - }); - - // Stop the event if required - if (!propagate) { - // e.cancelBubble is supported by IE - this will kill the bubbling process. - e.cancelBubble = true; - e.returnValue = false; - - // e.stopPropagation works in Firefox. - if (e.stopPropagation) { - e.stopPropagation(); - e.preventDefault(); - } - return false; - } + // Find out which key is pressed + if (e.keyCode) { + code = e.keyCode; + } else if (e.which) { + code = e.which; } - // Store all keyboard combination shortcuts - keyboardManagerService.keyboardEvent = {}; + var character = String.fromCharCode(code).toLowerCase(); - // Add a new keyboard combination shortcut - keyboardManagerService.bind = function (label, callback, opt) { + if (code === 188) { + character = ","; + } // If the user presses , when the type is onkeydown + if (code === 190) { + character = "."; + } // If the user presses , when the type is onkeydown - //replace ctrl key with meta key - if(isMac && label !== "ctrl+space"){ - label = label.replace("ctrl","meta"); + var propagate = true; + + //Now we need to determine which shortcut this event is for, we'll do this by iterating over each + //registered shortcut to find the match. We use Find here so that the loop exits as soon + //as we've found the one we're looking for + _.find(_.keys(keyboardManagerService.keyboardEvent), function (key) { + + var shortcutLabel = key; + var shortcutVal = keyboardManagerService.keyboardEvent[key]; + + // Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked + var kp = 0; + + // Some modifiers key + var modifiers = { + shift: { + wanted: false, + pressed: e.shiftKey ? true : false + }, + ctrl: { + wanted: false, + pressed: e.ctrlKey ? true : false + }, + alt: { + wanted: false, + pressed: e.altKey ? true : false + }, + meta: { //Meta is Mac specific + wanted: false, + pressed: e.metaKey ? true : false + } + }; + + var keys = shortcutLabel.split("+"); + var opt = shortcutVal.opt; + var callback = shortcutVal.callback; + + // Foreach keys in label (split on +) + var l = keys.length; + for (var i = 0; i < l; i++) { + + var k = keys[i]; + switch (k) { + case 'ctrl': + case 'control': + kp++; + modifiers.ctrl.wanted = true; + break; + case 'shift': + case 'alt': + case 'meta': + kp++; + modifiers[k].wanted = true; + break; } - var elt; - // Initialize opt object - opt = Utilities.extend({}, defaultOpt, opt); - label = label.toLowerCase(); - elt = opt.target; - if(typeof opt.target === 'string'){ - elt = document.getElementById(opt.target); - } - - //Ensure we aren't double binding to the same element + type otherwise we'll end up multi-binding - // and raising events for now reason. So here we'll check if the event is already registered for the element - var boundValues = _.values(keyboardManagerService.keyboardEvent); - var found = _.find(boundValues, function (i) { - return i.target === elt && i.event === opt['type']; - }); - - // Store shortcut - keyboardManagerService.keyboardEvent[label] = { - 'callback': callback, - 'target': elt, - 'opt': opt - }; - - if (!found) { - //Attach the function with the event - if (elt.addEventListener) { - elt.addEventListener(opt['type'], eventHandler, false); - } else if (elt.attachEvent) { - elt.attachEvent('on' + opt['type'], eventHandler); - } else { - elt['on' + opt['type']] = eventHandler; + if (k.length > 1) { // If it is a special key + if (special_keys[k] === code) { + kp++; + } + } else if (opt['keyCode']) { // If a specific key is set into the config + if (opt['keyCode'] === code) { + kp++; + } + } else { // The special keys did not match + if (character === k) { + kp++; + } else { + if (shift_nums[character] && e.shiftKey) { // Stupid Shift key bug created by using lowercase + character = shift_nums[character]; + if (character === k) { + kp++; + } } + } } - - }; - // Remove the shortcut - just specify the shortcut and I will remove the binding - keyboardManagerService.unbind = function (label) { - label = label.toLowerCase(); - var binding = keyboardManagerService.keyboardEvent[label]; - delete(keyboardManagerService.keyboardEvent[label]); - if(!binding){return;} + } //for end - var type = binding['event'], - elt = binding['target'], - callback = binding['callback']; + if (kp === keys.length && + modifiers.ctrl.pressed === modifiers.ctrl.wanted && + modifiers.shift.pressed === modifiers.shift.wanted && + modifiers.alt.pressed === modifiers.alt.wanted && + modifiers.meta.pressed === modifiers.meta.wanted) { - if(elt.detachEvent){ - elt.detachEvent('on' + type, callback); - }else if(elt.removeEventListener){ - elt.removeEventListener(type, callback, false); - }else{ - elt['on'+type] = false; + //found the right callback! + + // Disable event handler when focus input and textarea + if (opt['inputDisabled']) { + var elt; + if (e.composedPath()) { + elt = e.composedPath()[0]; + } else if (e.target) { + elt = e.target; + } else if (e.srcElement) { + elt = e.srcElement; + } + + if (elt.nodeType === 3) { + elt = elt.parentNode; + } + if (elt.tagName === 'INPUT' || elt.tagName === 'TEXTAREA' || elt.hasAttribute('disable-hotkeys')) { + //This exits the Find loop + return true; + } } - }; - // - return keyboardManagerService; + $timeout(function () { + callback(e); + }, 1); + + if (!opt['propagate']) { // Stop the event + propagate = false; + } + + //This exits the Find loop + return true; + } + + //we haven't found one so continue looking + return false; + + }); + + // Stop the event if required + if (!propagate) { + // e.cancelBubble is supported by IE - this will kill the bubbling process. + e.cancelBubble = true; + e.returnValue = false; + + // e.stopPropagation works in Firefox. + if (e.stopPropagation) { + e.stopPropagation(); + e.preventDefault(); + } + return false; + } + } + + // Store all keyboard combination shortcuts + keyboardManagerService.keyboardEvent = {}; + + // Add a new keyboard combination shortcut + keyboardManagerService.bind = function (label, callback, opt) { + + //replace ctrl key with meta key + if (isMac && label !== "ctrl+space") { + label = label.replace("ctrl", "meta"); + } + + var elt; + // Initialize opt object + opt = Utilities.extend({}, defaultOpt, opt); + label = label.toLowerCase(); + elt = opt.target; + if (typeof opt.target === 'string') { + elt = document.getElementById(opt.target); + } + + //Ensure we aren't double binding to the same element + type otherwise we'll end up multi-binding + // and raising events for now reason. So here we'll check if the event is already registered for the element + var boundValues = _.values(keyboardManagerService.keyboardEvent); + var found = _.find(boundValues, function (i) { + return i.target === elt && i.event === opt['type']; + }); + + // Store shortcut + keyboardManagerService.keyboardEvent[label] = { + 'callback': callback, + 'target': elt, + 'opt': opt + }; + + if (!found) { + //Attach the function with the event + if (elt.addEventListener) { + elt.addEventListener(opt['type'], eventHandler, false); + } else if (elt.attachEvent) { + elt.attachEvent('on' + opt['type'], eventHandler); + } else { + elt['on' + opt['type']] = eventHandler; + } + } + + }; + // Remove the shortcut - just specify the shortcut and I will remove the binding + keyboardManagerService.unbind = function (label) { + label = label.toLowerCase(); + var binding = keyboardManagerService.keyboardEvent[label]; + delete (keyboardManagerService.keyboardEvent[label]); + + if (!binding) { + return; + } + + var type = binding['event'], + elt = binding['target'], + callback = binding['callback']; + + if (elt.detachEvent) { + elt.detachEvent('on' + type, callback); + } else if (elt.removeEventListener) { + elt.removeEventListener(type, callback, false); + } else { + elt['on' + type] = false; + } + }; + // + + return keyboardManagerService; } angular.module('umbraco.services').factory('keyboardService', ['$window', '$timeout', keyboardService]); diff --git a/src/Umbraco.Web.UI.Client/src/less/main.less b/src/Umbraco.Web.UI.Client/src/less/main.less index 024a668874..2fce7dfe65 100644 --- a/src/Umbraco.Web.UI.Client/src/less/main.less +++ b/src/Umbraco.Web.UI.Client/src/less/main.less @@ -165,7 +165,7 @@ h6.-black { } } -umb-property:last-of-type .umb-control-group { +umb-property:last-of-type > .umb-property > ng-form > .umb-control-group { &::after { margin-top: 0px; height: 0; diff --git a/src/Umbraco.Web.UI.Client/src/less/pages/login.less b/src/Umbraco.Web.UI.Client/src/less/pages/login.less index 74b28dabcb..e565e7d8ab 100644 --- a/src/Umbraco.Web.UI.Client/src/less/pages/login.less +++ b/src/Umbraco.Web.UI.Client/src/less/pages/login.less @@ -118,6 +118,11 @@ line-height: 36px; } +.login-overlay .btn-social > .umb-icon { + padding: 2px; + box-sizing: border-box; +} + .login-overlay .text-error, .login-overlay .text-info { diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js index 730e7a5142..98755c4090 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js @@ -128,6 +128,13 @@ angular.module("umbraco").controller("Umbraco.Editors.LinkPickerController", eventsService.emit("dialogs.linkPicker.select", args); if ($scope.currentNode) { + if ($scope.currentNode.id == args.node.id && $scope.currentNode.selected) { + $scope.model.target = {}; + $scope.currentNode.selected = false; + + return; + } + //un-select if there's a current one selected $scope.currentNode.selected = false; } diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html index 8215c66691..c54d692850 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html @@ -18,10 +18,10 @@ + ng-attr-readonly="{{property.readonly || !allowUpdate || undefined}}"> @@ -52,10 +52,10 @@ + ng-attr-readonly="{{property.readonly || !allowUpdate || undefined}}"> diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/textstringlimited.html b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/textstringlimited.html index 4dd5b693b8..9ec218bba5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/textstringlimited.html +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/textstringlimited.html @@ -5,7 +5,7 @@ ng-model="model.value" val-server="value" min="0" - max="500" + max="512" fix-number /> @@ -13,5 +13,5 @@ - + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/umbblockgridblock.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/umbblockgridblock.component.js index 1a918638ca..3dfbdab0ff 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/umbblockgridblock.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/umbblockgridblock.component.js @@ -51,7 +51,7 @@ ` ${ model.stylesheet ? ` ` : '' } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/umbblockgridroot.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/umbblockgridroot.component.js index fbda5cf92e..bfa0746a30 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/umbblockgridroot.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/umbblockgridroot.component.js @@ -35,8 +35,8 @@ shadowRoot.innerHTML = `