diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/stylesheet.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/stylesheet.resource.js
new file mode 100644
index 0000000000..8716fdf29a
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/common/resources/stylesheet.resource.js
@@ -0,0 +1,43 @@
+/**
+ * @ngdoc service
+ * @name umbraco.resources.stylesheetResource
+ * @description service to retrieve available stylesheets
+ *
+ *
+ **/
+function stylesheetResource($q, $http, umbRequestHelper) {
+
+ //the factory object returned
+ return {
+
+ /**
+ * @ngdoc method
+ * @name umbraco.resources.stylesheetResource#getAll
+ * @methodOf umbraco.resources.stylesheetResource
+ *
+ * @description
+ * Gets all registered stylesheets
+ *
+ * ##usage
+ *
+ * stylesheetResource.getAll()
+ * .then(function(stylesheets) {
+ * alert('its here!');
+ * });
+ *
+ *
+ * @returns {Promise} resourcePromise object containing the stylesheets.
+ *
+ */
+ getAll: function () {
+ return umbRequestHelper.resourcePromise(
+ $http.get(
+ umbRequestHelper.getApiUrl(
+ "stylesheetApiBaseUrl",
+ "GetAll")),
+ 'Failed to retreive stylesheets ');
+ }
+ };
+}
+
+angular.module('umbraco.resources').factory('stylesheetResource', stylesheetResource);
diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/rte.controller.js b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/rte.controller.js
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/rte.html b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/rte.html
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html
index 51a07d5335..1848358833 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.html
@@ -1,3 +1,5 @@
+
+ {{model | json}}
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.controller.js
new file mode 100644
index 0000000000..84c502c03a
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.controller.js
@@ -0,0 +1,48 @@
+angular.module("umbraco").controller("Umbraco.PrevalueEditors.RteController",
+ function ($scope, $timeout, tinyMceService, stylesheetResource) {
+ var cfg = {};
+ cfg.toolbar = ["code", "bold", "italic", "umbracocss","alignleft", "aligncenter", "alignright", "bullist","numlist", "outdent", "indent", "link", "image", ",umbmediapicker", "umbembeddialog", "umbmacro"];
+ cfg.stylesheets = [];
+ cfg.dimensions = {height: 400, width: 600};
+
+ if($scope.model.value){
+ if(angular.isString($scope.model.value)){
+ $scope.model.value = angular.fromJson($scope.model.value);
+ }
+ angular.extend($scope.model.value, cfg);
+ }else{
+ $scope.model.value = cfg;
+ }
+
+ tinyMceService.configuration().then(function(config){
+ $scope.tinyMceConfig = config;
+ });
+
+ stylesheetResource.getAll().then(function(stylesheets){
+ $scope.stylesheets = stylesheets;
+ });
+
+ $scope.selected = function(alias, lookup){
+ return lookup.indexOf(alias) >= 0;
+ };
+
+ $scope.selectCommand = function(command){
+ var index = $scope.model.value.toolbar.indexOf(command.frontEndCommand);
+
+ if(command.selected && index === -1){
+ $scope.model.value.toolbar.push(command.frontEndCommand);
+ }else if(index >= 0){
+ $scope.model.value.toolbar.splice(index, 1);
+ }
+ };
+
+ $scope.selectStylesheet = function(css){
+ var index = $scope.model.value.stylesheets.indexOf(css.path);
+
+ if(css.selected && index === -1){
+ $scope.model.value.stylesheets.push(css.path);
+ }else if(index >= 0){
+ $scope.model.value.stylesheets.splice(index, 1);
+ }
+ };
+ });
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html
new file mode 100644
index 0000000000..407dc92578
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html
@@ -0,0 +1,35 @@
+
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/config/tinyMceConfig.config b/src/Umbraco.Web.UI/config/tinyMceConfig.config
index 0a3982b343..6ff945d6d4 100644
--- a/src/Umbraco.Web.UI/config/tinyMceConfig.config
+++ b/src/Umbraco.Web.UI/config/tinyMceConfig.config
@@ -81,25 +81,25 @@
JustifyLeft
images/editor/justifyleft.gif
- justifyleft
+ justifyleft
31
JustifyCenter
images/editor/justifycenter.gif
- justifycenter
+ justifycenter
32
JustifyRight
images/editor/justifyright.gif
- justifyright
+ justifyright
33
JustifyFull
images/editor/justifyfull.gif
- justifyfull
+ justifyfull
34
@@ -147,29 +147,33 @@
53
-
- mceImage
- images/editor/image.gif
- image
- 61
-
+
+ mceImage
+ images/editor/image.gif
+ image
+ 61
+
umbracomacro
images/editor/insMacro.gif
- umbracomacro
+ umbracomacro
62
+
+
+
mceInsertTable
images/editor/table.gif
table
63
+
umbracoembed
images/editor/media.gif
- umbracoembed
+ umbracoembed
66
@@ -207,15 +211,18 @@
+ code
paste
- inlinepopups
- noneditable
- table
+ inlinepopups
+ noneditable
+ table
+
umbracomacro
-
+
advlink
umbracocss
- umbracoembed
+ umbracoembed
+
umbracoimg
spellchecker
diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs
index 641d809ca7..69f79af521 100644
--- a/src/Umbraco.Web/Editors/BackOfficeController.cs
+++ b/src/Umbraco.Web/Editors/BackOfficeController.cs
@@ -9,6 +9,7 @@ using Umbraco.Core;
using Umbraco.Web.Mvc;
using Umbraco.Web.Trees;
using Umbraco.Web.UI.JavaScript;
+using Umbraco.Web.PropertyEditors;
namespace Umbraco.Web.Editors
{
@@ -74,6 +75,9 @@ namespace Umbraco.Web.Editors
{"dashboardApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl("GetDashboard")},
{"logApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl("GetEntityLog")},
{"memberApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl("GetByLogin")},
+ {"rteApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl("GetConfiguration")},
+ {"stylesheetApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl("GetAll")},
+ {"publishedContentApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl("GetUrl")}
}
},
{
diff --git a/src/Umbraco.Web/Editors/StylesheetController.cs b/src/Umbraco.Web/Editors/StylesheetController.cs
new file mode 100644
index 0000000000..842af1cd96
--- /dev/null
+++ b/src/Umbraco.Web/Editors/StylesheetController.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web.Http;
+using umbraco.cms.businesslogic.web;
+using Umbraco.Core.IO;
+using Umbraco.Web.Models.ContentEditing;
+using Umbraco.Web.Mvc;
+
+namespace Umbraco.Web.Editors
+{
+ ///
+ /// The API controller used for retrieving available stylesheets
+ ///
+ [PluginController("UmbracoApi")]
+ public class StylesheetController : UmbracoAuthorizedJsonController
+ {
+ public IEnumerable GetAll()
+ {
+ return StyleSheet.GetAll()
+ .Select(x =>
+ new Stylesheet() {
+ Name = x.Text,
+ Id = x.Id,
+ Path = SystemDirectories.Css + "/" + x.Text + ".css"
+ });
+ }
+
+ public IEnumerable GetRules(int id)
+ {
+ var css = new StyleSheet(id);
+ if (css == null)
+ throw new HttpResponseException(System.Net.HttpStatusCode.NotFound);
+
+ return css.Properties.Select(x => new StylesheetRule() { Id = x.Id, Name = x.Text, Selector = x.Alias });
+ }
+ }
+}
diff --git a/src/Umbraco.Web/Models/ContentEditing/RichTextEditorCommand.cs b/src/Umbraco.Web/Models/ContentEditing/RichTextEditorCommand.cs
new file mode 100644
index 0000000000..646046ae56
--- /dev/null
+++ b/src/Umbraco.Web/Models/ContentEditing/RichTextEditorCommand.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Umbraco.Web.Models.ContentEditing
+{
+ [DataContract(Name = "richtexteditorcommand", Namespace = "")]
+ public class RichTextEditorCommand
+ {
+ [DataMember(Name = "icon")]
+ public string Icon { get; set; }
+
+ [DataMember(Name = "command")]
+ public string Command { get; set; }
+
+ [DataMember(Name = "alias")]
+ public string Alias { get; set; }
+
+ [DataMember(Name = "userInterface")]
+ public string UserInterface { get; set; }
+
+ [DataMember(Name = "frontEndCommand")]
+ public string FrontendCommand { get; set; }
+
+ [DataMember(Name = "value")]
+ public string Value { get; set; }
+
+ [DataMember(Name = "priority")]
+ public int Priority { get; set; }
+
+ [DataMember(Name = "isStylePicker")]
+ public bool IsStylePicker { get; set; }
+ }
+}
diff --git a/src/Umbraco.Web/Models/ContentEditing/RichTextEditorConfiguration.cs b/src/Umbraco.Web/Models/ContentEditing/RichTextEditorConfiguration.cs
new file mode 100644
index 0000000000..380780b6d8
--- /dev/null
+++ b/src/Umbraco.Web/Models/ContentEditing/RichTextEditorConfiguration.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Umbraco.Web.Models.ContentEditing
+{
+ [DataContract(Name = "richtexteditorconfiguration", Namespace = "")]
+ public class RichTextEditorConfiguration
+ {
+ [DataMember(Name = "plugins")]
+ public IEnumerable Plugins { get; set; }
+
+ [DataMember(Name = "commands")]
+ public IEnumerable Commands { get; set; }
+
+ [DataMember(Name = "validElements")]
+ public string ValidElements { get; set; }
+
+ [DataMember(Name = "inValidElements")]
+ public string InvalidElements { get; set; }
+
+ [DataMember(Name = "customConfig")]
+ public IDictionary CustomConfig { get; set; }
+ }
+}
diff --git a/src/Umbraco.Web/Models/ContentEditing/RichTextEditorPlugin.cs b/src/Umbraco.Web/Models/ContentEditing/RichTextEditorPlugin.cs
new file mode 100644
index 0000000000..aec92a1eff
--- /dev/null
+++ b/src/Umbraco.Web/Models/ContentEditing/RichTextEditorPlugin.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Umbraco.Web.Models.ContentEditing
+{
+ [DataContract(Name = "richtexteditorplugin", Namespace = "")]
+ public class RichTextEditorPlugin
+ {
+ [DataMember(Name = "name")]
+ public string Name { get; set; }
+
+ [DataMember(Name = "useOnFrontend")]
+ public bool UseOnFrontend { get; set; }
+ }
+}
diff --git a/src/Umbraco.Web/Models/ContentEditing/StyleSheet.cs b/src/Umbraco.Web/Models/ContentEditing/StyleSheet.cs
new file mode 100644
index 0000000000..49141d80d5
--- /dev/null
+++ b/src/Umbraco.Web/Models/ContentEditing/StyleSheet.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace Umbraco.Web.Models.ContentEditing
+{
+ [DataContract(Name = "stylesheet", Namespace = "")]
+ public class Stylesheet
+ {
+ [DataMember(Name="name")]
+ public string Name { get; set; }
+
+ [DataMember(Name = "path")]
+ public string Path { get; set; }
+
+ [DataMember(Name = "id")]
+ public int Id { get; set; }
+ }
+}
diff --git a/src/Umbraco.Web/Models/ContentEditing/StylesheetRule.cs b/src/Umbraco.Web/Models/ContentEditing/StylesheetRule.cs
new file mode 100644
index 0000000000..9ef402dc89
--- /dev/null
+++ b/src/Umbraco.Web/Models/ContentEditing/StylesheetRule.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Umbraco.Web.Models.ContentEditing
+{
+ [DataContract(Name = "stylesheetRule", Namespace = "")]
+ public class StylesheetRule
+ {
+ [DataMember(Name = "name")]
+ public string Name { get; set; }
+
+ [DataMember(Name = "selector")]
+ public string Selector { get; set; }
+
+ [DataMember(Name = "id")]
+ public int Id { get; set; }
+ }
+}
diff --git a/src/Umbraco.Web/PropertyEditors/RichTextPreValueController.cs b/src/Umbraco.Web/PropertyEditors/RichTextPreValueController.cs
new file mode 100644
index 0000000000..33f8b61cb6
--- /dev/null
+++ b/src/Umbraco.Web/PropertyEditors/RichTextPreValueController.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+using Umbraco.Core.IO;
+using Umbraco.Web.Editors;
+using Umbraco.Web.Models.ContentEditing;
+using Umbraco.Web.Mvc;
+
+namespace Umbraco.Web.PropertyEditors
+{
+ ///
+ /// ApiController to provide RTE configuration with available plugins and commands from the RTE config
+ ///
+ [PluginController("UmbracoApi")]
+ public class RichTextPreValueController : UmbracoAuthorizedJsonController
+ {
+ private static bool _init = false;
+ private static Dictionary _commands = new Dictionary();
+ private static Dictionary _plugins = new Dictionary();
+ private static Dictionary _configOptions = new Dictionary();
+
+ private static string _invalidElements = "";
+ private static string _validElements = "";
+
+
+ public RichTextEditorConfiguration GetConfiguration()
+ {
+ if (!_init)
+ init();
+
+
+ RichTextEditorConfiguration config = new RichTextEditorConfiguration();
+ config.Plugins = _plugins.Values;
+ config.Commands = _commands.Values;
+ config.ValidElements = _validElements;
+ config.InvalidElements = _invalidElements;
+ config.CustomConfig = _configOptions;
+
+ return config;
+ }
+
+
+
+ private static void init()
+ {
+ // Load config
+ XmlDocument xd = new XmlDocument();
+ xd.Load(IOHelper.MapPath(SystemFiles.TinyMceConfig));
+
+ foreach (XmlNode n in xd.DocumentElement.SelectNodes("//command"))
+ {
+ var alias = n.SelectSingleNode("./umbracoAlias").FirstChild.Value.ToLower();
+
+ bool isStyle = false;
+ if (n.Attributes.GetNamedItem("isStyle") != null)
+ isStyle = bool.Parse(n.Attributes.GetNamedItem("isStyle").Value);
+
+ if(!_commands.ContainsKey(alias))
+ _commands.Add(
+ alias,
+ new RichTextEditorCommand()
+ {
+ IsStylePicker = isStyle,
+ Icon = n.SelectSingleNode("./icon").FirstChild.Value,
+ Command = n.SelectSingleNode("./tinyMceCommand").FirstChild.Value,
+ Alias = n.SelectSingleNode("./umbracoAlias").FirstChild.Value.ToLower(),
+ UserInterface = n.SelectSingleNode("./tinyMceCommand").Attributes.GetNamedItem("userInterface").Value,
+ FrontendCommand = n.SelectSingleNode("./tinyMceCommand").Attributes.GetNamedItem("frontendCommand").Value,
+ Value = n.SelectSingleNode("./tinyMceCommand").Attributes.GetNamedItem("value").Value,
+ Priority = int.Parse(n.SelectSingleNode("./priority").FirstChild.Value)
+ }
+ );
+ }
+
+
+ foreach (XmlNode n in xd.DocumentElement.SelectNodes("//plugin"))
+ {
+ if (!_plugins.ContainsKey(n.FirstChild.Value))
+ {
+ bool useOnFrontend = false;
+ if (n.Attributes.GetNamedItem("loadOnFrontend") != null)
+ useOnFrontend = bool.Parse(n.Attributes.GetNamedItem("loadOnFrontend").Value);
+
+ _plugins.Add(
+ n.FirstChild.Value.ToLower(),
+ new RichTextEditorPlugin(){
+ Name = n.FirstChild.Value,
+ UseOnFrontend = useOnFrontend});
+ }
+ }
+
+
+ foreach (XmlNode n in xd.DocumentElement.SelectNodes("//config"))
+ {
+ if (!_configOptions.ContainsKey(n.Attributes["key"].FirstChild.Value))
+ {
+ var value = "";
+ if (n.FirstChild != null)
+ value = n.FirstChild.Value;
+
+ _configOptions.Add(
+ n.Attributes["key"].FirstChild.Value.ToLower(),
+ value);
+ }
+ }
+
+ if (xd.DocumentElement.SelectSingleNode("./invalidElements") != null)
+ _invalidElements = xd.DocumentElement.SelectSingleNode("./invalidElements").FirstChild.Value;
+ if (xd.DocumentElement.SelectSingleNode("./validElements") != null)
+ {
+ string _val = xd.DocumentElement.SelectSingleNode("./validElements").FirstChild.Value.Replace("\r", "");
+ foreach (string s in _val.Split("\n".ToCharArray()))
+ _validElements += "'" + s + "' + \n";
+ _validElements = _validElements.Substring(0, _validElements.Length - 4);
+ }
+
+ _init = true;
+ }
+
+ }
+}
diff --git a/src/Umbraco.Web/PropertyEditors/RichTextPreValueEditor.cs b/src/Umbraco.Web/PropertyEditors/RichTextPreValueEditor.cs
new file mode 100644
index 0000000000..b8a5b497db
--- /dev/null
+++ b/src/Umbraco.Web/PropertyEditors/RichTextPreValueEditor.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Umbraco.Core.PropertyEditors;
+
+namespace Umbraco.Web.PropertyEditors
+{
+ //need to figure out how to use this...
+ internal class RichTextPreValueEditor : PreValueEditor
+ {
+ public RichTextPreValueEditor()
+ {
+ //use a custom editor too
+ Fields.Add(new PreValueField() {
+ View = "views/propertyeditors/rte/rte.prevalues.html",
+ HideLabel= true, Key="editor"});
+ }
+
+
+ }
+}
diff --git a/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs
index 77155bb470..5619743c8d 100644
--- a/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs
+++ b/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs
@@ -17,6 +17,12 @@ namespace Umbraco.Web.PropertyEditors
return new RichTextPropertyValueEditor(base.CreateValueEditor());
}
+ protected override PreValueEditor CreatePreValueEditor()
+ {
+ return new RichTextPreValueEditor();
+ }
+
+
///
/// A custom value editor to ensure that macro syntax is parsed when being persisted and formatted correctly for display in the editor
///
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index c11fa14d2c..8e79d6831b 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -312,11 +312,18 @@
+
+
+
+
+
+
+
@@ -360,6 +367,8 @@
+
+