diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/codefile.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/codefile.resource.js index 7cd55b268a..bb1dad1dbd 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/codefile.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/codefile.resource.js @@ -243,6 +243,77 @@ function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) { "PostCreateContainer", { type: type, parentId: parentId, name: encodeURIComponent(name) })), 'Failed to create a folder under parent id ' + parentId); + }, + + /** + * @ngdoc method + * @name umbraco.resources.codefileResource#interpolateStylesheetRules + * @methodOf umbraco.resources.codefileResource + * + * @description + * Takes all rich text editor styling rules and turns them into css + * + * ##usage + *
+         * codefileResource.interpolateStylesheetRules(".box{background:purple;}", "[{name: "heading", selector: "h1", styles: "color: red"}]")
+         *    .then(function(data) {
+         *        alert('its here!');
+         *    });
+         * 
+ * + * @param {string} content The style sheet content. + * @param {string} rules The rich text editor rules + * @returns {Promise} resourcePromise object. + * + */ + interpolateStylesheetRules: function (content, rules) { + var payload = { + content: content, + rules: rules + }; + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "codeFileApiBaseUrl", + "PostInterpolateStylesheetRules"), + payload), + "Failed to interpolate sheet rules"); + }, + + /** + * @ngdoc method + * @name umbraco.resources.codefileResource#extractStylesheetRules + * @methodOf umbraco.resources.codefileResource + * + * @description + * Find all rich text editor styles in the style sheets and turns them into "rules" + * + * ##usage + *
+         * 
+         * var conntent
+         * codefileResource.extractStylesheetRules(".box{background:purple;}")
+         *    .then(function(data) {
+         *        alert('its here!');
+         *    });
+         * 
+ * + * @param {string} content The style sheet content. + * @returns {Promise} resourcePromise object. + * + */ + extractStylesheetRules: function(content) { + var payload = { + content: content, + rules: null + }; + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "codeFileApiBaseUrl", + "PostExtractStylesheetRules"), + payload), + "Failed to extract style sheet rules"); } }; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less index 407cfaf6a7..3b49dceeb2 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation.less @@ -43,7 +43,7 @@ font-size: 24px; display: block; text-align: center; - margin-bottom: 5px; + margin-bottom: 7px; } .umb-sub-views-nav-item-text { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-stylesheet.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-stylesheet.less index 31824590e8..59ded555a6 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-stylesheet.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-stylesheet.less @@ -8,6 +8,7 @@ margin: 10px 0 !important; background: @gray-10; cursor: pointer; + border-radius: @baseBorderRadius; } .umb-stylesheet-rules__listitem i { diff --git a/src/Umbraco.Web.UI.Client/src/views/stylesheets/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/stylesheets/create.controller.js index 229587cc63..8695935062 100644 --- a/src/Umbraco.Web.UI.Client/src/views/stylesheets/create.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/stylesheets/create.controller.js @@ -7,11 +7,17 @@ var node = $scope.dialogOptions.currentNode; vm.createFile = createFile; + vm.createRichtextStyle = createRichtextStyle; function createFile() { $location.path("/settings/stylesheets/edit/" + node.id).search("create", "true"); navigationService.hideMenu(); } + + function createRichtextStyle() { + $location.path("/settings/stylesheets/edit/" + node.id).search("create", "true").search("rtestyle", "true"); + navigationService.hideMenu(); + } } angular.module("umbraco").controller("Umbraco.Editors.StyleSheets.CreateController", StyleSheetsCreateController); diff --git a/src/Umbraco.Web.UI.Client/src/views/stylesheets/create.html b/src/Umbraco.Web.UI.Client/src/views/stylesheets/create.html index 82854635f9..c735d2fe3c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/stylesheets/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/stylesheets/create.html @@ -10,6 +10,12 @@ New style sheet file +
  • + + + New richtext style sheet file + +
  • diff --git a/src/Umbraco.Web.UI.Client/src/views/stylesheets/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/stylesheets/edit.controller.js index 2705294d54..a05836be06 100644 --- a/src/Umbraco.Web.UI.Client/src/views/stylesheets/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/stylesheets/edit.controller.js @@ -12,24 +12,6 @@ vm.page.menu.currentNode = null; vm.page.saveButtonState = "init"; - localizationService.localizeMany(["stylesheet_tabCode", "stylesheet_tabRules"]).then(function (data) { - vm.page.navigation = [ - { - "name": data[0], - "alias": "code", - "icon": "icon-brackets", - "view": "views/stylesheets/views/code/code.html", - "active": true - }, - { - "name": data[1], - "alias": "rules", - "icon": "icon-font", - "view": "views/stylesheets/views/rules/rules.html" - } - ]; - }); - //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; @@ -45,7 +27,10 @@ vm.page.keyboardShortcutsOverview.push(shortcuts); }); - vm.stylesheet = {}; + vm.stylesheet = { + content: "", + rules: [] + }; // bind functions to view model vm.save = interpolateAndSave; @@ -139,16 +124,47 @@ if ($routeParams.create) { codefileResource.getScaffold("stylesheets", $routeParams.id).then(function (stylesheet) { + const mode = $routeParams.rtestyle ? "RTE" : null; ready(stylesheet, false); + generateNavigation(mode); }); } else { codefileResource.getByPath('stylesheets', $routeParams.id).then(function (stylesheet) { ready(stylesheet, true); + extractRules().then(rules => { + vm.stylesheet.rules = rules; + const mode = rules && rules.length > 0 ? "RTE" : null; + generateNavigation(mode); + }); }); } } + function generateNavigation(mode) { + localizationService.localizeMany(["stylesheet_tabRules", "stylesheet_tabCode"]).then(function (data) { + vm.page.navigation = [ + { + "name": data[0], + "alias": "rules", + "icon": "icon-font", + "view": "views/stylesheets/views/rules/rules.html" + }, + { + "name": data[1], + "alias": "code", + "icon": "icon-brackets", + "view": "views/stylesheets/views/code/code.html" + } + ]; + if(mode === "RTE") { + vm.page.navigation[0].active = true; + } else { + vm.page.navigation[1].active = true; + } + }); + } + function ready(stylesheet, syncTree) { vm.page.loading = false; @@ -240,31 +256,11 @@ } function interpolateRules() { - var payload = { - content: vm.stylesheet.content, - rules: vm.stylesheet.rules - }; - return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "codeFileApiBaseUrl", - "PostInterpolateStylesheetRules"), - payload), - "Failed to interpolate sheet rules"); + return codefileResource.interpolateStylesheetRules(vm.stylesheet.content, vm.stylesheet.rules); } function extractRules() { - var payload = { - content: vm.stylesheet.content, - rules: null - }; - return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "codeFileApiBaseUrl", - "PostExtractStylesheetRules"), - payload), - "Failed to extract style sheet rules"); + return codefileResource.extractStylesheetRules(vm.stylesheet.content); } $scope.selectApp = function (app) { diff --git a/src/Umbraco.Web.UI.Client/src/views/stylesheets/infiniteeditors/richtextrule/richtextrule.controller.js b/src/Umbraco.Web.UI.Client/src/views/stylesheets/infiniteeditors/richtextrule/richtextrule.controller.js new file mode 100644 index 0000000000..092cdaa55e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/stylesheets/infiniteeditors/richtextrule/richtextrule.controller.js @@ -0,0 +1,27 @@ +(function() { + "use strict"; + + function RichTextRuleController($scope, formHelper) { + + const vm = this; + + vm.submit = submit; + vm.close = close; + + function submit() { + if ($scope.model && $scope.model.submit && formHelper.submitForm({scope: $scope})) { + $scope.model.submit($scope.model); + } + } + + function close() { + if ($scope.model && $scope.model.close) { + $scope.model.close(); + } + } + + } + + angular.module("umbraco").controller("Umbraco.Editors.RichTextRuleController", RichTextRuleController); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/stylesheets/infiniteeditors/richtextrule/richtextrule.html b/src/Umbraco.Web.UI.Client/src/views/stylesheets/infiniteeditors/richtextrule/richtextrule.html new file mode 100644 index 0000000000..a36f3ef6a2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/stylesheets/infiniteeditors/richtextrule/richtextrule.html @@ -0,0 +1,72 @@ +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    + a b c d e f g h i j k l m n o p q r s t u v w x t z +
    + A B C D E F G H I J K L M N O P Q R S T U V W X Y Z +
    + 1 2 3 4 5 6 7 8 9 0 € £ $ % & (.,;:'\"!?) +
    + Just keep examining every bid quoted for zinc etchings. +
    +
    + +
    +
    + +
    + + + + + + + + + + ' +
    + +
    + +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.controller.js b/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.controller.js index 28d1724b64..b3aeedeb6e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.controller.js @@ -1,5 +1,5 @@ angular.module("umbraco").controller("Umbraco.Editors.StyleSheets.RulesController", - function ($scope, localizationService) { + function ($scope, localizationService, editorService) { $scope.sortableOptions = { axis: 'y', containment: 'parent', @@ -16,6 +16,9 @@ angular.module("umbraco").controller("Umbraco.Editors.StyleSheets.RulesControlle evt.preventDefault(); openOverlay({}, $scope.labels.addRule, (newRule) => { + if(!$scope.model.stylesheet.rules) { + $scope.model.stylesheet.rules = []; + } $scope.model.stylesheet.rules.push(newRule); setDirty(); }); @@ -40,17 +43,23 @@ angular.module("umbraco").controller("Umbraco.Editors.StyleSheets.RulesControlle } function openOverlay(rule, title, onSubmit) { - $scope.model.overlay = { + + const ruleDialog = { title: title, - submit: function (model) { + rule: _.clone(rule), + view: "views/stylesheets/infiniteeditors/richtextrule/richtextrule.html", + size: "small", + submit: function(model) { onSubmit(model.rule); - $scope.model.overlay = null; + editorService.close(); }, - close: function (oldModel) { - $scope.model.overlay = null; - }, - rule: _.clone(rule) + close: function() { + editorService.close(); + } }; + + editorService.open(ruleDialog); + } function setDirty() { diff --git a/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.html b/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.html index 17b52f064e..018d4d3741 100644 --- a/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.html +++ b/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.html @@ -18,24 +18,15 @@ -
    - -
    + + - - - - - - - - - - - - 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 a7a7c7d8e5..a75fe839ab 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -309,13 +309,14 @@ Document Type without a template New folder New data type - New JavaScript file + New JavaScript file New empty partial view New partial view macro New partial view from snippet New partial view macro from snippet New partial view macro (without macro) New style sheet file + New Rich Text Editor style sheet file Browse your website @@ -1357,7 +1358,9 @@ To manage your website, simply open the Umbraco back office and start adding con Styles The CSS that should be applied in the rich text editor, e.g. "color:red;" Code - Editor + Rich Text Editor + Preview + How the text will look like in the rich text editor. Edit template