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 + *
+ * + ***/ .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 + *Close + *Fallback value + * + * + * + * + * + *
+ * 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 @@
-