Merge branch '7.0.0' of https://github.com/umbraco/Umbraco-CMS into 7.0.0
Conflicts: src/Umbraco.Web.UI.Client/src/routes.js
This commit is contained in:
@@ -293,7 +293,10 @@ namespace Umbraco.Core.Models
|
||||
/// <returns><see cref="Property"/> Value as a <see cref="TPassType"/></returns>
|
||||
public virtual TPassType GetValue<TPassType>(string propertyTypeAlias)
|
||||
{
|
||||
return (TPassType)Properties[propertyTypeAlias].Value;
|
||||
if (Properties[propertyTypeAlias].Value is TPassType)
|
||||
return (TPassType)Properties[propertyTypeAlias].Value;
|
||||
|
||||
return (TPassType)Convert.ChangeType(Properties[propertyTypeAlias].Value, typeof(TPassType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -78,6 +78,53 @@ namespace Umbraco.Core.Models
|
||||
return (propertyValueChanged && publishedState == PublishedState.Published) || contentDataChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the published db flag should be set to true for the current entity version and all other db
|
||||
/// versions should have their flag set to false.
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is determined by:
|
||||
/// * If a new version is being created and the entity is published
|
||||
/// * If the published state has changed and the entity is published OR the entity has been un-published.
|
||||
/// </remarks>
|
||||
internal static bool ShouldClearPublishedFlagForPreviousVersions(this IContent entity)
|
||||
{
|
||||
var publishedState = ((Content)entity).PublishedState;
|
||||
return entity.ShouldClearPublishedFlagForPreviousVersions(publishedState, entity.ShouldCreateNewVersion(publishedState));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the published db flag should be set to true for the current entity version and all other db
|
||||
/// versions should have their flag set to false.
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="publishedState"></param>
|
||||
/// <param name="isCreatingNewVersion"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is determined by:
|
||||
/// * If a new version is being created and the entity is published
|
||||
/// * If the published state has changed and the entity is published OR the entity has been un-published.
|
||||
/// </remarks>
|
||||
internal static bool ShouldClearPublishedFlagForPreviousVersions(this IContent entity, PublishedState publishedState, bool isCreatingNewVersion)
|
||||
{
|
||||
if (isCreatingNewVersion && entity.Published)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//If Published state has changed then previous versions should have their publish state reset.
|
||||
//If state has been changed to unpublished the previous versions publish state should also be reset.
|
||||
if (((ICanBeDirty)entity).IsPropertyDirty("Published") && (entity.Published || publishedState == PublishedState.Unpublished))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of the current contents ancestors, not including the content itself.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the pre-value data for a DataType
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Due to the legacy nature of the data that can be stored for pre-values, we have this class which encapsulates the 2 different
|
||||
/// ways that pre-values are stored: A string array or a Dictionary.
|
||||
///
|
||||
/// Most legacy property editors won't support the dictionary format but new property editors should always use the dictionary format.
|
||||
/// In order to get overrideable pre-values working we need a dictionary since we'll have to reference a pre-value by a key.
|
||||
/// </remarks>
|
||||
public class PreValueCollection
|
||||
{
|
||||
private IDictionary<string, object> _preValuesAsDictionary;
|
||||
private IEnumerable<string> _preValuesAsArray;
|
||||
public IEnumerable<string> PreValuesAsArray
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_preValuesAsArray == null)
|
||||
{
|
||||
throw new InvalidOperationException("The current pre-value collection is dictionary based, use the PreValuesAsDictionary property instead");
|
||||
}
|
||||
return _preValuesAsArray;
|
||||
}
|
||||
set { _preValuesAsArray = value; }
|
||||
}
|
||||
|
||||
public IDictionary<string, object> PreValuesAsDictionary
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_preValuesAsDictionary == null)
|
||||
{
|
||||
throw new InvalidOperationException("The current pre-value collection is array based, use the PreValuesAsArray property instead");
|
||||
}
|
||||
return _preValuesAsDictionary;
|
||||
}
|
||||
set { _preValuesAsDictionary = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if it is a dictionary based collection
|
||||
/// </summary>
|
||||
public bool IsDictionaryBased
|
||||
{
|
||||
get { return _preValuesAsDictionary != null; }
|
||||
}
|
||||
|
||||
public PreValueCollection(IEnumerable<string> preVals)
|
||||
{
|
||||
_preValuesAsArray = preVals;
|
||||
}
|
||||
|
||||
public PreValueCollection(IDictionary<string, object> preVals)
|
||||
{
|
||||
_preValuesAsDictionary = preVals;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,8 +64,15 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
else
|
||||
{
|
||||
var dt = (DateTime)property.Value;
|
||||
xmlNode.AppendChild(xd.CreateTextNode(dt.ToXmlString<DateTime>()));
|
||||
var date = property.Value.TryConvertTo<DateTime?>();
|
||||
if (date.Success == false || date.Result == null)
|
||||
{
|
||||
xmlNode.AppendChild(xd.CreateTextNode(string.Empty));
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlNode.AppendChild(xd.CreateTextNode(date.Result.ToXmlString<DateTime>()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -77,7 +77,14 @@ namespace Umbraco.Core
|
||||
/// <returns></returns>
|
||||
public static Attempt<object> TryConvertTo(this object input, Type destinationType)
|
||||
{
|
||||
if (input == null) return Attempt<object>.False;
|
||||
//if it is null and it is nullable, then return success with null
|
||||
if (input == null && destinationType.IsGenericType && destinationType.GetGenericTypeDefinition() == typeof (Nullable<>))
|
||||
{
|
||||
return new Attempt<object>(true, null);
|
||||
}
|
||||
|
||||
//if its not nullable then return false
|
||||
if (input == null) return Attempt<object>.False;
|
||||
|
||||
if (destinationType == typeof(object)) return new Attempt<object>(true, input);
|
||||
|
||||
|
||||
@@ -13,8 +13,9 @@ namespace Umbraco.Core.ObjectResolution
|
||||
internal static class Resolution
|
||||
{
|
||||
private static readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
|
||||
private volatile static bool _isFrozen;
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Occurs when resolution is frozen.
|
||||
/// </summary>
|
||||
/// <remarks>Occurs only once, since resolution can be frozen only once.</remarks>
|
||||
@@ -23,12 +24,17 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether resolution of objects is frozen.
|
||||
/// </summary>
|
||||
public static bool IsFrozen { get; private set; }
|
||||
|
||||
public static void EnsureIsFrozen()
|
||||
public static bool IsFrozen
|
||||
{
|
||||
if (!IsFrozen)
|
||||
get { return _isFrozen; }
|
||||
private set { _isFrozen = value; }
|
||||
}
|
||||
|
||||
public static void EnsureIsFrozen()
|
||||
{
|
||||
if (!_isFrozen)
|
||||
throw new InvalidOperationException("Resolution is not frozen, it is not yet possible to get values from it.");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -40,7 +46,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
get
|
||||
{
|
||||
IDisposable l = new WriteLock(_lock);
|
||||
if (Resolution.IsFrozen)
|
||||
if (_isFrozen)
|
||||
{
|
||||
l.Dispose();
|
||||
throw new InvalidOperationException("Resolution is frozen, it is not possible to configure it anymore.");
|
||||
@@ -73,13 +79,13 @@ namespace Umbraco.Core.ObjectResolution
|
||||
public DirtyBackdoor()
|
||||
{
|
||||
_lock = new WriteLock(_dirtyLock);
|
||||
_frozen = Resolution.IsFrozen;
|
||||
Resolution.IsFrozen = false;
|
||||
_frozen = _isFrozen;
|
||||
_isFrozen = false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Resolution.IsFrozen = _frozen;
|
||||
_isFrozen = _frozen;
|
||||
_lock.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -90,10 +96,10 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// <exception cref="InvalidOperationException">resolution is already frozen.</exception>
|
||||
public static void Freeze()
|
||||
{
|
||||
if (Resolution.IsFrozen)
|
||||
if (_isFrozen)
|
||||
throw new InvalidOperationException("Resolution is frozen. It is not possible to freeze it again.");
|
||||
|
||||
IsFrozen = true;
|
||||
_isFrozen = true;
|
||||
if (Frozen != null)
|
||||
Frozen(null, null);
|
||||
}
|
||||
@@ -104,7 +110,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// <remarks>To be used in unit tests.</remarks>
|
||||
internal static void Reset()
|
||||
{
|
||||
IsFrozen = false;
|
||||
_isFrozen = false;
|
||||
Frozen = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,8 +223,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 4, DataTypeId = -88, ControlId = new Guid(Constants.PropertyEditors.Textbox), DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 5, DataTypeId = -89, ControlId = new Guid(Constants.PropertyEditors.TextboxMultiple), DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 6, DataTypeId = -90, ControlId = new Guid(Constants.PropertyEditors.UploadField), DbType = "Nvarchar" });
|
||||
//Dropdown list
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 12, DataTypeId = -91, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 7, DataTypeId = -92, ControlId = new Guid(Constants.PropertyEditors.NoEdit), DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 8, DataTypeId = -36, ControlId = new Guid(Constants.PropertyEditors.DateTime), DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 9, DataTypeId = -37, ControlId = new Guid(Constants.PropertyEditors.ColorPicker), DbType = "Nvarchar" });
|
||||
@@ -234,24 +232,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 13, DataTypeId = -41, ControlId = new Guid(Constants.PropertyEditors.Date), DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -42, ControlId = new Guid(Constants.PropertyEditors.DropDownList), DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, ControlId = new Guid(Constants.PropertyEditors.CheckBoxList), DbType = "Nvarchar" });
|
||||
// Fix for rich text editor backwards compatibility -> 83722133-f80c-4273-bdb6-1befaa04a612 TinyMCE DataType
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 22, DataTypeId = -44, ControlId = new Guid("a3776494-0574-4d93-b7de-efdfdec6f2d1"), DbType = "Ntext" });
|
||||
//Radiobutton list
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 23, DataTypeId = -128, ControlId = new Guid("a52c7c1c-c330-476e-8605-d63d3b84b6a6"), DbType = "Nvarchar" });
|
||||
//Dropdown list multiple
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 24, DataTypeId = -129, ControlId = new Guid("928639ed-9c73-4028-920c-1e55dbb68783"), DbType = "Nvarchar" });
|
||||
//Dropdown list
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 25, DataTypeId = -130, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" });
|
||||
//Dropdown list
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 26, DataTypeId = -131, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" });
|
||||
//Dropdown list
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 27, DataTypeId = -132, ControlId = new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6"), DbType = "Nvarchar" });
|
||||
//No edit
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 28, DataTypeId = -133, ControlId = new Guid("6c738306-4c17-4d88-b9bd-6546f3771597"), DbType = "Ntext" });
|
||||
//Dropdown list multiple
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 29, DataTypeId = -134, ControlId = new Guid("928639ed-9c73-4028-920c-1e55dbb68783"), DbType = "Nvarchar" });
|
||||
//Not found - maybe a legacy thing?
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 30, DataTypeId = -50, ControlId = new Guid("aaf99bb2-dbbe-444d-a296-185076bf0484"), DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 16, DataTypeId = 1034, ControlId = new Guid(Constants.PropertyEditors.ContentPicker), DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 17, DataTypeId = 1035, ControlId = new Guid(Constants.PropertyEditors.MediaPicker), DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 18, DataTypeId = 1036, ControlId = new Guid(Constants.PropertyEditors.MemberPicker), DbType = "Integer" });
|
||||
|
||||
@@ -332,7 +332,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
//If Published state has changed then previous versions should have their publish state reset.
|
||||
//If state has been changed to unpublished the previous versions publish state should also be reset.
|
||||
if (((ICanBeDirty)entity).IsPropertyDirty("Published") && (entity.Published || publishedState == PublishedState.Unpublished))
|
||||
//if (((ICanBeDirty)entity).IsPropertyDirty("Published") && (entity.Published || publishedState == PublishedState.Unpublished))
|
||||
if (entity.ShouldClearPublishedFlagForPreviousVersions(publishedState, shouldCreateNewVersion))
|
||||
{
|
||||
var publishedDocs = Database.Fetch<DocumentDto>("WHERE nodeId = @Id AND published = @IsPublished", new { Id = entity.Id, IsPublished = true });
|
||||
foreach (var doc in publishedDocs)
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sql = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId).Append(GetGroupBy(isContent, isMedia));
|
||||
var sql = GetBaseWhere(GetBase, isContent, isMedia, string.Empty, objectTypeId).Append(GetGroupBy(isContent, isMedia));
|
||||
var dtos = isMedia
|
||||
? _work.Database.Fetch<UmbracoEntityDto, UmbracoPropertyDto, UmbracoEntityDto>(
|
||||
new UmbracoEntityRelator().Map, sql)
|
||||
@@ -101,7 +101,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public virtual IEnumerable<IUmbracoEntity> GetByQuery(IQuery<IUmbracoEntity> query)
|
||||
{
|
||||
var sqlClause = GetBase(false, false);
|
||||
var wheres = string.Concat(" AND ", string.Join(" AND ", ((Query<IUmbracoEntity>) query).WhereClauses()));
|
||||
var sqlClause = GetBase(false, false, wheres);
|
||||
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
|
||||
var sql = translator.Translate().Append(GetGroupBy(false, false));
|
||||
|
||||
@@ -117,7 +118,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document);
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, objectTypeId);
|
||||
|
||||
var wheres = string.Concat(" AND ", string.Join(" AND ", ((Query<IUmbracoEntity>)query).WhereClauses()));
|
||||
var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, wheres, objectTypeId);
|
||||
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
|
||||
var sql = translator.Translate().Append(GetGroupBy(isContent, isMedia));
|
||||
|
||||
@@ -136,7 +139,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
#region Sql Statements
|
||||
|
||||
protected virtual Sql GetBase(bool isContent, bool isMedia)
|
||||
protected virtual Sql GetBase(bool isContent, bool isMedia, string additionWhereStatement = "")
|
||||
{
|
||||
var columns = new List<object>
|
||||
{
|
||||
@@ -187,42 +190,38 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
.On("umbracoNode.id = latest.nodeId");
|
||||
}
|
||||
|
||||
/*if (isContent)
|
||||
{
|
||||
sql.LeftJoin(
|
||||
"(SELECT contentNodeId, versionId, dataNvarchar, controlId FROM cmsPropertyData INNER JOIN cmsPropertyType ON cmsPropertyType.id = cmsPropertyData.propertytypeid" +
|
||||
" INNER JOIN cmsDataType ON cmsPropertyType.dataTypeId = cmsDataType.nodeId) as property")
|
||||
.On("umbracoNode.id = property.contentNodeId AND latest.versionId = property.versionId");
|
||||
}*/
|
||||
if (isMedia)
|
||||
{
|
||||
sql.LeftJoin(
|
||||
"(SELECT contentNodeId, versionId, dataNvarchar, controlId FROM cmsPropertyData INNER JOIN cmsPropertyType ON cmsPropertyType.id = cmsPropertyData.propertytypeid" +
|
||||
" INNER JOIN cmsDataType ON cmsPropertyType.dataTypeId = cmsDataType.nodeId) as property")
|
||||
"(SELECT contentNodeId, versionId, dataNvarchar, controlId FROM cmsPropertyData " +
|
||||
"INNER JOIN umbracoNode ON cmsPropertyData.contentNodeId = umbracoNode.id " +
|
||||
"INNER JOIN cmsPropertyType ON cmsPropertyType.id = cmsPropertyData.propertytypeid " +
|
||||
"INNER JOIN cmsDataType ON cmsPropertyType.dataTypeId = cmsDataType.nodeId "+
|
||||
"WHERE umbracoNode.nodeObjectType = '" + Constants.ObjectTypes.Media + "'" + additionWhereStatement + ") as property")
|
||||
.On("umbracoNode.id = property.contentNodeId");
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Sql> baseQuery, bool isContent, bool isMedia, Guid id)
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, string additionWhereStatement, Guid id)
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia)
|
||||
var sql = baseQuery(isContent, isMedia, additionWhereStatement)
|
||||
.Where("umbracoNode.nodeObjectType = @NodeObjectType", new { NodeObjectType = id });
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Sql> baseQuery, bool isContent, bool isMedia, int id)
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, int id)
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia)
|
||||
var sql = baseQuery(isContent, isMedia, " AND umbracoNode.id = '"+ id +"'")
|
||||
.Where("umbracoNode.id = @Id", new { Id = id })
|
||||
.Append(GetGroupBy(isContent, isMedia));
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Sql> baseQuery, bool isContent, bool isMedia, Guid objectId, int id)
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, string, Sql> baseQuery, bool isContent, bool isMedia, Guid objectId, int id)
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia)
|
||||
var sql = baseQuery(isContent, isMedia, " AND umbracoNode.id = '"+ id +"'")
|
||||
.Where("umbracoNode.id = @Id AND umbracoNode.nodeObjectType = @NodeObjectType",
|
||||
new {Id = id, NodeObjectType = objectId});
|
||||
return sql;
|
||||
|
||||
@@ -430,7 +430,9 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
internal IEnumerable<Type> ResolvePropertyEditors()
|
||||
{
|
||||
return ResolveTypes<PropertyEditor>();
|
||||
//return all proeprty editor types found except for the base property editor type
|
||||
return ResolveTypes<PropertyEditor>()
|
||||
.Except(new[] {typeof (PropertyEditor)});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -466,7 +468,9 @@ namespace Umbraco.Core
|
||||
/// <returns></returns>
|
||||
internal IEnumerable<Type> ResolveDataTypes()
|
||||
{
|
||||
return ResolveTypes<IDataType>();
|
||||
//ensure we ignore types that should not be loaded
|
||||
return ResolveTypes<IDataType>()
|
||||
.Except(new[] {Type.GetType("umbraco.presentation.LiveEditing.Modules.ItemEditing.PageElementEditor,umbraco")});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -3,6 +3,12 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a pre-value editor
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Json serialization attributes are required for manifest property editors to work
|
||||
/// </remarks>
|
||||
public class PreValueEditor
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic definition of a property editor
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Json serialization attributes are required for manifest property editors to work
|
||||
/// </remarks>
|
||||
public class PropertyEditor
|
||||
{
|
||||
/// <summary>
|
||||
@@ -20,14 +29,23 @@ namespace Umbraco.Core.PropertyEditors
|
||||
{
|
||||
Id = Guid.Parse(att.Id);
|
||||
Name = att.Name;
|
||||
|
||||
|
||||
StaticallyDefinedValueEditor.ValueType = att.ValueType;
|
||||
StaticallyDefinedValueEditor.View = att.EditorView;
|
||||
StaticallyDefinedPreValueEditor.View = att.PreValueEditorView;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// These are assigned by default normally based on property editor attributes or manifest definitions,
|
||||
/// developers have the chance to override CreateValueEditor if they don't want to use the pre-defined instance
|
||||
/// </summary>
|
||||
internal ValueEditor StaticallyDefinedValueEditor = null;
|
||||
|
||||
/// <summary>
|
||||
/// These are assigned by default normally based on property editor attributes or manifest definitions,
|
||||
/// developers have the chance to override CreatePreValueEditor if they don't want to use the pre-defined instance
|
||||
/// </summary>
|
||||
internal PreValueEditor StaticallyDefinedPreValueEditor = null;
|
||||
|
||||
/// <summary>
|
||||
@@ -54,6 +72,9 @@ namespace Umbraco.Core.PropertyEditors
|
||||
get { return CreatePreValueEditor(); }
|
||||
}
|
||||
|
||||
[JsonProperty("defaultConfig")]
|
||||
public virtual IDictionary<string, object> DefaultPreValues { get; set; }
|
||||
|
||||
//TODO: Now we need to implement a couple of methods for saving the data for editors and pre-value editors
|
||||
// generally we can handle that automatically in this base class but people should be allowed to override
|
||||
// it so they can perform custom operations on saving the data.
|
||||
@@ -88,6 +109,48 @@ namespace Umbraco.Core.PropertyEditors
|
||||
return StaticallyDefinedPreValueEditor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This can be used to re-format the currently saved pre-values that will be passed to the editor,
|
||||
/// by default this returns the merged default and persisted pre-values.
|
||||
/// </summary>
|
||||
/// <param name="defaultPreVals">
|
||||
/// The default/static pre-vals for the property editor
|
||||
/// </param>
|
||||
/// <param name="persistedPreVals">
|
||||
/// The persisted pre-vals for the property editor
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is generally not going to be used by anything unless a property editor wants to change the merging
|
||||
/// functionality or needs to convert some legacy persisted data, or convert the string values to strongly typed values in json (i.e. booleans)
|
||||
/// </remarks>
|
||||
public virtual IDictionary<string, object> FormatPreValues(IDictionary<string, object> defaultPreVals, PreValueCollection persistedPreVals)
|
||||
{
|
||||
if (defaultPreVals == null)
|
||||
{
|
||||
defaultPreVals = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
if (persistedPreVals.IsDictionaryBased)
|
||||
{
|
||||
//we just need to merge the dictionaries now, the persisted will replace default.
|
||||
foreach (var item in persistedPreVals.PreValuesAsDictionary)
|
||||
{
|
||||
defaultPreVals[item.Key] = item.Value;
|
||||
}
|
||||
return defaultPreVals;
|
||||
}
|
||||
|
||||
//it's an array so need to format it
|
||||
var result = new Dictionary<string, object>();
|
||||
var asArray = persistedPreVals.PreValuesAsArray.ToArray();
|
||||
for (var i = 0; i < asArray.Length; i++)
|
||||
{
|
||||
result.Add(i.ToInvariantString(), asArray[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected bool Equals(PropertyEditor other)
|
||||
{
|
||||
return Id.Equals(other.Id);
|
||||
|
||||
@@ -10,6 +10,9 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// <summary>
|
||||
/// Represents the value editor for the property editor during content editing
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Json serialization attributes are required for manifest property editors to work
|
||||
/// </remarks>
|
||||
public class ValueEditor
|
||||
{
|
||||
/// <summary>
|
||||
@@ -126,10 +129,12 @@ namespace Umbraco.Core.PropertyEditors
|
||||
valueType = typeof(string);
|
||||
break;
|
||||
case DataTypeDatabaseType.Integer:
|
||||
valueType = typeof(int);
|
||||
//ensure these are nullable so we can return a null if required
|
||||
valueType = typeof(int?);
|
||||
break;
|
||||
case DataTypeDatabaseType.Date:
|
||||
valueType = typeof(DateTime);
|
||||
//ensure these are nullable so we can return a null if required
|
||||
valueType = typeof(DateTime?);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
@@ -180,9 +185,14 @@ namespace Umbraco.Core.PropertyEditors
|
||||
case DataTypeDatabaseType.Integer:
|
||||
//we can just ToString() any of these types
|
||||
return dbValue.ToString();
|
||||
case DataTypeDatabaseType.Date:
|
||||
//Dates will be formatted in 'o' format (otherwise known as xml format)
|
||||
return dbValue.ToXmlString<DateTime>();
|
||||
case DataTypeDatabaseType.Date:
|
||||
var date = dbValue.TryConvertTo<DateTime?>();
|
||||
if (date.Success == false || date.Result == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
//Dates will be formatted as yyyy-MM-dd HH:mm:ss
|
||||
return date.Result.Value.ToIsoString();
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
@@ -133,6 +133,22 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the PreValueCollection for the specified data type
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
internal PreValueCollection GetPreValuesCollectionByDataTypeId(int id)
|
||||
{
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
{
|
||||
var dtos = uow.Database.Fetch<DataTypePreValueDto>("WHERE datatypeNodeId = @Id", new { Id = id });
|
||||
var list = dtos.Select(x => new Tuple<int, string, int, string>(x.Id, x.Alias, x.SortOrder, x.Value)).ToList();
|
||||
|
||||
return PreValueConverter.ConvertToPreValuesCollection(list);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific PreValue by its Id
|
||||
/// </summary>
|
||||
@@ -327,5 +343,41 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IDataTypeService, SaveEventArgs<IDataTypeDefinition>> Saved;
|
||||
#endregion
|
||||
|
||||
internal static class PreValueConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts the tuple to a pre-value collection
|
||||
/// </summary>
|
||||
/// <param name="list"></param>
|
||||
/// <returns></returns>
|
||||
internal static PreValueCollection ConvertToPreValuesCollection(IEnumerable<Tuple<int, string, int, string>> list)
|
||||
{
|
||||
//now we need to determine if they are dictionary based, otherwise they have to be array based
|
||||
var dictionary = new Dictionary<string, object>();
|
||||
|
||||
//need to check all of the keys, if there's only one and it is empty then it's an array
|
||||
var keys = list.Select(x => x.Item2).Distinct().ToArray();
|
||||
if (keys.Length == 1 && keys[0].IsNullOrWhiteSpace())
|
||||
{
|
||||
return new PreValueCollection(list.OrderBy(x => x.Item3).Select(x => x.Item4));
|
||||
}
|
||||
|
||||
foreach (var item in list
|
||||
.OrderBy(x => x.Item3) //we'll order them first so we maintain the order index in the dictionary
|
||||
.GroupBy(x => x.Item2))
|
||||
{
|
||||
if (item.Count() > 1)
|
||||
{
|
||||
//if there's more than 1 item per key, then it cannot be a dictionary, just return the array
|
||||
return new PreValueCollection(list.OrderBy(x => x.Item3).Select(x => x.Item4));
|
||||
}
|
||||
|
||||
dictionary.Add(item.Key, item.First().Item4);
|
||||
}
|
||||
|
||||
return new PreValueCollection(dictionary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,16 @@ namespace Umbraco.Core
|
||||
[UmbracoWillObsolete("Do not use this constants. See IShortStringHelper.CleanStringForSafeAliasJavaScriptCode.")]
|
||||
public const string UmbracoInvalidFirstCharacters = "01234567890";
|
||||
|
||||
public static string ExceptChars(this string str, HashSet<char> toExclude)
|
||||
{
|
||||
var sb = new StringBuilder(str.Length);
|
||||
foreach (var c in str.Where(c => toExclude.Contains(c) == false))
|
||||
{
|
||||
sb.Append(c);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a stream from a string
|
||||
/// </summary>
|
||||
|
||||
@@ -225,6 +225,7 @@
|
||||
<Compile Include="Models\Mapping\MapperConfiguration.cs" />
|
||||
<Compile Include="Models\Membership\EntityPermission.cs" />
|
||||
<Compile Include="Models\Membership\UmbracoMembershipUser.cs" />
|
||||
<Compile Include="Models\PreValueCollection.cs" />
|
||||
<Compile Include="Models\ServerRegistration.cs" />
|
||||
<Compile Include="Models\ITemplate.cs" />
|
||||
<Compile Include="Models\Language.cs" />
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Tests.AngularIntegration
|
||||
@@ -29,7 +30,7 @@ namespace Umbraco.Tests.AngularIntegration
|
||||
Label = "Property " + propertyIndex,
|
||||
Id = propertyIndex,
|
||||
Value = "value" + propertyIndex,
|
||||
Config = new[] {"config" + propertyIndex},
|
||||
Config = new Dictionary<string, string> {{ propertyIndex.ToInvariantString(), "value" }},
|
||||
Description = "Description " + propertyIndex,
|
||||
View = "~/Views/View" + propertyIndex,
|
||||
HideLabel = false
|
||||
@@ -68,7 +69,7 @@ namespace Umbraco.Tests.AngularIntegration
|
||||
Assert.AreEqual("Property " + prop, jObject["tabs"][tab]["properties"][prop]["label"].ToString());
|
||||
Assert.AreEqual(prop, jObject["tabs"][tab]["properties"][prop]["id"].Value<int>());
|
||||
Assert.AreEqual("value" + prop, jObject["tabs"][tab]["properties"][prop]["value"].ToString());
|
||||
Assert.AreEqual("[\"config" + prop + "\"]", jObject["tabs"][tab]["properties"][prop]["config"].ToString(Formatting.None));
|
||||
Assert.AreEqual("{\"" + prop + "\":\"value\"}", jObject["tabs"][tab]["properties"][prop]["config"].ToString(Formatting.None));
|
||||
Assert.AreEqual("Description " + prop, jObject["tabs"][tab]["properties"][prop]["description"].ToString());
|
||||
Assert.AreEqual(false, jObject["tabs"][tab]["properties"][prop]["hideLabel"].Value<bool>());
|
||||
}
|
||||
|
||||
@@ -82,6 +82,61 @@ namespace Umbraco.Tests.Models
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Should_Clear_Published_Flag_When_Newly_Published_Version()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
content.ChangePublishedState(PublishedState.Published);
|
||||
Assert.IsTrue(content.ShouldClearPublishedFlagForPreviousVersions());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Should_Not_Clear_Published_Flag_When_Saving_Version()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
content.ChangePublishedState(PublishedState.Published);
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
content.ChangePublishedState(PublishedState.Saved);
|
||||
Assert.IsFalse(content.ShouldClearPublishedFlagForPreviousVersions());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Should_Clear_Published_Flag_When_Unpublishing_From_Published()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
content.ChangePublishedState(PublishedState.Published);
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
content.ChangePublishedState(PublishedState.Unpublished);
|
||||
Assert.IsTrue(content.ShouldClearPublishedFlagForPreviousVersions());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Should_Not_Clear_Published_Flag_When_Unpublishing_From_Saved()
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateTextpageContentType();
|
||||
var content = MockedContent.CreateTextpageContent(contentType, "Textpage", -1);
|
||||
|
||||
content.ResetDirtyProperties(false);
|
||||
content.ChangePublishedState(PublishedState.Saved);
|
||||
content.ResetDirtyProperties(false);
|
||||
|
||||
content.ChangePublishedState(PublishedState.Unpublished);
|
||||
Assert.IsFalse(content.ShouldClearPublishedFlagForPreviousVersions());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -31,8 +31,8 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
|
||||
protected override void FreezeResolution()
|
||||
{
|
||||
PropertyEditorResolver.Current = new PropertyEditorResolver(
|
||||
() => new List<Type> {typeof (TestPropertyEditor)});
|
||||
//PropertyEditorResolver.Current = new PropertyEditorResolver(
|
||||
// () => new List<Type> {typeof (TestPropertyEditor)});
|
||||
|
||||
base.FreezeResolution();
|
||||
}
|
||||
@@ -96,6 +96,13 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
{
|
||||
var contentType = MockedContentTypes.CreateSimpleContentType();
|
||||
var content = MockedContent.CreateSimpleContent(contentType);
|
||||
//need ids for tabs
|
||||
var id = 1;
|
||||
foreach (var g in content.PropertyGroups)
|
||||
{
|
||||
g.Id = id;
|
||||
id++;
|
||||
}
|
||||
|
||||
var result = Mapper.Map<IContent, ContentItemDisplay>(content);
|
||||
|
||||
@@ -131,6 +138,13 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
p.Id = idSeed;
|
||||
idSeed++;
|
||||
}
|
||||
//need ids for tabs
|
||||
var id = 1;
|
||||
foreach (var g in content.PropertyGroups)
|
||||
{
|
||||
g.Id = id;
|
||||
id++;
|
||||
}
|
||||
//ensure that nothing is marked as dirty
|
||||
contentType.ResetDirtyProperties(false);
|
||||
//ensure that nothing is marked as dirty
|
||||
@@ -145,7 +159,7 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
}
|
||||
Assert.AreEqual(content.PropertyGroups.Count(), result.Tabs.Count() - 1);
|
||||
Assert.IsTrue(result.Tabs.Any(x => x.Label == "Generic properties"));
|
||||
Assert.AreEqual(2, result.Tabs.Where(x => x.Label == "Generic properties").SelectMany(x => x.Properties).Count());
|
||||
Assert.AreEqual(2, result.Tabs.Where(x => x.Label == "Generic properties").SelectMany(x => x.Properties.Where(p => p.Alias.StartsWith("_umb_") == false)).Count());
|
||||
}
|
||||
|
||||
#region Assertions
|
||||
@@ -158,10 +172,11 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
|
||||
var pDto = result.Properties.SingleOrDefault(x => x.Alias == p.Alias);
|
||||
Assert.IsNotNull(pDto);
|
||||
pDto.Alias = p.Alias;
|
||||
pDto.Description = p.PropertyType.Description;
|
||||
pDto.Label = p.PropertyType.Name;
|
||||
pDto.Config = applicationContext.Services.DataTypeService.GetPreValuesByDataTypeId(p.PropertyType.DataTypeDefinitionId);
|
||||
|
||||
//pDto.Alias = p.Alias;
|
||||
//pDto.Description = p.PropertyType.Description;
|
||||
//pDto.Label = p.PropertyType.Name;
|
||||
//pDto.Config = applicationContext.Services.DataTypeService.GetPreValuesByDataTypeId(p.PropertyType.DataTypeDefinitionId);
|
||||
|
||||
}
|
||||
|
||||
@@ -176,7 +191,7 @@ namespace Umbraco.Tests.Models.Mapping
|
||||
Assert.AreEqual(content.UpdateDate, result.UpdateDate);
|
||||
Assert.AreEqual(content.CreateDate, result.CreateDate);
|
||||
Assert.AreEqual(content.Name, result.Name);
|
||||
Assert.AreEqual(content.Properties.Count(), result.Properties.Count());
|
||||
Assert.AreEqual(content.Properties.Count(), result.Properties.Count(x => x.Alias.StartsWith("_umb_") == false));
|
||||
}
|
||||
|
||||
private void AssertBasicProperty<T, TPersisted>(ContentItemBasic<T, TPersisted> result, Property p)
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.PropertyEditors
|
||||
{
|
||||
[TestFixture]
|
||||
[TestFixture]
|
||||
public class PropertyEditorValueConverterTests
|
||||
{
|
||||
[TestCase("2012-11-10", true)]
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Tests.PropertyEditors
|
||||
{
|
||||
[TestFixture]
|
||||
public class PropertyEditorValueEditorTests
|
||||
{
|
||||
[TestCase("STRING", "hello", "hello")]
|
||||
[TestCase("TEXT", "hello", "hello")]
|
||||
[TestCase("INT", "123", 123)]
|
||||
[TestCase("INTEGER", "123", 123)]
|
||||
[TestCase("INTEGER", "", null)] //test empty string for int
|
||||
[TestCase("DATETIME", "", null)] //test empty string for date
|
||||
public void Value_Editor_Can_Convert_To_Clr_Type(string valueType, string val, object expected)
|
||||
{
|
||||
var valueEditor = new ValueEditor
|
||||
{
|
||||
ValueType = valueType
|
||||
};
|
||||
|
||||
var result = valueEditor.TryConvertValueToCrlType(val);
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(expected, result.Result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Value_Editor_Can_Convert_To_Date_Clr_Type()
|
||||
{
|
||||
var valueEditor = new ValueEditor
|
||||
{
|
||||
ValueType = "DATE"
|
||||
};
|
||||
|
||||
var result = valueEditor.TryConvertValueToCrlType("2010-02-05");
|
||||
Assert.IsTrue(result.Success);
|
||||
Assert.AreEqual(new DateTime(2010, 2, 5), result.Result);
|
||||
}
|
||||
|
||||
[TestCase("STRING", "hello", "hello")]
|
||||
[TestCase("TEXT", "hello", "hello")]
|
||||
[TestCase("INT", 123, "123")]
|
||||
[TestCase("INTEGER", 123, "123")]
|
||||
[TestCase("INTEGER", "", "")] //test empty string for int
|
||||
[TestCase("DATETIME", "", "")] //test empty string for date
|
||||
public void Value_Editor_Can_Serialize_Value(string valueType, object val, string expected)
|
||||
{
|
||||
var valueEditor = new ValueEditor
|
||||
{
|
||||
ValueType = valueType
|
||||
};
|
||||
|
||||
var result = valueEditor.SerializeValue(val);
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Value_Editor_Can_Serialize_Date_Value()
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
var valueEditor = new ValueEditor
|
||||
{
|
||||
ValueType = "DATE"
|
||||
};
|
||||
|
||||
var result = valueEditor.SerializeValue(now);
|
||||
Assert.AreEqual(now.ToXmlString<DateTime>(), result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -813,6 +813,48 @@ namespace Umbraco.Tests.Services
|
||||
Assert.That(hasPublishedVersion, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Verify_Property_Types_On_Content()
|
||||
{
|
||||
// Arrange
|
||||
var contentTypeService = ServiceContext.ContentTypeService;
|
||||
var contentType = MockedContentTypes.CreateAllTypesContentType("allDataTypes", "All DataTypes");
|
||||
contentTypeService.Save(contentType);
|
||||
var contentService = ServiceContext.ContentService;
|
||||
var content = MockedContent.CreateAllTypesContent(contentType, "Random Content", -1);
|
||||
contentService.Save(content);
|
||||
var id = content.Id;
|
||||
|
||||
// Act
|
||||
var sut = contentService.GetById(id);
|
||||
|
||||
// Arrange
|
||||
Assert.That(sut.GetValue<bool>("isTrue"), Is.True);
|
||||
Assert.That(sut.GetValue<int>("number"), Is.EqualTo(42));
|
||||
Assert.That(sut.GetValue<string>("bodyText"), Is.EqualTo("Lorem Ipsum Body Text Test"));
|
||||
Assert.That(sut.GetValue<string>("singleLineText"), Is.EqualTo("Single Line Text Test"));
|
||||
Assert.That(sut.GetValue<string>("multilineText"), Is.EqualTo("Multiple lines \n in one box"));
|
||||
Assert.That(sut.GetValue<string>("upload"), Is.EqualTo("/media/1234/koala.jpg"));
|
||||
Assert.That(sut.GetValue<string>("label"), Is.EqualTo("Non-editable label"));
|
||||
Assert.That(sut.GetValue<DateTime>("dateTime"), Is.EqualTo(content.GetValue<DateTime>("dateTime")));
|
||||
Assert.That(sut.GetValue<string>("colorPicker"), Is.EqualTo("black"));
|
||||
Assert.That(sut.GetValue<string>("folderBrowser"), Is.Empty);
|
||||
Assert.That(sut.GetValue<string>("ddlMultiple"), Is.EqualTo("1234,1235"));
|
||||
Assert.That(sut.GetValue<string>("rbList"), Is.EqualTo("random"));
|
||||
Assert.That(sut.GetValue<DateTime>("date"), Is.EqualTo(content.GetValue<DateTime>("date")));
|
||||
Assert.That(sut.GetValue<string>("ddl"), Is.EqualTo("1234"));
|
||||
Assert.That(sut.GetValue<string>("chklist"), Is.EqualTo("randomc"));
|
||||
Assert.That(sut.GetValue<int>("contentPicker"), Is.EqualTo(1090));
|
||||
Assert.That(sut.GetValue<int>("mediaPicker"), Is.EqualTo(1091));
|
||||
Assert.That(sut.GetValue<int>("memberPicker"), Is.EqualTo(1092));
|
||||
Assert.That(sut.GetValue<string>("simpleEditor"), Is.EqualTo("This is simply edited"));
|
||||
Assert.That(sut.GetValue<string>("ultimatePicker"), Is.EqualTo("1234,1235"));
|
||||
Assert.That(sut.GetValue<string>("relatedLinks"), Is.EqualTo("<links><link title=\"google\" link=\"http://google.com\" type=\"external\" newwindow=\"0\" /></links>"));
|
||||
Assert.That(sut.GetValue<string>("tags"), Is.EqualTo("this,is,tags"));
|
||||
Assert.That(sut.GetValue<string>("macroContainer"), Is.Empty);
|
||||
Assert.That(sut.GetValue<string>("imgCropper"), Is.Empty);
|
||||
}
|
||||
|
||||
private IEnumerable<IContent> CreateContentHierarchy()
|
||||
{
|
||||
var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage");
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace Umbraco.Tests.Services
|
||||
base.TearDown();
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Test]
|
||||
public void DataTypeService_Can_Persist_New_DataTypeDefinition()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Tests.Services
|
||||
{
|
||||
[TestFixture]
|
||||
public class PreValueConverterTests
|
||||
{
|
||||
[Test]
|
||||
public void Can_Convert_To_Dictionary_Pre_Value_Collection()
|
||||
{
|
||||
var list = new List<Tuple<int, string, int, string>>
|
||||
{
|
||||
new Tuple<int, string, int, string>(10, "key1", 0, "value1"),
|
||||
new Tuple<int, string, int, string>(11, "key2", 3, "value2"),
|
||||
new Tuple<int, string, int, string>(12, "key3", 2, "value3"),
|
||||
new Tuple<int, string, int, string>(13, "key4", 1, "value4")
|
||||
};
|
||||
|
||||
var result = DataTypeService.PreValueConverter.ConvertToPreValuesCollection(list);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
var blah = result.PreValuesAsArray;
|
||||
});
|
||||
|
||||
Assert.AreEqual(4, result.PreValuesAsDictionary.Count);
|
||||
Assert.AreEqual("key1", result.PreValuesAsDictionary.ElementAt(0).Key);
|
||||
Assert.AreEqual("key4", result.PreValuesAsDictionary.ElementAt(1).Key);
|
||||
Assert.AreEqual("key3", result.PreValuesAsDictionary.ElementAt(2).Key);
|
||||
Assert.AreEqual("key2", result.PreValuesAsDictionary.ElementAt(3).Key);
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Convert_To_Array_Pre_Value_Collection_When_Empty_Key()
|
||||
{
|
||||
var list = new List<Tuple<int, string, int, string>>
|
||||
{
|
||||
new Tuple<int, string, int, string>(10, "", 0, "value1"),
|
||||
new Tuple<int, string, int, string>(11, "", 3, "value2"),
|
||||
new Tuple<int, string, int, string>(12, "", 2, "value3"),
|
||||
new Tuple<int, string, int, string>(13, "", 1, "value4")
|
||||
};
|
||||
|
||||
var result = DataTypeService.PreValueConverter.ConvertToPreValuesCollection(list);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
var blah = result.PreValuesAsDictionary;
|
||||
});
|
||||
|
||||
Assert.AreEqual(4, result.PreValuesAsArray.Count());
|
||||
Assert.AreEqual("value1", result.PreValuesAsArray.ElementAt(0));
|
||||
Assert.AreEqual("value4", result.PreValuesAsArray.ElementAt(1));
|
||||
Assert.AreEqual("value3", result.PreValuesAsArray.ElementAt(2));
|
||||
Assert.AreEqual("value2", result.PreValuesAsArray.ElementAt(3));
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Convert_To_Array_Pre_Value_Collection()
|
||||
{
|
||||
var list = new List<Tuple<int, string, int, string>>
|
||||
{
|
||||
new Tuple<int, string, int, string>(10, "key1", 0, "value1"),
|
||||
new Tuple<int, string, int, string>(11, "key1", 3, "value2"),
|
||||
new Tuple<int, string, int, string>(12, "key3", 2, "value3"),
|
||||
new Tuple<int, string, int, string>(13, "key4", 1, "value4")
|
||||
};
|
||||
|
||||
var result = DataTypeService.PreValueConverter.ConvertToPreValuesCollection(list);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
var blah = result.PreValuesAsDictionary;
|
||||
});
|
||||
|
||||
Assert.AreEqual(4, result.PreValuesAsArray.Count());
|
||||
Assert.AreEqual("value1", result.PreValuesAsArray.ElementAt(0));
|
||||
Assert.AreEqual("value4", result.PreValuesAsArray.ElementAt(1));
|
||||
Assert.AreEqual("value3", result.PreValuesAsArray.ElementAt(2));
|
||||
Assert.AreEqual("value2", result.PreValuesAsArray.ElementAt(3));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,6 +79,38 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
return content;
|
||||
}
|
||||
|
||||
public static Content CreateAllTypesContent(IContentType contentType, string name, int parentId)
|
||||
{
|
||||
var content = new Content("Random Content Name", parentId, contentType) { Language = "en-US", Level = 1, SortOrder = 1, CreatorId = 0, WriterId = 0 };
|
||||
|
||||
content.SetValue("isTrue", true);
|
||||
content.SetValue("number", 42);
|
||||
content.SetValue("bodyText", "Lorem Ipsum Body Text Test");
|
||||
content.SetValue("singleLineText", "Single Line Text Test");
|
||||
content.SetValue("multilineText", "Multiple lines \n in one box");
|
||||
content.SetValue("upload", "/media/1234/koala.jpg");
|
||||
content.SetValue("label", "Non-editable label");
|
||||
content.SetValue("dateTime", DateTime.Now.AddDays(-20));
|
||||
content.SetValue("colorPicker", "black");
|
||||
content.SetValue("folderBrowser", "");
|
||||
content.SetValue("ddlMultiple", "1234,1235");
|
||||
content.SetValue("rbList", "random");
|
||||
content.SetValue("date", DateTime.Now.AddDays(-10));
|
||||
content.SetValue("ddl", "1234");
|
||||
content.SetValue("chklist", "randomc");
|
||||
content.SetValue("contentPicker", 1090);
|
||||
content.SetValue("mediaPicker", 1091);
|
||||
content.SetValue("memberPicker", 1092);
|
||||
content.SetValue("simpleEditor", "This is simply edited");
|
||||
content.SetValue("ultimatePicker", "1234,1235");
|
||||
content.SetValue("relatedLinks", "<links><link title=\"google\" link=\"http://google.com\" type=\"external\" newwindow=\"0\" /></links>");
|
||||
content.SetValue("tags", "this,is,tags");
|
||||
content.SetValue("macroContainer", "");
|
||||
content.SetValue("imgCropper", "");
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
public static IEnumerable<Content> CreateTextpageContent(IContentType contentType, int parentId, int amount)
|
||||
{
|
||||
var list = new List<Content>();
|
||||
|
||||
@@ -180,6 +180,51 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static ContentType CreateAllTypesContentType(string alias, string name)
|
||||
{
|
||||
var contentType = new ContentType(-1)
|
||||
{
|
||||
Alias = alias,
|
||||
Name = name,
|
||||
Description = "ContentType containing all standard DataTypes",
|
||||
Icon = ".sprTreeDoc3",
|
||||
Thumbnail = "doc.png",
|
||||
SortOrder = 1,
|
||||
CreatorId = 0,
|
||||
Trashed = false
|
||||
};
|
||||
|
||||
var contentCollection = new PropertyTypeCollection();
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.TrueFalse), DataTypeDatabaseType.Integer) { Alias = "isTrue", Name = "Is True or False", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -49 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.Integer), DataTypeDatabaseType.Integer) { Alias = "number", Name = "Number", Mandatory = false, SortOrder = 2, DataTypeDefinitionId = -51 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.TinyMCEv3), DataTypeDatabaseType.Ntext) { Alias = "bodyText", Name = "Body Text", Mandatory = false, SortOrder = 3, DataTypeDefinitionId = -87 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.Textbox), DataTypeDatabaseType.Nvarchar) { Alias = "singleLineText", Name = "Text String", Mandatory = false, SortOrder = 4, DataTypeDefinitionId = -88 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.TextboxMultiple), DataTypeDatabaseType.Ntext) { Alias = "multilineText", Name = "Multiple Text Strings", Mandatory = false, SortOrder = 5, DataTypeDefinitionId = -89 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.UploadField), DataTypeDatabaseType.Nvarchar) { Alias = "upload", Name = "Upload Field", Mandatory = false, SortOrder = 6, DataTypeDefinitionId = -90 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.NoEdit), DataTypeDatabaseType.Nvarchar) { Alias = "label", Name = "Label", Mandatory = false, SortOrder = 7, DataTypeDefinitionId = -92 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.DateTime), DataTypeDatabaseType.Date) { Alias = "dateTime", Name = "Date Time", Mandatory = false, SortOrder = 8, DataTypeDefinitionId = -36 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.ColorPicker), DataTypeDatabaseType.Nvarchar) { Alias = "colorPicker", Name = "Color Picker", Mandatory = false, SortOrder = 9, DataTypeDefinitionId = -37 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.FolderBrowser), DataTypeDatabaseType.Nvarchar) { Alias = "folderBrowser", Name = "Folder Browser", Mandatory = false, SortOrder = 10, DataTypeDefinitionId = -38 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.DropDownListMultiple), DataTypeDatabaseType.Nvarchar) { Alias = "ddlMultiple", Name = "Dropdown List Multiple", Mandatory = false, SortOrder = 11, DataTypeDefinitionId = -39 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.RadioButtonList), DataTypeDatabaseType.Nvarchar) { Alias = "rbList", Name = "Radio Button List", Mandatory = false, SortOrder = 12, DataTypeDefinitionId = -40 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.Date), DataTypeDatabaseType.Date) { Alias = "date", Name = "Date", Mandatory = false, SortOrder = 13, DataTypeDefinitionId = -41 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.DropDownList), DataTypeDatabaseType.Integer) { Alias = "ddl", Name = "Dropdown List", Mandatory = false, SortOrder = 14, DataTypeDefinitionId = -42 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.CheckBoxList), DataTypeDatabaseType.Nvarchar) { Alias = "chklist", Name = "Checkbox List", Mandatory = false, SortOrder = 15, DataTypeDefinitionId = -43 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.ContentPicker), DataTypeDatabaseType.Integer) { Alias = "contentPicker", Name = "Content Picker", Mandatory = false, SortOrder = 16, DataTypeDefinitionId = 1034 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.MediaPicker), DataTypeDatabaseType.Integer) { Alias = "mediaPicker", Name = "Media Picker", Mandatory = false, SortOrder = 17, DataTypeDefinitionId = 1035 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.MemberPicker), DataTypeDatabaseType.Integer) { Alias = "memberPicker", Name = "Member Picker", Mandatory = false, SortOrder = 18, DataTypeDefinitionId = 1036 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.UltraSimpleEditor), DataTypeDatabaseType.Ntext) { Alias = "simpleEditor", Name = "Ultra Simple Editor", Mandatory = false, SortOrder = 19, DataTypeDefinitionId = 1038 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.UltimatePicker), DataTypeDatabaseType.Ntext) { Alias = "ultimatePicker", Name = "Ultimate Picker", Mandatory = false, SortOrder = 20, DataTypeDefinitionId = 1039 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.RelatedLinks), DataTypeDatabaseType.Ntext) { Alias = "relatedLinks", Name = "Related Links", Mandatory = false, SortOrder = 21, DataTypeDefinitionId = 1040 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.Tags), DataTypeDatabaseType.Ntext) { Alias = "tags", Name = "Tags", Mandatory = false, SortOrder = 22, DataTypeDefinitionId = 1041 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.MacroContainer), DataTypeDatabaseType.Ntext) { Alias = "macroContainer", Name = "Macro Container", Mandatory = false, SortOrder = 23, DataTypeDefinitionId = 1042 });
|
||||
contentCollection.Add(new PropertyType(new Guid(Constants.PropertyEditors.ImageCropper), DataTypeDatabaseType.Ntext) { Alias = "imgCropper", Name = "Image Cropper", Mandatory = false, SortOrder = 24, DataTypeDefinitionId = 1043 });
|
||||
|
||||
contentType.PropertyGroups.Add(new PropertyGroup(contentCollection) { Name = "Content", SortOrder = 1 });
|
||||
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public static MediaType CreateVideoMediaType()
|
||||
{
|
||||
var mediaType = new MediaType(-1)
|
||||
|
||||
@@ -55,9 +55,9 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\AutoMapper.2.2.1\lib\net40\AutoMapper.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Examine, Version=0.1.52.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Examine.0.1.51.2941\lib\Examine.dll</HintPath>
|
||||
<HintPath>..\packages\Examine.0.1.52.2941\lib\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@@ -213,8 +213,10 @@
|
||||
<Compile Include="Persistence\Repositories\UserRepositoryTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\UserTypeRepositoryTest.cs" />
|
||||
<Compile Include="Models\Mapping\ContentWebModelMappingTests.cs" />
|
||||
<Compile Include="PropertyEditors\PropertyEditorValueEditorTests.cs" />
|
||||
<Compile Include="Services\PackagingServiceTests.cs" />
|
||||
<Compile Include="Services\PerformanceTests.cs" />
|
||||
<Compile Include="Services\PreValueConverterTests.cs" />
|
||||
<Compile Include="Services\UserServiceTests.cs" />
|
||||
<Compile Include="Manifest\ManifestParserTests.cs" />
|
||||
<Compile Include="TestHelpers\BaseSeleniumTest.cs" />
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="AspNetWebApi.SelfHost" version="4.0.20710.0" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
|
||||
<package id="AutoMapper" version="2.2.1" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.51.2941" targetFramework="net40" />
|
||||
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/** Converts a Date object to a globally acceptable ISO string, NOTE: This is different from the built in
|
||||
JavaScript toISOString method which returns date/time like "2013-08-07T02:04:11.487Z" but we want "yyyy-MM-dd HH:mm:ss" */
|
||||
Date.prototype.toIsoDateTimeString = function (str) {
|
||||
var month = this.getMonth().toString();
|
||||
var month = (this.getMonth() + 1).toString();
|
||||
if (month.length === 1) {
|
||||
month = "0" + month;
|
||||
}
|
||||
@@ -28,6 +28,23 @@
|
||||
return this.getFullYear() + "-" + month + "-" + day + " " + hour + ":" + mins + ":" + secs;
|
||||
};
|
||||
}
|
||||
|
||||
if (!Date.prototype.toIsoDateString) {
|
||||
/** Converts a Date object to a globally acceptable ISO string, NOTE: This is different from the built in
|
||||
JavaScript toISOString method which returns date/time like "2013-08-07T02:04:11.487Z" but we want "yyyy-MM-dd" */
|
||||
Date.prototype.toIsoDateString = function (str) {
|
||||
var month = (this.getMonth() + 1).toString();
|
||||
if (month.length === 1) {
|
||||
month = "0" + month;
|
||||
}
|
||||
var day = this.getDate().toString();
|
||||
if (day.length === 1) {
|
||||
day = "0" + day;
|
||||
}
|
||||
|
||||
return this.getFullYear() + "-" + month + "-" + day;
|
||||
};
|
||||
}
|
||||
|
||||
//create guid method on the String
|
||||
if (String.CreateGuid == null) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* @ngdoc directive
|
||||
* @function
|
||||
* @name umbraco.directives.directive:umbEditor
|
||||
* @requires formController
|
||||
* @restrict E
|
||||
**/
|
||||
angular.module("umbraco.directives")
|
||||
@@ -10,11 +11,17 @@ angular.module("umbraco.directives")
|
||||
scope: {
|
||||
model: "="
|
||||
},
|
||||
require: "^form",
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/directives/umb-editor.html',
|
||||
link: function (scope, element, attrs, ctrl) {
|
||||
|
||||
|
||||
//we need to copy the form controller val to our isolated scope so that
|
||||
//it get's carried down to the child scopes of this!
|
||||
//we'll also maintain the current form name.
|
||||
scope[ctrl.$name] = ctrl;
|
||||
|
||||
if(!scope.model.alias){
|
||||
scope.model.alias = Math.random().toString(36).slice(2);
|
||||
}
|
||||
|
||||
@@ -33,8 +33,8 @@ angular.module("umbraco.directives")
|
||||
template: '<li><div ng-style="setTreePadding(node)" ng-class="{\'loading\': node.loading}">' +
|
||||
'<ins ng-hide="node.hasChildren" style="background:none;width:18px;"></ins>' +
|
||||
'<ins ng-show="node.hasChildren" ng-class="{\'icon-caret-right\': !node.expanded, \'icon-caret-down\': node.expanded}" ng-click="load(this, node)"></ins>' +
|
||||
'<i class="{{node.cssClass}}" style="{{node.style}}"></i>' +
|
||||
'<a href title="#{{node.routePath}}" ng-click="select(this, node, $event)" >{{node.name}}</a>' +
|
||||
'<i title="#{{node.routePath}}" class="{{node.cssClass}}" style="{{node.style}}"></i>' +
|
||||
'<a href ng-click="select(this, node, $event)" >{{node.name}}</a>' +
|
||||
'<a href class="umb-options" ng-hide="!node.menuUrl" ng-click="options(this, node, $event)"><i></i><i></i><i></i></a>' +
|
||||
'<div ng-show="node.loading" class="l"><div></div></div>' +
|
||||
'</div>' +
|
||||
|
||||
@@ -94,7 +94,9 @@ function valPropertyMsg(serverValidationManager) {
|
||||
// we need to re-validate it for the server side validator so the user can resubmit
|
||||
// the form. Of course normal client-side validators will continue to execute.
|
||||
scope.$watch("property.value", function (newValue) {
|
||||
if (formCtrl.$invalid) {
|
||||
//we are explicitly checking for valServer errors here, since we shouldn't auto clear
|
||||
// based on other errors.
|
||||
if (formCtrl.$invalid && scope.formCtrl.$error.valServer !== undefined) {
|
||||
scope.errorMsg = "";
|
||||
formCtrl.$setValidity('valPropertyMsg', true);
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@ function valServer(serverValidationManager) {
|
||||
ctrl.$viewChangeListeners.push(function () {
|
||||
if (ctrl.$invalid) {
|
||||
ctrl.$setValidity('valServer', true);
|
||||
//emit the event upwards
|
||||
scope.$emit("serverRevalidated", { modelCtrl: ctrl });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@ function valServerField(serverValidationManager) {
|
||||
ctrl.$viewChangeListeners.push(function () {
|
||||
if (ctrl.$invalid) {
|
||||
ctrl.$setValidity('valServerField', true);
|
||||
//emit the event upwards
|
||||
scope.$emit("serverRevalidated", { modelCtrl: ctrl });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ function valTab() {
|
||||
|
||||
var tabId = "tab" + scope.tab.id;
|
||||
|
||||
//assign the form control to our isolated scope so we can watch it's values
|
||||
scope.formCtrl = formCtrl;
|
||||
scope.tabHasError = false;
|
||||
|
||||
|
||||
@@ -15,10 +15,13 @@ function valToggleMsg(serverValidationManager) {
|
||||
throw "valToggleMsg requires that the attribute valMsgFor exists on the element";
|
||||
}
|
||||
|
||||
//assign the form control to our isolated scope so we can watch it's values
|
||||
scope.formCtrl = formCtrl;
|
||||
|
||||
//if there's any remaining errors in the server validation service then we should show them.
|
||||
var showValidation = serverValidationManager.items.length > 0;
|
||||
var hasError = false;
|
||||
|
||||
|
||||
//add a watch to the validator for the value (i.e. myForm.value.$error.required )
|
||||
scope.$watch(formCtrl.$name + "." + attr.valMsgFor + ".$error." + attr.valToggleMsg, function (isInvalid, oldValue) {
|
||||
hasError = isInvalid;
|
||||
|
||||
@@ -45,7 +45,7 @@ angular.module('umbraco.mocks').
|
||||
label: "Sample Editor",
|
||||
id: 3,
|
||||
properties: [
|
||||
{ alias: "datepicker", label: "Datepicker", view: "datepicker", config: { rows: 7 } },
|
||||
{ alias: "datepicker", label: "Datepicker", view: "datepicker", config: { pickTime: false, format: "yyyy-MM-dd" } },
|
||||
{ alias: "tags", label: "Tags", view: "tags", value: "" }
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,69 +1,77 @@
|
||||
app.config(function ($routeProvider) {
|
||||
$routeProvider
|
||||
.when('/framed/:url', {
|
||||
//This occurs when we need to launch some content in an iframe
|
||||
templateUrl: function (rp) {
|
||||
if (!rp.url)
|
||||
throw "A framed resource must have a url route parameter";
|
||||
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/:section', {
|
||||
templateUrl: function (rp) {
|
||||
if (rp.section === "default")
|
||||
{
|
||||
rp.section = "content";
|
||||
}
|
||||
|
||||
rp.url = "dashboard.aspx?app=" + rp.section;
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/:section/:tree', {
|
||||
templateUrl: function (rp) {
|
||||
if (rp.section === "default")
|
||||
{
|
||||
rp.section = "content";
|
||||
}
|
||||
|
||||
if (rp.tree === "")
|
||||
{
|
||||
rp.tree = "default";
|
||||
}
|
||||
|
||||
rp.url = "dashboard.aspx?app=" + rp.section;
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/:section/:tree/:method', {
|
||||
templateUrl: function(rp) {
|
||||
if (!rp.method){
|
||||
return "views/common/dashboard.html";
|
||||
}
|
||||
|
||||
if(rp.tree === "default" || rp.tree === ""){
|
||||
return 'views/' + rp.section + '/' + rp.method + '.html';
|
||||
}else{
|
||||
return 'views/' + rp.section + '/' + rp.tree + '/' + rp.method + '.html';
|
||||
}
|
||||
}
|
||||
})
|
||||
.when('/:section/:tree/:method/:id', {
|
||||
templateUrl: function (rp) {
|
||||
return 'views/' + rp.section + '/' + rp.tree + '/' + rp.method + '.html';
|
||||
}
|
||||
})
|
||||
.otherwise({ redirectTo: '/content/document' });
|
||||
}).config(function ($locationProvider) {
|
||||
|
||||
//$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off
|
||||
// $locationProvider.html5Mode(true); //turn html5 mode on
|
||||
});
|
||||
|
||||
|
||||
app.run(['userService', function (userService) {
|
||||
// Get the current user when the application starts
|
||||
// (in case they are still logged in from a previous session)
|
||||
userService.isAuthenticated();
|
||||
}]);
|
||||
app.config(function ($routeProvider) {
|
||||
$routeProvider
|
||||
.when('/framed/:url', {
|
||||
//This occurs when we need to launch some content in an iframe
|
||||
templateUrl: function (rp) {
|
||||
if (!rp.url)
|
||||
throw "A framed resource must have a url route parameter";
|
||||
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/:section', {
|
||||
templateUrl: function (rp) {
|
||||
if (rp.section === "default")
|
||||
{
|
||||
rp.section = "content";
|
||||
}
|
||||
|
||||
rp.url = "dashboard.aspx?app=" + rp.section;
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/:section/:tree', {
|
||||
templateUrl: function (rp) {
|
||||
if (rp.section === "default")
|
||||
{
|
||||
rp.section = "content";
|
||||
}
|
||||
|
||||
if (rp.tree === "")
|
||||
{
|
||||
rp.tree = "default";
|
||||
}
|
||||
|
||||
rp.url = "dashboard.aspx?app=" + rp.section;
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/:section/:tree/:method', {
|
||||
templateUrl: function(rp) {
|
||||
if (!rp.method){
|
||||
return "views/common/dashboard.html";
|
||||
}
|
||||
|
||||
if(rp.tree === "default" || rp.tree === ""){
|
||||
return 'views/' + rp.section + '/' + rp.method + '.html';
|
||||
}else{
|
||||
return 'views/' + rp.section + '/' + rp.tree + '/' + rp.method + '.html';
|
||||
}
|
||||
}
|
||||
})
|
||||
.when('/:section/:tree/:method/:id', {
|
||||
templateUrl: function (rp) {
|
||||
if (!rp.method)
|
||||
return "views/common/dashboard.html";
|
||||
|
||||
////here we detect recycle bins, all recycle bins start with -2* (i.e. -20, -21)
|
||||
//if (rp.id.startsWith("-2")) {
|
||||
// return 'views/' + rp.section + '/recyclebin.html';
|
||||
//}
|
||||
|
||||
return 'views/' + rp.section + '/' + rp.tree + '/' + rp.method + '.html';
|
||||
}
|
||||
})
|
||||
.otherwise({ redirectTo: '/content/document' });
|
||||
}).config(function ($locationProvider) {
|
||||
|
||||
//$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off
|
||||
// $locationProvider.html5Mode(true); //turn html5 mode on
|
||||
});
|
||||
|
||||
|
||||
app.run(['userService', function (userService) {
|
||||
// Get the current user when the application starts
|
||||
// (in case they are still logged in from a previous session)
|
||||
userService.isAuthenticated();
|
||||
}]);
|
||||
|
||||
Vendored
+8
File diff suppressed because one or more lines are too long
Vendored
+26
File diff suppressed because one or more lines are too long
-18
@@ -1,18 +0,0 @@
|
||||
/* Show cursor when hovering dates and navigation arrows, to indicate they are clickable */
|
||||
.datepicker-days .day,
|
||||
.datepicker .add-on,
|
||||
.datepicker-days .icon-arrow-right {
|
||||
cursor: pointer;
|
||||
}
|
||||
.datepicker-days .day:hover {
|
||||
background: #f8f8f7;
|
||||
}
|
||||
/* Ensures that the "select" color is not shown when clicking arrows in the datepicker window */
|
||||
.datepicker-days .icon-arrow-right {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
-1174
File diff suppressed because it is too large
Load Diff
+39
-20
@@ -1,27 +1,46 @@
|
||||
angular.module("umbraco").controller("Umbraco.Editors.DatepickerController",
|
||||
function ($scope, notificationsService, assetsService) {
|
||||
|
||||
assetsService.loadJs(
|
||||
'views/propertyeditors/datepicker/bootstrap.datepicker.js'
|
||||
).then(
|
||||
function () {
|
||||
//The Datepicker js and css files are available and all components are ready to use.
|
||||
|
||||
// Get the id of the datepicker button that was clicked
|
||||
var pickerId = $scope.model.alias;
|
||||
//setup the default config
|
||||
var config = {
|
||||
pickDate: true,
|
||||
pickTime: true,
|
||||
format: "yyyy-MM-dd HH:mm:ss"
|
||||
};
|
||||
//map the user config
|
||||
angular.extend(config, $scope.model.config);
|
||||
//map back to the model
|
||||
$scope.model.config = config;
|
||||
|
||||
// Open the datepicker and add a changeDate eventlistener
|
||||
$("#" + pickerId).datepicker({
|
||||
format: "dd/mm/yyyy",
|
||||
autoclose: true
|
||||
}).on("changeDate", function (e) {
|
||||
// When a date is clicked the date is stored in model.value as a ISO 8601 date
|
||||
$scope.model.value = e.date.toIsoDateTimeString();
|
||||
assetsService.loadJs(
|
||||
'views/propertyeditors/datepicker/bootstrap-datetimepicker.min.js'
|
||||
).then(
|
||||
function () {
|
||||
//The Datepicker js and css files are available and all components are ready to use.
|
||||
|
||||
// Get the id of the datepicker button that was clicked
|
||||
var pickerId = $scope.model.alias;
|
||||
|
||||
// Open the datepicker and add a changeDate eventlistener
|
||||
$("#" + pickerId).datetimepicker($scope.model.config).on("changeDate", function (e) {
|
||||
// when a date is changed, update the model
|
||||
if (e.localDate) {
|
||||
if ($scope.model.config.format == "yyyy-MM-dd HH:mm:ss") {
|
||||
$scope.model.value = e.localDate.toIsoDateTimeString();
|
||||
}
|
||||
else {
|
||||
$scope.model.value = e.localDate.toIsoDateString();
|
||||
}
|
||||
}
|
||||
else {
|
||||
$scope.model.value = null;
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
assetsService.loadCss(
|
||||
'views/propertyeditors/datepicker/bootstrap.datepicker.css'
|
||||
);
|
||||
});
|
||||
assetsService.loadCss(
|
||||
'views/propertyeditors/datepicker/bootstrap-datetimepicker.min.css'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<div ng-controller="Umbraco.Editors.DatepickerController">
|
||||
<div class="input-append date datepicker" id="{{model.alias}}">
|
||||
<input data-format="dd/MM/yyyy" type="text" value="{{model.value | date:'dd/MM/yyyy'}}" />
|
||||
<span class="add-on"> <i class="icon-calendar"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-append date datepicker" id="{{model.alias}}">
|
||||
<input name="datepicker" data-format="{{model.config.format}}" type="text"
|
||||
ng-model="model.value"
|
||||
val-server="value" />
|
||||
<span class="add-on">
|
||||
<i data-time-icon="icon-time" data-date-icon="icon-calendar"></i>
|
||||
</span>
|
||||
</div>
|
||||
<span class="help-inline" val-msg-for="datepicker" val-toggle-msg="valServer">{{propertyForm.datepicker.errorMsg}}</span>
|
||||
</div>
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
var values = [];
|
||||
|
||||
//this will be comma delimited
|
||||
if ($scope.value && (typeof $scope.value == "string")) {
|
||||
var splitVals = $scope.value.split(",");
|
||||
if ($scope.model.value && (typeof $scope.model.value == "string")) {
|
||||
var splitVals = $scope.model.value.split(",");
|
||||
//set the values of our object
|
||||
for (var i = 0; i < splitVals.length; i++) {
|
||||
values.push({
|
||||
@@ -35,7 +35,7 @@
|
||||
csv.push(newValue[v].value);
|
||||
}
|
||||
//write the csv value back to the property
|
||||
$scope.value = csv.join();
|
||||
$scope.model.value = csv.join();
|
||||
}, true);
|
||||
};
|
||||
|
||||
|
||||
@@ -11,5 +11,5 @@
|
||||
</ng-form>
|
||||
</div>
|
||||
|
||||
<span>{{value}}</span>
|
||||
<span>{{model.value}}</span>
|
||||
</div>
|
||||
@@ -1,8 +1,8 @@
|
||||
<div ng-controller="MyPackage.PropertyEditors.PostcodeEditor">
|
||||
<p>
|
||||
Enter a postcode for country <span>{{config.country}}</span>
|
||||
Enter a postcode for country <span>{{model.config.country}}</span>
|
||||
</p>
|
||||
<input name="myPackage_postcode" type="text" ng-model="value"
|
||||
<input name="myPackage_postcode" type="text" ng-model="model.value"
|
||||
val-server="value"
|
||||
val-postcode="config.country"/>
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<div ng-controller="MyPackage.PropertyEditors.RegexEditor">
|
||||
<span>{{model.value}}</span>
|
||||
|
||||
<p>
|
||||
Value in the format of <span>{{config}}</span>
|
||||
Value in the format of <span>{{model.config}}</span>
|
||||
</p>
|
||||
|
||||
<input name="regex" id="regex"
|
||||
type="text" ng-model="value"
|
||||
type="text" ng-model="model.value"
|
||||
required
|
||||
val-regex="config"
|
||||
val-server="value" />
|
||||
|
||||
@@ -114,9 +114,9 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\ClientDependency-Mvc.1.7.0.4\lib\ClientDependency.Core.Mvc.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Examine, Version=0.1.52.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Examine.0.1.51.2941\lib\Examine.dll</HintPath>
|
||||
<HintPath>..\packages\Examine.0.1.52.2941\lib\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=1.2.11.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
app.config(function ($routeProvider) {
|
||||
$routeProvider
|
||||
.when('/framed/:url', {
|
||||
//This occurs when we need to launch some content in an iframe
|
||||
templateUrl: function (rp) {
|
||||
if (!rp.url)
|
||||
throw "A framed resource must have a url route parameter";
|
||||
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/:section', {
|
||||
templateUrl: function (rp) {
|
||||
if (rp.section === "default")
|
||||
{
|
||||
rp.section = "content";
|
||||
}
|
||||
|
||||
rp.url = "dashboard.aspx?app=" + rp.section;
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/:section/:tree', {
|
||||
templateUrl: function (rp) {
|
||||
if (rp.section === "default")
|
||||
{
|
||||
rp.section = "content";
|
||||
}
|
||||
|
||||
if (rp.tree === "")
|
||||
{
|
||||
rp.tree = "default";
|
||||
}
|
||||
|
||||
rp.url = "dashboard.aspx?app=" + rp.section;
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/:section/:tree/:method', {
|
||||
templateUrl: function(rp) {
|
||||
if (!rp.method){
|
||||
return "views/common/dashboard.html";
|
||||
}
|
||||
|
||||
if(rp.tree === "default" || rp.tree === ""){
|
||||
return 'views/' + rp.section + '/' + rp.method + '.html';
|
||||
}else{
|
||||
return 'views/' + rp.section + '/' + rp.tree + '/' + rp.method + '.html';
|
||||
}
|
||||
}
|
||||
})
|
||||
.when('/:section/:tree/:method/:id', {
|
||||
templateUrl: function (rp) {
|
||||
<<<<<<< HEAD
|
||||
return 'views/' + rp.section + '/' + rp.tree + '/' + rp.method + '.html';
|
||||
=======
|
||||
if (!rp.method)
|
||||
return "views/common/dashboard.html";
|
||||
|
||||
return 'views/' + rp.section + '/' + rp.method + '.html';
|
||||
>>>>>>> 4a8026c902fd1f6afa32749882611c7e4d37e882
|
||||
}
|
||||
})
|
||||
.otherwise({ redirectTo: '/content/document' });
|
||||
}).config(function ($locationProvider) {
|
||||
|
||||
//$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off
|
||||
// $locationProvider.html5Mode(true); //turn html5 mode on
|
||||
});
|
||||
|
||||
|
||||
app.run(['userService', function (userService) {
|
||||
// Get the current user when the application starts
|
||||
// (in case they are still logged in from a previous session)
|
||||
userService.isAuthenticated();
|
||||
}]);
|
||||
@@ -0,0 +1,56 @@
|
||||
app.config(function ($routeProvider) {
|
||||
$routeProvider
|
||||
.when('/:section', {
|
||||
templateUrl: function (rp) {
|
||||
if (rp.section === "default")
|
||||
{
|
||||
rp.section = "content";
|
||||
}
|
||||
|
||||
rp.url = "dashboard.aspx?app=" + rp.section;
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/framed/:url', {
|
||||
//This occurs when we need to launch some content in an iframe
|
||||
templateUrl: function (rp) {
|
||||
if (!rp.url)
|
||||
throw "A framed resource must have a url route parameter";
|
||||
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/:section/:method', {
|
||||
templateUrl: function(rp) {
|
||||
if (!rp.method)
|
||||
return "views/common/dashboard.html";
|
||||
|
||||
return 'views/' + rp.section + '/' + rp.method + '.html';
|
||||
}
|
||||
})
|
||||
.when('/:section/:method/:id', {
|
||||
templateUrl: function (rp) {
|
||||
if (!rp.method)
|
||||
return "views/common/dashboard.html";
|
||||
|
||||
////here we detect recycle bins, all recycle bins start with -2* (i.e. -20, -21)
|
||||
//if (rp.id.startsWith("-2")) {
|
||||
// return 'views/' + rp.section + '/recyclebin.html';
|
||||
//}
|
||||
|
||||
return 'views/' + rp.section + '/' + rp.method + '.html';
|
||||
}
|
||||
})
|
||||
.otherwise({ redirectTo: '/content' });
|
||||
}).config(function ($locationProvider) {
|
||||
|
||||
//$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off
|
||||
// $locationProvider.html5Mode(true); //turn html5 mode on
|
||||
});
|
||||
|
||||
|
||||
app.run(['userService', function (userService) {
|
||||
// Get the current user when the application starts
|
||||
// (in case they are still logged in from a previous session)
|
||||
userService.isAuthenticated();
|
||||
}]);
|
||||
@@ -0,0 +1,69 @@
|
||||
app.config(function ($routeProvider) {
|
||||
$routeProvider
|
||||
.when('/framed/:url', {
|
||||
//This occurs when we need to launch some content in an iframe
|
||||
templateUrl: function (rp) {
|
||||
if (!rp.url)
|
||||
throw "A framed resource must have a url route parameter";
|
||||
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/:section', {
|
||||
templateUrl: function (rp) {
|
||||
if (rp.section === "default")
|
||||
{
|
||||
rp.section = "content";
|
||||
}
|
||||
|
||||
rp.url = "dashboard.aspx?app=" + rp.section;
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/:section/:tree', {
|
||||
templateUrl: function (rp) {
|
||||
if (rp.section === "default")
|
||||
{
|
||||
rp.section = "content";
|
||||
}
|
||||
|
||||
if (rp.tree === "")
|
||||
{
|
||||
rp.tree = "default";
|
||||
}
|
||||
|
||||
rp.url = "dashboard.aspx?app=" + rp.section;
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/:section/:tree/:method', {
|
||||
templateUrl: function(rp) {
|
||||
if (!rp.method){
|
||||
return "views/common/dashboard.html";
|
||||
}
|
||||
|
||||
if(rp.tree === "default" || rp.tree === ""){
|
||||
return 'views/' + rp.section + '/' + rp.method + '.html';
|
||||
}else{
|
||||
return 'views/' + rp.section + '/' + rp.tree + '/' + rp.method + '.html';
|
||||
}
|
||||
}
|
||||
})
|
||||
.when('/:section/:tree/:method/:id', {
|
||||
templateUrl: function (rp) {
|
||||
return 'views/' + rp.section + '/' + rp.tree + '/' + rp.method + '.html';
|
||||
}
|
||||
})
|
||||
.otherwise({ redirectTo: '/content/document' });
|
||||
}).config(function ($locationProvider) {
|
||||
|
||||
//$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off
|
||||
// $locationProvider.html5Mode(true); //turn html5 mode on
|
||||
});
|
||||
|
||||
|
||||
app.run(['userService', function (userService) {
|
||||
// Get the current user when the application starts
|
||||
// (in case they are still logged in from a previous session)
|
||||
userService.isAuthenticated();
|
||||
}]);
|
||||
@@ -0,0 +1,51 @@
|
||||
app.config(function ($routeProvider) {
|
||||
$routeProvider
|
||||
.when('/:section', {
|
||||
templateUrl: function (rp) {
|
||||
if (rp.section === "default")
|
||||
{
|
||||
rp.section = "content";
|
||||
}
|
||||
|
||||
rp.url = "dashboard.aspx?app=" + rp.section;
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/framed/:url', {
|
||||
//This occurs when we need to launch some content in an iframe
|
||||
templateUrl: function (rp) {
|
||||
if (!rp.url)
|
||||
throw "A framed resource must have a url route parameter";
|
||||
|
||||
return 'views/common/legacy.html';
|
||||
}
|
||||
})
|
||||
.when('/:section/:method', {
|
||||
templateUrl: function(rp) {
|
||||
if (!rp.method)
|
||||
return "views/common/dashboard.html";
|
||||
|
||||
return 'views/' + rp.section + '/' + rp.method + '.html';
|
||||
}
|
||||
})
|
||||
.when('/:section/:method/:id', {
|
||||
templateUrl: function (rp) {
|
||||
if (!rp.method)
|
||||
return "views/common/dashboard.html";
|
||||
|
||||
return 'views/' + rp.section + '/' + rp.method + '.html';
|
||||
}
|
||||
})
|
||||
.otherwise({ redirectTo: '/content' });
|
||||
}).config(function ($locationProvider) {
|
||||
|
||||
//$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off
|
||||
// $locationProvider.html5Mode(true); //turn html5 mode on
|
||||
});
|
||||
|
||||
|
||||
app.run(['userService', function (userService) {
|
||||
// Get the current user when the application starts
|
||||
// (in case they are still logged in from a previous session)
|
||||
userService.isAuthenticated();
|
||||
}]);
|
||||
@@ -26,6 +26,5 @@ More information and documentation can be found on CodePlex: http://umbracoexami
|
||||
|
||||
<!-- Default Indexset for external searches, this indexes all fields on all types of nodes-->
|
||||
<IndexSet SetName="ExternalIndexSet" IndexPath="~/App_Data/TEMP/ExamineIndexes/External/" />
|
||||
|
||||
|
||||
</ExamineLuceneIndexSets>
|
||||
@@ -21,7 +21,7 @@ More information and documentation can be found on CodePlex: http://umbracoexami
|
||||
|
||||
<!-- default external indexer, which excludes protected and published pages-->
|
||||
<add name="ExternalIndexer" type="UmbracoExamine.UmbracoContentIndexer, UmbracoExamine"/>
|
||||
|
||||
|
||||
</providers>
|
||||
</ExamineIndexProviders>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<packages>
|
||||
<package id="ClientDependency" version="1.7.0.4" targetFramework="net40" />
|
||||
<package id="ClientDependency-Mvc" version="1.7.0.4" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.51.2941" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
|
||||
<package id="log4net-mediumtrust" version="2.0.0" targetFramework="net40" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
|
||||
|
||||
@@ -195,7 +195,9 @@ namespace Umbraco.Web.Editors
|
||||
contentItem.PersistedContent.ExpireDate = contentItem.ExpireDate;
|
||||
contentItem.PersistedContent.ReleaseDate = contentItem.ReleaseDate;
|
||||
//only set the template if it didn't change
|
||||
if (contentItem.PersistedContent.Template.Alias != contentItem.TemplateAlias)
|
||||
var templateChanged = (contentItem.PersistedContent.Template == null && contentItem.TemplateAlias.IsNullOrWhiteSpace() == false)
|
||||
|| (contentItem.PersistedContent.Template != null && contentItem.PersistedContent.Template.Alias != contentItem.TemplateAlias);
|
||||
if (templateChanged)
|
||||
{
|
||||
var template = Services.FileService.GetTemplate(contentItem.TemplateAlias);
|
||||
if (template == null)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Web.Http;
|
||||
@@ -32,20 +31,4 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
public string[] Urls { get; set; }
|
||||
|
||||
}
|
||||
|
||||
[DataContract(Name = "template", Namespace = "")]
|
||||
public class TemplateBasic
|
||||
{
|
||||
[DataMember(Name = "id", IsRequired = true)]
|
||||
[Required]
|
||||
public int Id { get; set; }
|
||||
|
||||
[DataMember(Name = "name", IsRequired = true)]
|
||||
[Required(AllowEmptyStrings = false)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[DataMember(Name = "alias", IsRequired = true)]
|
||||
[Required(AllowEmptyStrings = false)]
|
||||
public string Alias { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
public string View { get; set; }
|
||||
|
||||
[DataMember(Name = "config")]
|
||||
public IEnumerable<string> Config { get; set; }
|
||||
public IDictionary<string, object> Config { get; set; }
|
||||
|
||||
[DataMember(Name = "hideLabel")]
|
||||
public bool HideLabel { get; set; }
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
public IDataTypeDefinition DataType { get; set; }
|
||||
public string Label { get; set; }
|
||||
public string Description { get; set; }
|
||||
public PropertyEditor PropertyEditor { get; set; }
|
||||
public bool IsRequired { get; set; }
|
||||
public string ValidationRegExp { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
[DataContract(Name = "template", Namespace = "")]
|
||||
public class TemplateBasic
|
||||
{
|
||||
[DataMember(Name = "id", IsRequired = true)]
|
||||
[Required]
|
||||
public int Id { get; set; }
|
||||
|
||||
[DataMember(Name = "name", IsRequired = true)]
|
||||
[Required(AllowEmptyStrings = false)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[DataMember(Name = "alias", IsRequired = true)]
|
||||
[Required(AllowEmptyStrings = false)]
|
||||
public string Alias { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,11 @@ namespace Umbraco.Web.Models.Mapping
|
||||
internal class ContentPropertyBasicConverter<T> : TypeConverter<Property, T>
|
||||
where T : ContentPropertyBasic, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Assigns the PropertyEditor, Id, Alias and Value to the property
|
||||
/// </summary>
|
||||
/// <param name="property"></param>
|
||||
/// <returns></returns>
|
||||
protected override T ConvertCore(Property property)
|
||||
{
|
||||
var editor = PropertyEditorResolver.Current.GetById(property.PropertyType.DataTypeId);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using Umbraco.Core;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.Models.Mapping
|
||||
@@ -25,7 +27,13 @@ namespace Umbraco.Web.Models.Mapping
|
||||
display.Alias = originalProp.Alias;
|
||||
display.Description = originalProp.PropertyType.Description;
|
||||
display.Label = originalProp.PropertyType.Name;
|
||||
display.Config = _applicationContext.Services.DataTypeService.GetPreValuesByDataTypeId(originalProp.PropertyType.DataTypeDefinitionId);
|
||||
var dataTypeService = (DataTypeService) _applicationContext.Services.DataTypeService;
|
||||
|
||||
var preVals = dataTypeService.GetPreValuesCollectionByDataTypeId(originalProp.PropertyType.DataTypeDefinitionId);
|
||||
|
||||
//let the property editor format the pre-values
|
||||
display.Config = display.PropertyEditor.FormatPreValues(display.PropertyEditor.DefaultPreValues, preVals);
|
||||
|
||||
if (display.PropertyEditor == null)
|
||||
{
|
||||
//if there is no property editor it means that it is a legacy data type
|
||||
|
||||
@@ -23,11 +23,9 @@ namespace Umbraco.Web.Models.Mapping
|
||||
|
||||
propertyDto.IsRequired = originalProperty.PropertyType.Mandatory;
|
||||
propertyDto.ValidationRegExp = originalProperty.PropertyType.ValidationRegExp;
|
||||
propertyDto.Alias = originalProperty.Alias;
|
||||
propertyDto.Description = originalProperty.PropertyType.Description;
|
||||
propertyDto.Label = originalProperty.PropertyType.Name;
|
||||
propertyDto.DataType = _applicationContext.Services.DataTypeService.GetDataTypeDefinitionById(originalProperty.PropertyType.DataTypeDefinitionId);
|
||||
propertyDto.PropertyEditor = PropertyEditorResolver.Current.GetById(originalProperty.PropertyType.DataTypeId);
|
||||
|
||||
return propertyDto;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
[PropertyEditor(Constants.PropertyEditors.Date, "Date", "datepicker", ValueType = "DATE")]
|
||||
public class DatePropertyEditor : PropertyEditor
|
||||
{
|
||||
public DatePropertyEditor()
|
||||
{
|
||||
_defaultPreVals = new Dictionary<string, object>
|
||||
{
|
||||
{"format", "yyyy-MM-dd"},
|
||||
{"pickTime", false}
|
||||
};
|
||||
}
|
||||
|
||||
private IDictionary<string, object> _defaultPreVals;
|
||||
|
||||
/// <summary>
|
||||
/// Overridden because we ONLY support Date (no time) format and we don't have pre-values in the db.
|
||||
/// </summary>
|
||||
public override IDictionary<string, object> DefaultPreValues
|
||||
{
|
||||
get { return _defaultPreVals; }
|
||||
set { _defaultPreVals = value; }
|
||||
}
|
||||
|
||||
protected override ValueEditor CreateValueEditor()
|
||||
{
|
||||
var baseEditor = base.CreateValueEditor();
|
||||
|
||||
return new DateValueEditor
|
||||
{
|
||||
View = baseEditor.View
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CUstom value editor so we can serialize with the correct date format (excluding time)
|
||||
/// and includes the date validator
|
||||
/// </summary>
|
||||
private class DateValueEditor : ValueEditor
|
||||
{
|
||||
public DateValueEditor()
|
||||
{
|
||||
Validators = new List<ValidatorBase> { new DateTimeValidator() };
|
||||
}
|
||||
|
||||
public override string SerializeValue(object dbValue)
|
||||
{
|
||||
var date = dbValue.TryConvertTo<DateTime?>();
|
||||
if (date.Success == false || date.Result == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
//Dates will be formatted as yyyy-MM-dd
|
||||
return date.Result.Value.ToString("yyyy-MM-dd");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
[PropertyEditor(Constants.PropertyEditors.DateTime, "Date/Time", "datepicker", ValueType = "DATETIME")]
|
||||
public class DateTimePropertyEditor : PropertyEditor
|
||||
{
|
||||
public DateTimePropertyEditor()
|
||||
{
|
||||
_defaultPreVals = new Dictionary<string, object>
|
||||
{
|
||||
{"format", "yyyy-MM-dd HH:mm:ss"}
|
||||
};
|
||||
}
|
||||
|
||||
private IDictionary<string, object> _defaultPreVals;
|
||||
|
||||
/// <summary>
|
||||
/// Overridden because we ONLY support Date + Time format and we don't have pre-values in the db.
|
||||
/// </summary>
|
||||
public override IDictionary<string, object> DefaultPreValues
|
||||
{
|
||||
get { return _defaultPreVals; }
|
||||
set { _defaultPreVals = value; }
|
||||
}
|
||||
|
||||
protected override ValueEditor CreateValueEditor()
|
||||
{
|
||||
var editor = base.CreateValueEditor();
|
||||
|
||||
editor.Validators = new List<ValidatorBase> { new DateTimeValidator() };
|
||||
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to validate if the value is a valid date/time
|
||||
/// </summary>
|
||||
internal class DateTimeValidator : ValidatorBase
|
||||
{
|
||||
public override IEnumerable<ValidationResult> Validate(string value, string preValues, PropertyEditor editor)
|
||||
{
|
||||
DateTime dt;
|
||||
if (value.IsNullOrWhiteSpace() == false && DateTime.TryParse(value, out dt) == false)
|
||||
{
|
||||
yield return new ValidationResult(string.Format("The string value {0} cannot be parsed into a DateTime", value),
|
||||
new[]
|
||||
{
|
||||
//we only store a single value for this editor so the 'member' or 'field'
|
||||
// we'll associate this error with will simply be called 'value'
|
||||
"value"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,9 +106,9 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\xmlrpcnet.2.5.0\lib\net20\CookComputing.XmlRpcV2.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Examine, Version=0.1.52.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Examine.0.1.51.2941\lib\Examine.dll</HintPath>
|
||||
<HintPath>..\packages\Examine.0.1.52.2941\lib\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HtmlAgilityPack, Version=1.4.6.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
@@ -299,7 +299,11 @@
|
||||
<Compile Include="Editors\AuthenticationController.cs" />
|
||||
<Compile Include="Editors\ContentController.cs" />
|
||||
<Compile Include="Editors\EntityController.cs" />
|
||||
<Compile Include="Models\ContentEditing\TemplateBasic.cs" />
|
||||
<Compile Include="Models\PagedResult.cs" />
|
||||
<Compile Include="PropertyEditors\DatePropertyEditor.cs" />
|
||||
<Compile Include="PropertyEditors\DateTimePropertyEditor.cs" />
|
||||
<Compile Include="PropertyEditors\DateTimeValidator.cs" />
|
||||
<Compile Include="PropertyEditors\LabelPropertyEditor.cs" />
|
||||
<Compile Include="PropertyEditors\LabelValueEditor.cs" />
|
||||
<Compile Include="Routing\UrlProviderExtensions.cs" />
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace Umbraco.Web
|
||||
/// <param name="httpContext"></param>
|
||||
static void BeginRequest(HttpContextBase httpContext)
|
||||
{
|
||||
|
||||
//we need to set the initial url in our ApplicationContext, this is so our keep alive service works and this must
|
||||
//exist on a global context because the keep alive service doesn't run in a web context.
|
||||
//we are NOT going to put a lock on this because locking will slow down the application and we don't really care
|
||||
@@ -170,26 +171,34 @@ namespace Umbraco.Web
|
||||
var ticket = http.GetUmbracoAuthTicket();
|
||||
if (ticket != null && !ticket.Expired && http.RenewUmbracoAuthTicket())
|
||||
{
|
||||
//create the Umbraco user identity
|
||||
var identity = new UmbracoBackOfficeIdentity(ticket);
|
||||
|
||||
//set the principal object
|
||||
var principal = new GenericPrincipal(identity, identity.Roles);
|
||||
|
||||
//It is actually not good enough to set this on the current app Context and the thread, it also needs
|
||||
// to be set explicitly on the HttpContext.Current !! This is a strange web api thing that is actually
|
||||
// an underlying fault of asp.net not propogating the User correctly.
|
||||
if (HttpContext.Current != null)
|
||||
try
|
||||
{
|
||||
HttpContext.Current.User = principal;
|
||||
}
|
||||
app.Context.User = principal;
|
||||
Thread.CurrentPrincipal = principal;
|
||||
//create the Umbraco user identity
|
||||
var identity = new UmbracoBackOfficeIdentity(ticket);
|
||||
|
||||
//This is a back office request, we will also set the culture/ui culture
|
||||
Thread.CurrentThread.CurrentCulture =
|
||||
Thread.CurrentThread.CurrentUICulture =
|
||||
new System.Globalization.CultureInfo(identity.Culture);
|
||||
//set the principal object
|
||||
var principal = new GenericPrincipal(identity, identity.Roles);
|
||||
|
||||
//It is actually not good enough to set this on the current app Context and the thread, it also needs
|
||||
// to be set explicitly on the HttpContext.Current !! This is a strange web api thing that is actually
|
||||
// an underlying fault of asp.net not propogating the User correctly.
|
||||
if (HttpContext.Current != null)
|
||||
{
|
||||
HttpContext.Current.User = principal;
|
||||
}
|
||||
app.Context.User = principal;
|
||||
Thread.CurrentPrincipal = principal;
|
||||
|
||||
//This is a back office request, we will also set the culture/ui culture
|
||||
Thread.CurrentThread.CurrentCulture =
|
||||
Thread.CurrentThread.CurrentUICulture =
|
||||
new System.Globalization.CultureInfo(identity.Culture);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
//this will occur if the cookie data is invalid
|
||||
http.UmbracoLogout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<package id="AutoMapper" version="2.2.1" targetFramework="net45" />
|
||||
<package id="ClientDependency" version="1.7.0.4" targetFramework="net40" />
|
||||
<package id="CodeSharp.Package.AspNetWebPage" version="1.0" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.51.2941" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
|
||||
<package id="HtmlAgilityPack" version="1.4.6" targetFramework="net40" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
|
||||
|
||||
@@ -40,9 +40,9 @@
|
||||
<Reference Include="AzureDirectory">
|
||||
<HintPath>..\packages\AzureDirectory.1.0.5\lib\AzureDirectory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Examine, Version=0.1.52.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Examine.0.1.51.2941\lib\Examine.dll</HintPath>
|
||||
<HintPath>..\packages\Examine.0.1.52.2941\lib\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine.Azure, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<packages>
|
||||
<package id="AnglicanGeek.WindowsAzure.ServiceRuntime" version="1.6" targetFramework="net40" />
|
||||
<package id="AzureDirectory" version="1.0.5" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.51.2941" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
|
||||
<package id="Examine.Azure" version="0.1.51.2941" targetFramework="net40" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net40" />
|
||||
|
||||
@@ -40,9 +40,9 @@
|
||||
<Reference Include="AzureDirectory">
|
||||
<HintPath>..\packages\AzureDirectory.1.0.5\lib\AzureDirectory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Examine, Version=0.1.52.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Examine.0.1.51.2941\lib\Examine.dll</HintPath>
|
||||
<HintPath>..\packages\Examine.0.1.52.2941\lib\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Examine.Azure, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<packages>
|
||||
<package id="AnglicanGeek.WindowsAzure.ServiceRuntime" version="1.6" targetFramework="net40" />
|
||||
<package id="AzureDirectory" version="1.0.5" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.51.2941" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
|
||||
<package id="Examine.Azure" version="0.1.51.2941" targetFramework="net40" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net40" />
|
||||
|
||||
@@ -12,6 +12,7 @@ using iTextSharp.text.pdf;
|
||||
using System.Text;
|
||||
using Lucene.Net.Analysis;
|
||||
using UmbracoExamine.DataServices;
|
||||
using iTextSharp.text.pdf.parser;
|
||||
|
||||
|
||||
namespace UmbracoExamine.PDF
|
||||
@@ -105,6 +106,7 @@ namespace UmbracoExamine.PDF
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="config"></param>
|
||||
[SecuritySafeCritical]
|
||||
public override void Initialize(string name, NameValueCollection config)
|
||||
{
|
||||
base.Initialize(name, config);
|
||||
@@ -133,7 +135,7 @@ namespace UmbracoExamine.PDF
|
||||
|
||||
Action<Exception> onError = (e) => OnIndexingError(new IndexingErrorEventArgs("Could not read PDF", -1, e));
|
||||
|
||||
var txt = pdf.ParsePdfText(file.FullName, onError);
|
||||
var txt = pdf.GetTextFromAllPages(file.FullName, onError);
|
||||
return txt;
|
||||
|
||||
}
|
||||
@@ -193,16 +195,21 @@ namespace UmbracoExamine.PDF
|
||||
|
||||
static PDFParser()
|
||||
{
|
||||
lock (m_Locker)
|
||||
lock (Locker)
|
||||
{
|
||||
m_UnsupportedRange = new List<int>();
|
||||
m_UnsupportedRange.AddRange(Enumerable.Range(0x0000, 0x001F));
|
||||
m_UnsupportedRange.Add(0x1F);
|
||||
UnsupportedRange = new HashSet<char>();
|
||||
foreach (var c in Enumerable.Range(0x0000, 0x001F))
|
||||
{
|
||||
UnsupportedRange.Add((char) c);
|
||||
}
|
||||
UnsupportedRange.Add((char)0x1F);
|
||||
|
||||
//replace line breaks with space
|
||||
ReplaceWithSpace = new HashSet<char> {'\r', '\n'};
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly object m_Locker = new object();
|
||||
private static readonly object Locker = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Stores the unsupported range of character
|
||||
@@ -214,61 +221,68 @@ namespace UmbracoExamine.PDF
|
||||
/// http://en.wikipedia.org/wiki/Unicode
|
||||
/// http://en.wikipedia.org/wiki/Basic_Multilingual_Plane
|
||||
/// </remarks>
|
||||
private static List<int> m_UnsupportedRange;
|
||||
private static HashSet<char> UnsupportedRange;
|
||||
|
||||
/// <summary>
|
||||
/// Return only the valid string contents of the PDF
|
||||
/// </summary>
|
||||
/// <param name="sourcePDF"></param>
|
||||
/// <param name="onError"></param>
|
||||
/// <returns></returns>
|
||||
[SecuritySafeCritical]
|
||||
public string ParsePdfText(string sourcePDF, Action<Exception> onError)
|
||||
private static HashSet<char> ReplaceWithSpace;
|
||||
|
||||
[SecuritySafeCritical]
|
||||
public string GetTextFromAllPages(string pdfPath, Action<Exception> onError)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var output = new StringWriter();
|
||||
|
||||
var reader = new PdfReader(sourcePDF);
|
||||
PRTokeniser token = null;
|
||||
var tknValue = String.Empty;
|
||||
|
||||
for (var i = 1; (i <= reader.NumberOfPages); i++)
|
||||
try
|
||||
{
|
||||
var pageBytes = reader.GetPageContent(i);
|
||||
if (pageBytes != null)
|
||||
{
|
||||
token = new PRTokeniser(pageBytes);
|
||||
try
|
||||
{
|
||||
while (token.NextToken())
|
||||
{
|
||||
var tknType = token.TokenType;
|
||||
tknValue = token.StringValue;
|
||||
if ((tknType == PRTokeniser.TokType.STRING))
|
||||
{
|
||||
foreach (var s in tknValue)
|
||||
{
|
||||
//strip out unsupported characters, based on unicode tables.
|
||||
if (!m_UnsupportedRange.Contains(s))
|
||||
{
|
||||
sb.Append(s);
|
||||
}
|
||||
}
|
||||
var reader = new PdfReader(pdfPath);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidPdfException ex)
|
||||
{
|
||||
onError(ex);
|
||||
}
|
||||
for (int i = 1; i <= reader.NumberOfPages; i++)
|
||||
{
|
||||
var result =
|
||||
ExceptChars(
|
||||
PdfTextExtractor.GetTextFromPage(reader, i, new SimpleTextExtractionStrategy()),
|
||||
UnsupportedRange,
|
||||
ReplaceWithSpace);
|
||||
output.Write(result);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
onError(ex);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
return output.ToString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// remove all toExclude chars from string
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="toExclude"></param>
|
||||
/// <param name="replaceWithSpace"></param>
|
||||
/// <returns></returns>
|
||||
private static string ExceptChars(string str, HashSet<char> toExclude, HashSet<char> replaceWithSpace)
|
||||
{
|
||||
var sb = new StringBuilder(str.Length);
|
||||
for (var i = 0; i < str.Length; i++)
|
||||
{
|
||||
var c = str[i];
|
||||
if (toExclude.Contains(c) == false)
|
||||
{
|
||||
if (replaceWithSpace.Contains(c))
|
||||
{
|
||||
sb.Append(" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(c);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -28,4 +28,5 @@ using System.Security;
|
||||
[assembly: AssemblyVersion("0.6.0.*")]
|
||||
[assembly: AssemblyFileVersion("0.6.0.*")]
|
||||
|
||||
[assembly: AllowPartiallyTrustedCallers]
|
||||
//Unfortunately itextsharp does not natively support full trust
|
||||
//[assembly: AllowPartiallyTrustedCallers]
|
||||
@@ -46,9 +46,9 @@
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Examine, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Examine, Version=0.1.52.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Examine.0.1.51.2941\lib\Examine.dll</HintPath>
|
||||
<HintPath>..\packages\Examine.0.1.52.2941\lib\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib">
|
||||
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Examine" version="0.1.51.2941" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
|
||||
<package id="iTextSharp" version="5.3.3" targetFramework="net40" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net40" />
|
||||
|
||||
@@ -96,6 +96,7 @@ namespace UmbracoExamine
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="config"></param>
|
||||
[SecuritySafeCritical]
|
||||
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
|
||||
{
|
||||
if (config["dataService"] != null && !string.IsNullOrEmpty(config["dataService"]))
|
||||
|
||||
@@ -124,6 +124,7 @@ namespace UmbracoExamine
|
||||
/// <exception cref="T:System.InvalidOperationException">
|
||||
/// An attempt is made to call <see cref="M:System.Configuration.Provider.ProviderBase.Initialize(System.String,System.Collections.Specialized.NameValueCollection)"/> on a provider after the provider has already been initialized.
|
||||
/// </exception>
|
||||
[SecuritySafeCritical]
|
||||
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
|
||||
{
|
||||
|
||||
|
||||
@@ -82,9 +82,9 @@
|
||||
<AssemblyOriginatorKeyFile>..\Solution Items\TheFARM-Public.snk</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Examine, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Examine, Version=0.1.52.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Examine.0.1.51.2941\lib\Examine.dll</HintPath>
|
||||
<HintPath>..\packages\Examine.0.1.52.2941\lib\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace UmbracoExamine
|
||||
}
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException("name");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Examine" version="0.1.51.2941" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net40" />
|
||||
</packages>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Examine" version="0.1.51.2941" targetFramework="net40" />
|
||||
<package id="Examine" version="0.1.52.2941" targetFramework="net40" />
|
||||
<package id="HtmlAgilityPack" version="1.4.6" targetFramework="net40" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net40" />
|
||||
<package id="Microsoft.AspNet.Mvc" version="4.0.30506.0" targetFramework="net40" />
|
||||
|
||||
@@ -45,9 +45,9 @@
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Examine, Version=0.1.51.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<Reference Include="Examine, Version=0.1.52.2941, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Examine.0.1.51.2941\lib\Examine.dll</HintPath>
|
||||
<HintPath>..\packages\Examine.0.1.52.2941\lib\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HtmlAgilityPack, Version=1.4.6.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
@@ -308,27 +309,35 @@ namespace umbraco
|
||||
{
|
||||
var cacheKey = "uitext_" + language;
|
||||
|
||||
return ApplicationContext.Current.ApplicationCache.GetCacheItem(
|
||||
cacheKey,
|
||||
CacheItemPriority.Default,
|
||||
new CacheDependency(IOHelper.MapPath(UmbracoPath + "/config/lang/" + language + ".xml")),
|
||||
() =>
|
||||
{
|
||||
using (var langReader = new XmlTextReader(IOHelper.MapPath(UmbracoPath + "/config/lang/" + language + ".xml")))
|
||||
var file = IOHelper.MapPath(UmbracoPath + "/config/lang/" + language + ".xml");
|
||||
if (File.Exists(file))
|
||||
{
|
||||
return ApplicationContext.Current.ApplicationCache.GetCacheItem(
|
||||
cacheKey,
|
||||
CacheItemPriority.Default,
|
||||
new CacheDependency(IOHelper.MapPath(UmbracoPath + "/config/lang/" + language + ".xml")),
|
||||
() =>
|
||||
{
|
||||
try
|
||||
using (var langReader = new XmlTextReader(IOHelper.MapPath(UmbracoPath + "/config/lang/" + language + ".xml")))
|
||||
{
|
||||
var langFile = new XmlDocument();
|
||||
langFile.Load(langReader);
|
||||
return langFile;
|
||||
try
|
||||
{
|
||||
var langFile = new XmlDocument();
|
||||
langFile.Load(langReader);
|
||||
return langFile;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogHelper.Error<ui>("Error reading umbraco language xml source (" + language + ")", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogHelper.Error<ui>("Error reading umbraco language xml source (" + language + ")", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace umbraco.editorControls
|
||||
public void Save()
|
||||
{
|
||||
if (ItemIdValue.Value.Trim() != "")
|
||||
_data.Value = ItemIdValue.Value.Trim();
|
||||
_data.Value = int.Parse(ItemIdValue.Value.Trim());
|
||||
else
|
||||
_data.Value = null;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.Xml.Linq;
|
||||
using ClientDependency.Core;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using umbraco.BusinessLogic;
|
||||
using umbraco.cms.presentation.Trees;
|
||||
using umbraco.controls.Images;
|
||||
using umbraco.controls.Tree;
|
||||
@@ -45,7 +46,15 @@ namespace umbraco.editorControls.MultiNodeTreePicker
|
||||
//need to add our tree definitions to the collection.
|
||||
|
||||
//find the content tree to duplicate
|
||||
var contentTree = TreeDefinitionCollection.Instance.Single(x => string.Equals(x.Tree.Alias, Umbraco.Core.Constants.Applications.Content, StringComparison.OrdinalIgnoreCase));
|
||||
var contentTree = TreeDefinitionCollection.Instance.SingleOrDefault(x => string.Equals(x.Tree.Alias, Umbraco.Core.Constants.Applications.Content, StringComparison.OrdinalIgnoreCase));
|
||||
//have put this here because the legacy content tree no longer exists as a tree def
|
||||
if (contentTree == null)
|
||||
{
|
||||
contentTree = new TreeDefinition(
|
||||
typeof (loadContent),
|
||||
new ApplicationTree(false, true, 0, "content", "content", "Content", ".sprTreeFolder", ".sprTreeFolder_o", "", typeof (loadContent).GetFullNameWithAssembly(), ""),
|
||||
new Application("Content", "content", "content"));
|
||||
}
|
||||
var filteredContentTree = new TreeDefinition(typeof(FilteredContentTree),
|
||||
new umbraco.BusinessLogic.ApplicationTree(true, false, 0,
|
||||
contentTree.Tree.ApplicationAlias,
|
||||
@@ -59,7 +68,15 @@ namespace umbraco.editorControls.MultiNodeTreePicker
|
||||
contentTree.App);
|
||||
|
||||
//find the media tree to duplicate
|
||||
var mediaTree = TreeDefinitionCollection.Instance.Single(x => string.Equals(x.Tree.Alias, Umbraco.Core.Constants.Applications.Media, StringComparison.OrdinalIgnoreCase));
|
||||
var mediaTree = TreeDefinitionCollection.Instance.SingleOrDefault(x => string.Equals(x.Tree.Alias, Umbraco.Core.Constants.Applications.Media, StringComparison.OrdinalIgnoreCase));
|
||||
//have put this here because the legacy content tree no longer exists as a tree def
|
||||
if (mediaTree == null)
|
||||
{
|
||||
mediaTree = new TreeDefinition(
|
||||
typeof(loadMedia),
|
||||
new ApplicationTree(false, true, 0, "media", "media", "Media", ".sprTreeFolder", ".sprTreeFolder_o", "", typeof(loadMedia).GetFullNameWithAssembly(), ""),
|
||||
new Application("Media", "media", "media"));
|
||||
}
|
||||
var filteredMediaTree = new TreeDefinition(typeof(FilteredMediaTree),
|
||||
new umbraco.BusinessLogic.ApplicationTree(true, false, 0,
|
||||
mediaTree.Tree.ApplicationAlias,
|
||||
|
||||
Reference in New Issue
Block a user