Adds RTE and stylesheet services

This commit is contained in:
perploug
2013-10-03 20:57:36 +02:00
parent 14e1e741ed
commit a3d77b7e72
18 changed files with 486 additions and 17 deletions

View File

@@ -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
* <pre>
* stylesheetResource.getAll()
* .then(function(stylesheets) {
* alert('its here!');
* });
* </pre>
*
* @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);

View File

@@ -1,3 +1,5 @@
<div ng-controller="Umbraco.Editors.RTEController" class="umb-editor umb-rte">
<textarea ng-model="model.value" rows="10" id="{{model.alias}}_rte"></textarea>
{{model | json}}
</div>

View File

@@ -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);
}
};
});

View File

@@ -0,0 +1,35 @@
<div ng-controller="Umbraco.PrevalueEditors.RteController">
<umb-control-group label="Toolbar">
<div ng-repeat="cmd in tinyMceConfig.commands">
<input type="checkbox"
ng-checked="selected(cmd.frontEndCommand, model.value.toolbar)"
ng-model="cmd.selected"
ng-change="selectCommand(cmd)"
/>
<img src="{{cmd.icon}}" />
{{cmd.frontEndCommand}}
</div>
</umb-control-group>
<umb-control-group label="Stylesheets">
<div ng-repeat="css in stylesheets">
<input type="checkbox"
ng-checked="selected(css.path, model.value.stylesheets)"
ng-model="css.selected"
ng-change="selectStylesheet(css)"
/>
{{css.name}}
</div>
</umb-control-group>
<umb-control-group label="Dimensions">
<input type="number" ng-model="model.value.dimensions.height" class="umb-editor-tiny" placeholder="Height" /> x <input type="number" ng-model="model.value.dimensions.width" class="umb-editor umb-editor-tiny" placeholder="Width" /> Pixels
</umb-control-group>
{{model.value | json}}
{{tinyMceConfig | json}}
</div>

View File

@@ -81,25 +81,25 @@
<command>
<umbracoAlias>JustifyLeft</umbracoAlias>
<icon>images/editor/justifyleft.gif</icon>
<tinyMceCommand value="" userInterface="false" frontendCommand="justifyleft">justifyleft</tinyMceCommand>
<tinyMceCommand value="" userInterface="false" frontendCommand="alignleft">justifyleft</tinyMceCommand>
<priority>31</priority>
</command>
<command>
<umbracoAlias>JustifyCenter</umbracoAlias>
<icon>images/editor/justifycenter.gif</icon>
<tinyMceCommand value="" userInterface="false" frontendCommand="justifycenter">justifycenter</tinyMceCommand>
<tinyMceCommand value="" userInterface="false" frontendCommand="aligncenter">justifycenter</tinyMceCommand>
<priority>32</priority>
</command>
<command>
<umbracoAlias>JustifyRight</umbracoAlias>
<icon>images/editor/justifyright.gif</icon>
<tinyMceCommand value="" userInterface="false" frontendCommand="justifyright">justifyright</tinyMceCommand>
<tinyMceCommand value="" userInterface="false" frontendCommand="alignright">justifyright</tinyMceCommand>
<priority>33</priority>
</command>
<command>
<umbracoAlias>JustifyFull</umbracoAlias>
<icon>images/editor/justifyfull.gif</icon>
<tinyMceCommand value="" userInterface="false" frontendCommand="justifyfull">justifyfull</tinyMceCommand>
<tinyMceCommand value="" userInterface="false" frontendCommand="alignfull">justifyfull</tinyMceCommand>
<priority>34</priority>
</command>
@@ -147,29 +147,33 @@
<priority>53</priority>
</command>
<command>
<umbracoAlias>mceImage</umbracoAlias>
<icon>images/editor/image.gif</icon>
<tinyMceCommand value="" userInterface="true" frontendCommand="image">image</tinyMceCommand>
<priority>61</priority>
</command>
<command>
<umbracoAlias>mceImage</umbracoAlias>
<icon>images/editor/image.gif</icon>
<tinyMceCommand value="" userInterface="true" frontendCommand="umbmediapicker">image</tinyMceCommand>
<priority>61</priority>
</command>
<command>
<umbracoAlias>umbracomacro</umbracoAlias>
<icon>images/editor/insMacro.gif</icon>
<tinyMceCommand value="" userInterface="true" frontendCommand="mceUmbracomacro">umbracomacro</tinyMceCommand>
<tinyMceCommand value="" userInterface="true" frontendCommand="umbmacro">umbracomacro</tinyMceCommand>
<priority>62</priority>
</command>
<command>
<umbracoAlias>mceInsertTable</umbracoAlias>
<icon>images/editor/table.gif</icon>
<tinyMceCommand value="" userInterface="true" frontendCommand="table">table</tinyMceCommand>
<priority>63</priority>
</command>
<command>
<umbracoAlias>umbracoembed</umbracoAlias>
<icon>images/editor/media.gif</icon>
<tinyMceCommand value="" userInterface="true" frontendCommand="mceUmbracoEmbed">umbracoembed</tinyMceCommand>
<tinyMceCommand value="" userInterface="true" frontendCommand="umbembeddialog">umbracoembed</tinyMceCommand>
<priority>66</priority>
</command>
<command>
@@ -207,15 +211,18 @@
</command>
</commands>
<plugins>
<plugin loadOnFrontend="true">code</plugin>
<plugin loadOnFrontend="true">paste</plugin>
<plugin loadOnFrontend="true">inlinepopups</plugin>
<plugin loadOnFrontend="true">noneditable</plugin>
<plugin loadOnFrontend="true">table</plugin>
<plugin loadOnFrontend="false">inlinepopups</plugin>
<plugin loadOnFrontend="false">noneditable</plugin>
<plugin loadOnFrontend="false">table</plugin>
<plugin loadOnFrontend="false">umbracomacro</plugin>
<!--<plugin loadOnFrontend="false">advimage</plugin>-->
<plugin loadOnFrontend="false">advlink</plugin>
<plugin loadOnFrontend="false">umbracocss</plugin>
<plugin loadOnFrontend="false">umbracoembed</plugin>
<plugin loadOnFrontend="false">umbracoembed</plugin>
<!--<plugin loadOnFrontend="false">media</plugin>-->
<plugin loadOnFrontend="false">umbracoimg</plugin>
<plugin loadOnFrontend="false">spellchecker</plugin>

View File

@@ -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<DashboardController>("GetDashboard")},
{"logApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<LogController>("GetEntityLog")},
{"memberApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<MemberController>("GetByLogin")},
{"rteApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<RichTextPreValueController>("GetConfiguration")},
{"stylesheetApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<StylesheetController>("GetAll")},
{"publishedContentApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<PublishedContentController>("GetUrl")}
}
},
{

View File

@@ -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
{
/// <summary>
/// The API controller used for retrieving available stylesheets
/// </summary>
[PluginController("UmbracoApi")]
public class StylesheetController : UmbracoAuthorizedJsonController
{
public IEnumerable<Stylesheet> GetAll()
{
return StyleSheet.GetAll()
.Select(x =>
new Stylesheet() {
Name = x.Text,
Id = x.Id,
Path = SystemDirectories.Css + "/" + x.Text + ".css"
});
}
public IEnumerable<StylesheetRule> 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 });
}
}
}

View File

@@ -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; }
}
}

View File

@@ -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<RichTextEditorPlugin> Plugins { get; set; }
[DataMember(Name = "commands")]
public IEnumerable<RichTextEditorCommand> Commands { get; set; }
[DataMember(Name = "validElements")]
public string ValidElements { get; set; }
[DataMember(Name = "inValidElements")]
public string InvalidElements { get; set; }
[DataMember(Name = "customConfig")]
public IDictionary<string,string> CustomConfig { get; set; }
}
}

View File

@@ -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; }
}
}

View File

@@ -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; }
}
}

View File

@@ -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; }
}
}

View File

@@ -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
{
/// <summary>
/// ApiController to provide RTE configuration with available plugins and commands from the RTE config
/// </summary>
[PluginController("UmbracoApi")]
public class RichTextPreValueController : UmbracoAuthorizedJsonController
{
private static bool _init = false;
private static Dictionary<string, RichTextEditorCommand> _commands = new Dictionary<string,RichTextEditorCommand>();
private static Dictionary<string, RichTextEditorPlugin> _plugins = new Dictionary<string, RichTextEditorPlugin>();
private static Dictionary<string, string> _configOptions = new Dictionary<string, string>();
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;
}
}
}

View File

@@ -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"});
}
}
}

View File

@@ -17,6 +17,12 @@ namespace Umbraco.Web.PropertyEditors
return new RichTextPropertyValueEditor(base.CreateValueEditor());
}
protected override PreValueEditor CreatePreValueEditor()
{
return new RichTextPreValueEditor();
}
/// <summary>
/// A custom value editor to ensure that macro syntax is parsed when being persisted and formatted correctly for display in the editor
/// </summary>

View File

@@ -312,11 +312,18 @@
<Compile Include="Editors\DataTypeValidateAttribute.cs" />
<Compile Include="Editors\LogController.cs" />
<Compile Include="Editors\MacroController.cs" />
<Compile Include="Editors\PublishedContentController.cs" />
<Compile Include="Models\ContentEditing\StyleSheet.cs" />
<Compile Include="Editors\StylesheetController.cs" />
<Compile Include="Models\ContentEditing\AuditLog.cs" />
<Compile Include="Models\ContentEditing\MoveOrCopy.cs" />
<Compile Include="Models\ContentEditing\MacroParameter.cs" />
<Compile Include="Models\ContentEditing\MemberDisplay.cs" />
<Compile Include="Models\ContentEditing\MemberSave.cs" />
<Compile Include="Models\ContentEditing\RichTextEditorCommand.cs" />
<Compile Include="Models\ContentEditing\RichTextEditorConfiguration.cs" />
<Compile Include="Models\ContentEditing\RichTextEditorPlugin.cs" />
<Compile Include="Models\ContentEditing\StylesheetRule.cs" />
<Compile Include="Models\ContentEditing\UmbracoEntityTypes.cs" />
<Compile Include="Models\ContentEditing\AuditLogType.cs" />
<Compile Include="Models\Mapping\LogModelMapper.cs" />
@@ -360,6 +367,8 @@
<Compile Include="PropertyEditors\PublishValuesMultipleValueEditor.cs" />
<Compile Include="PropertyEditors\DropDownMultipleWithKeysPropertyEditor.cs" />
<Compile Include="PropertyEditors\RadioButtonsPropertyEditor.cs" />
<Compile Include="PropertyEditors\RichTextPreValueController.cs" />
<Compile Include="PropertyEditors\RichTextPreValueEditor.cs" />
<Compile Include="PropertyEditors\TagsPropertyEditor.cs" />
<Compile Include="PropertyEditors\UserPickerPropertyEditor.cs" />
<Compile Include="PropertyEditors\ValueListPreValueEditor.cs" />