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 0a69ef5340..3833dc50b9 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 @@ -5,7 +5,27 @@ angular.module("umbraco.directives") * @name umbraco.directives.directive:localize * @restrict EA * @function - * @description Localize directive + * @description + *
+ * Component
+ * Localize a specific token to put into the HTML as an item + *
+ *
+ * Attribute
+ * Add a HTML attribute to an element containing the HTML attribute name you wish to localise + * Using the format of '@section_key' or 'section_key' + *
+ * ##Usage + *
+    * 
+    * Close
+    * Fallback value
+    *
+    * 
+    * 
+    * 
+    * 
+ *
**/ .directive('localize', function ($log, localizationService) { return { @@ -28,6 +48,7 @@ angular.module("umbraco.directives") return { restrict: 'A', link: function (scope, element, attrs) { + //Support one or more attribute properties to update var keys = attrs.localize.split(','); angular.forEach(keys, function(value, key){ @@ -35,13 +56,15 @@ angular.module("umbraco.directives") if(attr){ if(attr[0] === '@'){ - - var t = localizationService.tokenize(attr.substring(1), scope); - localizationService.localize(t.key, t.tokens).then(function(val){ - element.attr(value, val); - }); - + //If the translation key starts with @ then remove it + attr = attr.substring(1); } + + var t = localizationService.tokenize(attr, scope); + + localizationService.localize(t.key, t.tokens).then(function(val){ + element.attr(value, val); + }); } }); } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js index d69c7f6ba0..d728865015 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js @@ -478,8 +478,10 @@ Opens an overlay to show a custom YSOD.
numberOfOverlays = overlayHelper.getNumberOfOverlays(); - if(numberOfOverlays === overlayNumber) { - scope.closeOverLay(); + if (numberOfOverlays === overlayNumber) { + scope.$apply(function () { + scope.closeOverLay(); + }); } event.preventDefault(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbaceeditor.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbaceeditor.directive.js index c97851bbb9..40a1a2cc6d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbaceeditor.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbaceeditor.directive.js @@ -125,7 +125,7 @@ function link(scope, el, attr, ngModel) { // Load in ace library - assetsService.loadJs('lib/ace-builds/src-min-noconflict/ace.js').then(function () { + assetsService.load(['lib/ace-builds/src-min-noconflict/ace.js', 'lib/ace-builds/src-min-noconflict/ext-language_tools.js']).then(function () { if (angular.isUndefined(window.ace)) { throw new Error('ui-ace need ace to work... (o rly?)'); } else { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbkeyboardshortcutsoverview.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbkeyboardshortcutsoverview.directive.js index 1bbfb850d9..40fe431fb8 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbkeyboardshortcutsoverview.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbkeyboardshortcutsoverview.directive.js @@ -107,34 +107,76 @@ When this combination is hit an overview is opened with shortcuts based on the m @param {object} model keyboard shortcut model. See description and example above. **/ -(function() { - 'use strict'; +(function () { + 'use strict'; - function KeyboardShortcutsOverviewDirective() { + function KeyboardShortcutsOverviewDirective(platformService) { - function link(scope, el, attr, ctrl) { + function link(scope, el, attr, ctrl) { - scope.shortcutOverlay = false; + var eventBindings = []; + var isMac = platformService.isMac(); - scope.toggleShortcutsOverlay = function() { - scope.shortcutOverlay = !scope.shortcutOverlay; - }; + scope.toggleShortcutsOverlay = function () { + scope.showOverlay = !scope.showOverlay; + scope.onToggle(); + }; + function onInit() { + + angular.forEach(scope.model, function (shortcutGroup) { + angular.forEach(shortcutGroup.shortcuts, function (shortcut) { + + shortcut.platformKeys = []; + + // get shortcut keys for mac + if (isMac && shortcut.keys && shortcut.keys.mac) { + shortcut.platformKeys = shortcut.keys.mac; + // get shortcut keys for windows + } else if (!isMac && shortcut.keys && shortcut.keys.win) { + shortcut.platformKeys = shortcut.keys.win; + // get default shortcut keys + } else if (shortcut.keys && shortcut && shortcut.keys.length > 0) { + shortcut.platformKeys = shortcut.keys; + } + + }); + }); + } + + onInit(); + + eventBindings.push(scope.$watch('model', function(newValue, oldValue){ + if (newValue !== oldValue) { + onInit(); + } + })); + + // clean up + scope.$on('$destroy', function () { + // unbind watchers + for (var e in eventBindings) { + eventBindings[e](); + } + }); + + } + + var directive = { + restrict: 'E', + replace: true, + templateUrl: 'views/components/umb-keyboard-shortcuts-overview.html', + link: link, + scope: { + model: "=", + onToggle: "&", + showOverlay: "=?" + } + }; + + return directive; } - var directive = { - restrict: 'E', - replace: true, - templateUrl: 'views/components/umb-keyboard-shortcuts-overview.html', - link: link, - scope: { - model: "=" - } - }; - - return directive; - } - - angular.module('umbraco.directives').directive('umbKeyboardShortcutsOverview', KeyboardShortcutsOverviewDirective); + angular.module('umbraco.directives').directive('umbKeyboardShortcutsOverview', KeyboardShortcutsOverviewDirective); })(); 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 430ed02242..8d1d274e85 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 @@ -135,8 +135,13 @@ angular.module('umbraco.services') * * @description * Checks the dictionary for a localized resource string - * @param {String} value the area/key to localize - * @param {Array} tokens if specified this array will be sent as parameter values + * @param {String} value the area/key to localize in the format of 'section_key' + * alternatively if no section is set such as 'key' then we assume the key is to be looked in + * the 'general' section + * + * @param {Array} tokens if specified this array will be sent as parameter values + * This replaces %0% and %1% etc in the dictionary key value with the passed in strings + * * @returns {String} localized resource string */ localize: function (value, tokens) { @@ -146,6 +151,143 @@ angular.module('umbraco.services') }); }, + /** + * @ngdoc method + * @name umbraco.services.localizationService#localizeMany + * @methodOf umbraco.services.localizationService + * + * @description + * Checks the dictionary for multipe localized resource strings at once, preventing the need for nested promises + * with localizationService.localize + * + * ##Usage + *
+         * localizationService.localizeMany(["speechBubbles_templateErrorHeader", "speechBubbles_templateErrorText"]).then(function(data){
+         *      var header = data[0];
+         *      var message = data[1];
+         *      notificationService.error(header, message);
+         * });
+         * 
+ * + * @param {Array} keys is an array of strings of the area/key to localize in the format of 'section_key' + * alternatively if no section is set such as 'key' then we assume the key is to be looked in + * the 'general' section + * + * @returns {Array} An array of localized resource string in the same order + */ + localizeMany: function(keys) { + if(keys){ + + //The LocalizationService.localize promises we want to resolve + var promises = []; + + for(var i = 0; i < keys.length; i++){ + promises.push(service.localize(keys[i], undefined)); + } + + return $q.all(promises).then(function(localizedValues){ + return localizedValues; + }); + } + }, + + /** + * @ngdoc method + * @name umbraco.services.localizationService#concat + * @methodOf umbraco.services.localizationService + * + * @description + * Checks the dictionary for multipe localized resource strings at once & concats them to a single string + * Which was not possible with localizationSerivce.localize() due to returning a promise + * + * ##Usage + *
+         * localizationService.concat(["speechBubbles_templateErrorHeader", "speechBubbles_templateErrorText"]).then(function(data){
+         *      var combinedText = data;
+         * });
+         * 
+ * + * @param {Array} keys is an array of strings of the area/key to localize in the format of 'section_key' + * alternatively if no section is set such as 'key' then we assume the key is to be looked in + * the 'general' section + * + * @returns {String} An concatenated string of localized resource string passed into the function in the same order + */ + concat: function(keys) { + if(keys){ + + //The LocalizationService.localize promises we want to resolve + var promises = []; + + for(var i = 0; i < keys.length; i++){ + promises.push(service.localize(keys[i], undefined)); + } + + return $q.all(promises).then(function(localizedValues){ + + //Build a concat string by looping over the array of resolved promises/translations + var returnValue = ""; + + for(var i = 0; i < localizedValues.length; i++){ + returnValue += localizedValues[i]; + } + + return returnValue; + }); + } + }, + + /** + * @ngdoc method + * @name umbraco.services.localizationService#format + * @methodOf umbraco.services.localizationService + * + * @description + * Checks the dictionary for multipe localized resource strings at once & formats a tokenized message + * Which was not possible with localizationSerivce.localize() due to returning a promise + * + * ##Usage + *
+         * localizationService.format(["template_insert", "template_insertSections"], "%0% %1%").then(function(data){
+         *      //Will return 'Insert Sections'
+         *      var formattedResult = data;
+         * });
+         * 
+ * + * @param {Array} keys is an array of strings of the area/key to localize in the format of 'section_key' + * alternatively if no section is set such as 'key' then we assume the key is to be looked in + * the 'general' section + * + * @param {String} message is the string you wish to replace containing tokens in the format of %0% and %1% + * with the localized resource strings + * + * @returns {String} An concatenated string of localized resource string passed into the function in the same order + */ + format: function(keys, message){ + if(keys){ + + //The LocalizationService.localize promises we want to resolve + var promises = []; + + for(var i = 0; i < keys.length; i++){ + promises.push(service.localize(keys[i], undefined)); + } + + return $q.all(promises).then(function(localizedValues){ + + //Replace {0} and {1} etc in message with the localized values + for(var i = 0; i < localizedValues.length; i++){ + var token = "%" + i + "%"; + var regex = new RegExp(token, "g"); + + message = message.replace(regex, localizedValues[i]); + } + + return message; + }); + } + } + }; //This happens after login / auth and assets loading diff --git a/src/Umbraco.Web.UI.Client/src/common/services/platform.service.js b/src/Umbraco.Web.UI.Client/src/common/services/platform.service.js new file mode 100644 index 0000000000..7834c2f781 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/services/platform.service.js @@ -0,0 +1,23 @@ +(function() { + 'use strict'; + + function platformService() { + + function isMac() { + return navigator.platform.toUpperCase().indexOf('MAC')>=0; + } + + //////////// + + var service = { + isMac: isMac + }; + + return service; + + } + + angular.module('umbraco.services').factory('platformService', platformService); + + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/templatehelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/templatehelper.service.js index 01e544c78d..aefbc5625b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/templatehelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/templatehelper.service.js @@ -1,7 +1,7 @@ (function() { 'use strict'; - function templateHelperService() { + function templateHelperService(localizationService) { //crappy hack due to dictionary items not in umbracoNode table function getInsertDictionarySnippet(nodeName) { @@ -36,6 +36,124 @@ return "@section " + sectionName + "\r\n{\r\n\r\n\t{0}\r\n\r\n}\r\n"; } + function getGeneralShortcuts(){ + return { + "name": localizationService.localize("shortcuts_generalHeader"), + "shortcuts": [ + { + "description": localizationService.localize("buttons_undo"), + "keys": [{ "key": "ctrl" }, { "key": "z" }] + }, + { + "description": localizationService.localize("buttons_redo"), + "keys": [{ "key": "ctrl" }, { "key": "y" }] + }, + { + "description": localizationService.localize("buttons_save"), + "keys": [{ "key": "ctrl" }, { "key": "s" }] + } + ] + }; + } + + function getEditorShortcuts(){ + return { + "name": localizationService.localize("shortcuts_editorHeader"), + "shortcuts": [ + { + "description": localizationService.localize("shortcuts_commentLine"), + "keys": [{ "key": "ctrl" }, { "key": "/" }] + }, + { + "description": localizationService.localize("shortcuts_removeLine"), + "keys": [{ "key": "ctrl" }, { "key": "d" }] + }, + { + "description": localizationService.localize("shortcuts_copyLineUp"), + "keys": { + "win": [{ "key": "alt" }, { "key": "shift" }, { "key": "up" }], + "mac": [{ "key": "cmd" }, { "key": "alt" }, { "key": "up" }] + } + }, + { + "description": localizationService.localize("shortcuts_copyLineDown"), + "keys": { + "win": [{ "key": "alt" }, { "key": "shift" }, { "key": "down" }], + "mac": [{ "key": "cmd" }, { "key": "alt" }, { "key": "down" }] + } + }, + { + "description": localizationService.localize("shortcuts_moveLineUp"), + "keys": [{ "key": "alt" }, { "key": "up" }] + }, + { + "description": localizationService.localize("shortcuts_moveLineDown"), + "keys": [{ "key": "alt" }, { "key": "down" }] + } + ] + }; + } + + function getTemplateEditorShortcuts(){ + return { + "name": "Umbraco", //No need to localise Umbraco is the same in all languages :) + "shortcuts": [ + { + "description": localizationService.format(["template_insert", "template_insertPageField"], "%0% %1%"), + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "v" }] + }, + { + "description": localizationService.format(["template_insert", "template_insertPartialView"], "%0% %1%"), + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "p" }] + }, + { + "description": localizationService.format(["template_insert", "template_insertDictionaryItem"], "%0% %1%"), + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "d" }] + }, + { + "description": localizationService.format(["template_insert", "template_insertMacro"], "%0% %1%"), + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "m" }] + }, + { + "description": localizationService.localize("template_queryBuilder"), + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "q" }] + }, + { + "description": localizationService.format(["template_insert", "template_insertSections"], "%0% %1%"), + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "s" }] + }, + { + "description": localizationService.localize("template_mastertemplate"), + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }] + } + ] + }; + } + + function getPartialViewEditorShortcuts(){ + return { + "name": "Umbraco", //No need to localise Umbraco is the same in all languages :) + "shortcuts": [ + { + "description": localizationService.format(["template_insert", "template_insertPageField"], "%0% %1%"), + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "v" }] + }, + { + "description": localizationService.format(["template_insert", "template_insertDictionaryItem"], "%0% %1%"), + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "d" }] + }, + { + "description": localizationService.format(["template_insert", "template_insertMacro"], "%0% %1%"), + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "m" }] + }, + { + "description": localizationService.localize("template_queryBuilder"), + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "q" }] + } + ] + }; + } + //////////// var service = { @@ -44,7 +162,11 @@ getQuerySnippet: getQuerySnippet, getRenderBodySnippet: getRenderBodySnippet, getRenderSectionSnippet: getRenderSectionSnippet, - getAddSectionSnippet: getAddSectionSnippet + getAddSectionSnippet: getAddSectionSnippet, + getGeneralShortcuts: getGeneralShortcuts, + getEditorShortcuts: getEditorShortcuts, + getTemplateEditorShortcuts: getTemplateEditorShortcuts, + getPartialViewEditorShortcuts: getPartialViewEditorShortcuts }; return service; diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-keyboard-shortcuts-overview.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-keyboard-shortcuts-overview.html index 6368bb1e37..8b12ee4afd 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-keyboard-shortcuts-overview.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-keyboard-shortcuts-overview.html @@ -17,7 +17,7 @@ -
+
@@ -35,7 +35,7 @@
{{ keyboardShortcut.description }}
-
+
{{ key.key }}
diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js index a493ed30c1..fcd91071c0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js @@ -15,6 +15,16 @@ vm.page.menu.currentSection = appState.getSectionState("currentSection"); vm.page.menu.currentNode = null; + //Used to toggle the keyboard shortcut modal + //From a custom keybinding in ace editor - that conflicts with our own to show the dialog + vm.showKeyboardShortcut = false; + + //Keyboard shortcuts for help dialog + vm.page.keyboardShortcutsOverview = []; + vm.page.keyboardShortcutsOverview.push(templateHelper.getGeneralShortcuts()); + vm.page.keyboardShortcutsOverview.push(templateHelper.getEditorShortcuts()); + vm.page.keyboardShortcutsOverview.push(templateHelper.getPartialViewEditorShortcuts()); + // bind functions to view model vm.save = save; vm.openPageFieldOverlay = openPageFieldOverlay; @@ -270,6 +280,71 @@ }, onLoad: function(_editor) { vm.editor = _editor; + + //Update the auto-complete method to use ctrl+alt+space + _editor.commands.bindKey("ctrl-alt-space", "startAutocomplete"); + + //Unassigns the keybinding (That was previously auto-complete) + //As conflicts with our own tree search shortcut + _editor.commands.bindKey("ctrl-space", null); + + // Assign new keybinding + _editor.commands.addCommands([ + //Disable (alt+shift+K) + //Conflicts with our own show shortcuts dialog - this overrides it + { + name: 'unSelectOrFindPrevious', + bindKey: 'Alt-Shift-K', + exec: function () { + //Toggle the show keyboard shortcuts overlay + $scope.$apply(function () { + vm.showKeyboardShortcut = !vm.showKeyboardShortcut; + }); + }, + readOnly: true + }, + { + name: 'insertUmbracoValue', + bindKey: 'Alt-Shift-V', + exec: function () { + $scope.$apply(function () { + openPageFieldOverlay(); + }); + }, + readOnly: true + }, + { + name: 'insertDictionary', + bindKey: 'Alt-Shift-D', + exec: function () { + $scope.$apply(function () { + openDictionaryItemOverlay(); + }); + }, + readOnly: true + }, + { + name: 'insertUmbracoMacro', + bindKey: 'Alt-Shift-M', + exec: function () { + $scope.$apply(function () { + openMacroOverlay(); + }); + }, + readOnly: true + }, + { + name: 'insertQuery', + bindKey: 'Alt-Shift-Q', + exec: function () { + $scope.$apply(function () { + openQueryBuilderOverlay(); + }); + }, + readOnly: true + }, + + ]); // initial cursor placement // Keep cursor in name field if we are create a new template diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.html b/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.html index 2c974fcfaa..45ef1d38a4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.html @@ -67,18 +67,23 @@ - + + + + - - - - + + + + diff --git a/src/Umbraco.Web.UI.Client/src/views/scripts/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/scripts/edit.controller.js index d2a5fcbc0e..d8c3723d2d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/scripts/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/scripts/edit.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function ScriptsEditController($scope, $routeParams, $timeout, appState, editorState, navigationService, assetsService, codefileResource, contentEditingHelper, notificationsService, localizationService) { + function ScriptsEditController($scope, $routeParams, $timeout, appState, editorState, navigationService, assetsService, codefileResource, contentEditingHelper, notificationsService, localizationService, templateHelper) { var vm = this; var currentPosition = null; @@ -14,6 +14,16 @@ vm.page.menu.currentNode = null; vm.page.saveButtonState = "init"; + //Used to toggle the keyboard shortcut modal + //From a custom keybinding in ace editor - that conflicts with our own to show the dialog + vm.showKeyboardShortcut = false; + + //Keyboard shortcuts for help dialog + vm.page.keyboardShortcutsOverview = []; + vm.page.keyboardShortcutsOverview.push(templateHelper.getGeneralShortcuts()); + vm.page.keyboardShortcutsOverview.push(templateHelper.getEditorShortcuts()); + + vm.script = {}; // bind functions to view model @@ -39,10 +49,10 @@ rebindCallback: function (orignal, saved) {} }).then(function (saved) { - localizationService.localize("speechBubbles_fileSavedHeader").then(function (headerValue) { - localizationService.localize("speechBubbles_fileSavedText").then(function(msgValue) { - notificationsService.success(headerValue, msgValue); - }); + localizationService.localizeMany(["speechBubbles_fileSavedHeader", "speechBubbles_fileSavedText"]).then(function(data){ + var header = data[0]; + var message = data[1]; + notificationsService.success(header, message); }); vm.page.saveButtonState = "success"; @@ -60,10 +70,10 @@ vm.page.saveButtonState = "error"; - localizationService.localize("speechBubbles_validationFailedHeader").then(function (headerValue) { - localizationService.localize("speechBubbles_validationFailedMessage").then(function(msgValue) { - notificationsService.error(headerValue, msgValue); - }); + localizationService.localizeMany(["speechBubbles_validationFailedHeader", "speechBubbles_validationFailedMessage"]).then(function(data){ + var header = data[0]; + var message = data[1]; + notificationsService.error(header, message); }); }); @@ -108,11 +118,38 @@ theme: "chrome", showPrintMargin: false, advanced: { - fontSize: '14px' + fontSize: '14px', + enableSnippets: true, + enableBasicAutocompletion: true, + enableLiveAutocompletion: false }, onLoad: function(_editor) { vm.editor = _editor; + + //Update the auto-complete method to use ctrl+alt+space + _editor.commands.bindKey("ctrl-alt-space", "startAutocomplete"); + + //Unassigns the keybinding (That was previously auto-complete) + //As conflicts with our own tree search shortcut + _editor.commands.bindKey("ctrl-space", null); + + //TODO: Move all these keybinding config out into some helper/service + _editor.commands.addCommands([ + //Disable (alt+shift+K) + //Conflicts with our own show shortcuts dialog - this overrides it + { + name: 'unSelectOrFindPrevious', + bindKey: 'Alt-Shift-K', + exec: function() { + //Toggle the show keyboard shortcuts overlay + $scope.$apply(function(){ + vm.showKeyboardShortcut = !vm.showKeyboardShortcut; + }); + }, + readOnly: true + }, + ]); // initial cursor placement // Keep cursor in name field if we are create a new script diff --git a/src/Umbraco.Web.UI.Client/src/views/scripts/edit.html b/src/Umbraco.Web.UI.Client/src/views/scripts/edit.html index 18e5e8525c..4c58356732 100644 --- a/src/Umbraco.Web.UI.Client/src/views/scripts/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/scripts/edit.html @@ -29,19 +29,27 @@ + - + + - - + - + + + + + + diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js index 526107daae..9edb659d09 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js @@ -15,6 +15,17 @@ vm.page.menu = {}; vm.page.menu.currentSection = appState.getSectionState("currentSection"); vm.page.menu.currentNode = null; + + //Used to toggle the keyboard shortcut modal + //From a custom keybinding in ace editor - that conflicts with our own to show the dialog + vm.showKeyboardShortcut = false; + + //Keyboard shortcuts for help dialog + vm.page.keyboardShortcutsOverview = []; + vm.page.keyboardShortcutsOverview.push(templateHelper.getGeneralShortcuts()); + vm.page.keyboardShortcutsOverview.push(templateHelper.getEditorShortcuts()); + vm.page.keyboardShortcutsOverview.push(templateHelper.getTemplateEditorShortcuts()); + vm.save = function () { vm.page.saveButtonState = "busy"; @@ -33,10 +44,10 @@ rebindCallback: function (orignal, saved) {} }).then(function (saved) { - localizationService.localize("speechBubbles_templateSavedHeader").then(function (headerValue) { - localizationService.localize("speechBubbles_templateSavedText").then(function(msgValue) { - notificationsService.success(headerValue, msgValue); - }); + localizationService.localizeMany(["speechBubbles_templateSavedHeader", "speechBubbles_templateSavedText"]).then(function(data){ + var header = data[0]; + var message = data[1]; + notificationsService.success(header, message); }); @@ -78,10 +89,10 @@ vm.page.saveButtonState = "error"; - localizationService.localize("speechBubbles_validationFailedHeader").then(function (headerValue) { - localizationService.localize("speechBubbles_validationFailedMessage").then(function(msgValue) { - notificationsService.error(headerValue, msgValue); - }); + localizationService.localizeMany(["speechBubbles_validationFailedHeader", "speechBubbles_validationFailedMessage"]).then(function(data){ + var header = data[0]; + var message = data[1]; + notificationsService.error(header, message); }); }); @@ -135,11 +146,110 @@ theme: "chrome", showPrintMargin: false, advanced: { - fontSize: '14px' + fontSize: '14px', + enableSnippets: false, //The Razor mode snippets are awful (Need a way to override these) + enableBasicAutocompletion: true, + enableLiveAutocompletion: false }, onLoad: function(_editor) { vm.editor = _editor; + //Update the auto-complete method to use ctrl+alt+space + _editor.commands.bindKey("ctrl-alt-space", "startAutocomplete"); + + //Unassigns the keybinding (That was previously auto-complete) + //As conflicts with our own tree search shortcut + _editor.commands.bindKey("ctrl-space", null); + + // Assign new keybinding + _editor.commands.addCommands([ + //Disable (alt+shift+K) + //Conflicts with our own show shortcuts dialog - this overrides it + { + name: 'unSelectOrFindPrevious', + bindKey: 'Alt-Shift-K', + exec: function() { + //Toggle the show keyboard shortcuts overlay + $scope.$apply(function(){ + vm.showKeyboardShortcut = !vm.showKeyboardShortcut; + }); + + }, + readOnly: true + }, + { + name: 'insertUmbracoValue', + bindKey: 'Alt-Shift-V', + exec: function() { + $scope.$apply(function(){ + openPageFieldOverlay(); + }); + }, + readOnly: true + }, + { + name: 'insertPartialView', + bindKey: 'Alt-Shift-P', + exec: function() { + $scope.$apply(function(){ + openPartialOverlay(); + }); + }, + readOnly: true + }, + { + name: 'insertDictionary', + bindKey: 'Alt-Shift-D', + exec: function() { + $scope.$apply(function(){ + openDictionaryItemOverlay(); + }); + }, + readOnly: true + }, + { + name: 'insertUmbracoMacro', + bindKey: 'Alt-Shift-M', + exec: function() { + $scope.$apply(function(){ + openMacroOverlay(); + }); + }, + readOnly: true + }, + { + name: 'insertQuery', + bindKey: 'Alt-Shift-Q', + exec: function() { + $scope.$apply(function(){ + openQueryBuilderOverlay(); + }); + }, + readOnly: true + }, + { + name: 'insertSection', + bindKey: 'Alt-Shift-S', + exec: function() { + $scope.$apply(function(){ + openSectionsOverlay(); + }); + }, + readOnly: true + }, + { + name: 'chooseMasterTemplate', + bindKey: 'Alt-Shift-T', + exec: function() { + $scope.$apply(function(){ + openMasterTemplateOverlay(); + }); + }, + readOnly: true + }, + + ]); + // initial cursor placement // Keep cursor in name field if we are create a new template // else set the cursor at the bottom of the code editor diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.html b/src/Umbraco.Web.UI.Client/src/views/templates/edit.html index e747a56138..ec8ca3e9b4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.html @@ -99,6 +99,15 @@ + + + + + + + diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml index fb032a7f22..b7ba94c243 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml @@ -526,6 +526,16 @@ Brug listevisning Tillad på rodniveau + + Comment/Uncomment lines + Remove line + Copy Lines Up + Copy Lines Down + Move Lines Up + Move Lines Down + + General + Editor diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml index 3f317ad407..c3aac3a243 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml @@ -100,6 +100,8 @@ Show styles Insert table Generate models + Undo + Redo To change the document type for the selected content, first select from the list of valid types for this location. @@ -558,6 +560,16 @@ Toggle list view Toggle allow as root + + Comment/Uncomment lines + Remove line + Copy Lines Up + Copy Lines Down + Move Lines Up + Move Lines Down + + General + Editor diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml index aa9f33695d..7139d0e398 100644 --- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml @@ -553,6 +553,16 @@ Toggle list view Toggle allow as root + + Comment/Uncomment lines + Remove line + Copy Lines Up + Copy Lines Down + Move Lines Up + Move Lines Down + + General + Editor Background color