Merge remote-tracking branch 'refs/remotes/umbraco/dev-v7' into dev-v7
This commit is contained in:
@@ -11,6 +11,10 @@ namespace Umbraco.Core.Cache
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <typeparam name="TId"></typeparam>
|
||||
/// <remarks>
|
||||
/// This cache policy uses sliding expiration and caches instances for 5 minutes. However if allow zero count is true, then we use the
|
||||
/// default policy with no expiry.
|
||||
/// </remarks>
|
||||
internal class DefaultRepositoryCachePolicy<TEntity, TId> : DisposableObject, IRepositoryCachePolicy<TEntity, TId>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
@@ -54,7 +58,9 @@ namespace Umbraco.Core.Cache
|
||||
//just to be safe, we cannot cache an item without an identity
|
||||
if (entity.HasIdentity)
|
||||
{
|
||||
Cache.InsertCacheItem(GetCacheIdKey(entity.Id), () => entity);
|
||||
Cache.InsertCacheItem(GetCacheIdKey(entity.Id), () => entity,
|
||||
timeout: TimeSpan.FromMinutes(5),
|
||||
isSliding: true);
|
||||
}
|
||||
|
||||
//If there's a GetAllCacheAllowZeroCount cache, ensure it is cleared
|
||||
@@ -225,7 +231,9 @@ namespace Umbraco.Core.Cache
|
||||
//just to be safe, we cannot cache an item without an identity
|
||||
if (entity.HasIdentity)
|
||||
{
|
||||
Cache.InsertCacheItem(cacheKey, () => entity);
|
||||
Cache.InsertCacheItem(cacheKey, () => entity,
|
||||
timeout: TimeSpan.FromMinutes(5),
|
||||
isSliding: true);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -244,6 +252,7 @@ namespace Umbraco.Core.Cache
|
||||
{
|
||||
//there was nothing returned but we want to cache a zero count result so add an TEntity[] to the cache
|
||||
// to signify that there is a zero count cache
|
||||
//NOTE: Don't set expiry/sliding for a zero count
|
||||
Cache.InsertCacheItem(GetCacheTypeKey(), () => new TEntity[] {});
|
||||
}
|
||||
else
|
||||
@@ -256,7 +265,9 @@ namespace Umbraco.Core.Cache
|
||||
//just to be safe, we cannot cache an item without an identity
|
||||
if (localCopy.HasIdentity)
|
||||
{
|
||||
Cache.InsertCacheItem(GetCacheIdKey(entity.Id), () => localCopy);
|
||||
Cache.InsertCacheItem(GetCacheIdKey(entity.Id), () => localCopy,
|
||||
timeout: TimeSpan.FromMinutes(5),
|
||||
isSliding: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@ namespace Umbraco.Core.Cache
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <typeparam name="TId"></typeparam>
|
||||
/// <remarks>
|
||||
/// This caching policy has no sliding expiration but uses the default ObjectCache.InfiniteAbsoluteExpiration as it's timeout, so it
|
||||
/// should not leave the cache unless the cache memory is exceeded and it gets thrown out.
|
||||
/// </remarks>
|
||||
internal class FullDataSetRepositoryCachePolicy<TEntity, TId> : DefaultRepositoryCachePolicy<TEntity, TId>
|
||||
where TEntity : class, IAggregateRoot
|
||||
{
|
||||
|
||||
@@ -98,45 +98,10 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cache
|
||||
|
||||
// these methods are called by ContentTypeCacheRefresher and DataTypeCacheRefresher
|
||||
|
||||
internal static void ClearAll()
|
||||
{
|
||||
Logging.LogHelper.Debug<PublishedContentType>("Clear all.");
|
||||
// ok and faster to do it by types, assuming noone else caches PublishedContentType instances
|
||||
//ApplicationContext.Current.ApplicationCache.ClearStaticCacheByKeySearch("PublishedContentType_");
|
||||
ApplicationContext.Current.ApplicationCache.StaticCache.ClearCacheObjectTypes<PublishedContentType>();
|
||||
}
|
||||
|
||||
internal static void ClearContentType(int id)
|
||||
{
|
||||
Logging.LogHelper.Debug<PublishedContentType>("Clear content type w/id {0}.", () => id);
|
||||
// requires a predicate because the key does not contain the ID
|
||||
// faster than key strings comparisons anyway
|
||||
ApplicationContext.Current.ApplicationCache.StaticCache.ClearCacheObjectTypes<PublishedContentType>(
|
||||
(key, value) => value.Id == id);
|
||||
}
|
||||
|
||||
internal static void ClearDataType(int id)
|
||||
{
|
||||
Logging.LogHelper.Debug<PublishedContentType>("Clear data type w/id {0}.", () => id);
|
||||
// there is no recursion to handle here because a PublishedContentType contains *all* its
|
||||
// properties ie both its own properties and those that were inherited (it's based upon an
|
||||
// IContentTypeComposition) and so every PublishedContentType having a property based upon
|
||||
// the cleared data type, be it local or inherited, will be cleared.
|
||||
ApplicationContext.Current.ApplicationCache.StaticCache.ClearCacheObjectTypes<PublishedContentType>(
|
||||
(key, value) => value.PropertyTypes.Any(x => x.DataTypeId == id));
|
||||
}
|
||||
|
||||
|
||||
public static PublishedContentType Get(PublishedItemType itemType, string alias)
|
||||
{
|
||||
var key = string.Format("PublishedContentType_{0}_{1}",
|
||||
itemType.ToString().ToLowerInvariant(), alias.ToLowerInvariant());
|
||||
|
||||
var type = ApplicationContext.Current.ApplicationCache.StaticCache.GetCacheItem<PublishedContentType>(key,
|
||||
() => CreatePublishedContentType(itemType, alias));
|
||||
var type = CreatePublishedContentType(itemType, alias);
|
||||
|
||||
return type;
|
||||
}
|
||||
@@ -169,21 +134,8 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
return new PublishedContentType(contentType);
|
||||
}
|
||||
|
||||
// for unit tests - changing the callback must reset the cache obviously
|
||||
private static Func<string, PublishedContentType> _getPublishedContentTypeCallBack;
|
||||
internal static Func<string, PublishedContentType> GetPublishedContentTypeCallback
|
||||
{
|
||||
get { return _getPublishedContentTypeCallBack; }
|
||||
set
|
||||
{
|
||||
// see note above
|
||||
//ClearAll();
|
||||
ApplicationContext.Current.ApplicationCache.StaticCache.ClearCacheByKeySearch("PublishedContentType_");
|
||||
|
||||
_getPublishedContentTypeCallBack = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
// for unit tests
|
||||
internal static Func<string, PublishedContentType> GetPublishedContentTypeCallback { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,11 @@ namespace Umbraco.Core.Persistence.Relators
|
||||
// Is this the same DictionaryItem as the current one we're processing
|
||||
if (Current != null && Current.Id == a.Id)
|
||||
{
|
||||
// Yes, just add this User2AppDto to the current item's collection
|
||||
Current.User2AppDtos.Add(p);
|
||||
if (p.AppAlias.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
// Yes, just add this User2AppDto to the current item's collection
|
||||
Current.User2AppDtos.Add(p);
|
||||
}
|
||||
|
||||
// Return null to indicate we're not done with this User yet
|
||||
return null;
|
||||
@@ -35,7 +38,7 @@ namespace Umbraco.Core.Persistence.Relators
|
||||
Current = a;
|
||||
Current.User2AppDtos = new List<User2AppDto>();
|
||||
//this can be null since we are doing a left join
|
||||
if (p.AppAlias != null)
|
||||
if (p.AppAlias.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
Current.User2AppDtos.Add(p);
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
"DELETE FROM cmsContentXml WHERE nodeId = @Id",
|
||||
"DELETE FROM cmsContent WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoAccess WHERE nodeId = @Id",
|
||||
"DELETE FROM umbracoNode WHERE id = @Id"
|
||||
"DELETE FROM umbracoNode WHERE id = @Id"
|
||||
};
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
return moveInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the content type ids that match the query
|
||||
/// </summary>
|
||||
|
||||
@@ -475,7 +475,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (aliases.Any() == false) return base.GetAll();
|
||||
|
||||
//return from base.GetAll, this is all cached
|
||||
return base.GetAll().Where(x => aliases.Contains(x.Alias));
|
||||
return base.GetAll().Where(x => aliases.InvariantContains(x.Alias));
|
||||
}
|
||||
|
||||
public IEnumerable<ITemplate> GetChildren(int masterTemplateId)
|
||||
|
||||
@@ -910,7 +910,7 @@ namespace Umbraco.Core.Services
|
||||
new MoveEventArgs<IContent>(evtMsgs, new MoveEventInfo<IContent>(content, originalPath, Constants.System.RecycleBinContent)),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
|
||||
var moveInfo = new List<MoveEventInfo<IContent>>
|
||||
@@ -957,7 +957,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Audit(AuditType.Move, "Move Content to Recycle Bin performed by user", userId, content.Id);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1080,7 +1080,7 @@ namespace Umbraco.Core.Services
|
||||
new SaveEventArgs<IContent>(asArray, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
}
|
||||
using (new WriteLock(Locker))
|
||||
@@ -1124,7 +1124,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Audit(AuditType.Save, "Bulk Save content performed by user", userId == -1 ? 0 : userId, Constants.System.Root);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1147,7 +1147,7 @@ namespace Umbraco.Core.Services
|
||||
new DeleteEventArgs<IContent>(content, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
|
||||
//Make sure that published content is unpublished before being deleted
|
||||
@@ -1178,7 +1178,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Audit(AuditType.Delete, "Delete Content performed by user", userId, content.Id);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2043,7 +2043,7 @@ namespace Umbraco.Core.Services
|
||||
new SaveEventArgs<IContent>(content, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2075,7 +2075,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Audit(AuditType.Save, "Save Content performed by user", userId, content.Id);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,8 +44,9 @@ namespace Umbraco.Core.Services
|
||||
|
||||
#region Containers
|
||||
|
||||
public Attempt<int> CreateContentTypeContainer(int parentId, string name, int userId = 0)
|
||||
public Attempt<OperationStatus<EntityContainer, OperationStatusType>> CreateContentTypeContainer(int parentId, string name, int userId = 0)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DocumentTypeContainerGuid))
|
||||
{
|
||||
@@ -57,20 +58,32 @@ namespace Umbraco.Core.Services
|
||||
ParentId = parentId,
|
||||
CreatorId = userId
|
||||
};
|
||||
|
||||
if (SavingContentTypeContainer.IsRaisedEventCancelled(
|
||||
new SaveEventArgs<EntityContainer>(container, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(new OperationStatus<EntityContainer, OperationStatusType>(container, OperationStatusType.FailedCancelledByEvent, evtMsgs));
|
||||
}
|
||||
|
||||
repo.AddOrUpdate(container);
|
||||
uow.Commit();
|
||||
return Attempt.Succeed(container.Id);
|
||||
|
||||
SavedContentTypeContainer.RaiseEvent(new SaveEventArgs<EntityContainer>(container, evtMsgs), this);
|
||||
//TODO: Audit trail ?
|
||||
|
||||
return Attempt.Succeed(new OperationStatus<EntityContainer, OperationStatusType>(container, OperationStatusType.Success, evtMsgs));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Attempt<int>.Fail(ex);
|
||||
return Attempt.Fail(new OperationStatus<EntityContainer, OperationStatusType>(null, OperationStatusType.FailedExceptionThrown, evtMsgs), ex);
|
||||
}
|
||||
//TODO: Audit trail ?
|
||||
}
|
||||
}
|
||||
|
||||
public Attempt<int> CreateMediaTypeContainer(int parentId, string name, int userId = 0)
|
||||
public Attempt<OperationStatus<EntityContainer, OperationStatusType>> CreateMediaTypeContainer(int parentId, string name, int userId = 0)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.MediaTypeContainerGuid))
|
||||
{
|
||||
@@ -82,42 +95,83 @@ namespace Umbraco.Core.Services
|
||||
ParentId = parentId,
|
||||
CreatorId = userId
|
||||
};
|
||||
|
||||
if (SavingMediaTypeContainer.IsRaisedEventCancelled(
|
||||
new SaveEventArgs<EntityContainer>(container, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(new OperationStatus<EntityContainer, OperationStatusType>(container, OperationStatusType.FailedCancelledByEvent, evtMsgs));
|
||||
}
|
||||
|
||||
repo.AddOrUpdate(container);
|
||||
uow.Commit();
|
||||
return Attempt.Succeed(container.Id);
|
||||
|
||||
SavedMediaTypeContainer.RaiseEvent(new SaveEventArgs<EntityContainer>(container, evtMsgs), this);
|
||||
//TODO: Audit trail ?
|
||||
|
||||
return Attempt.Succeed(new OperationStatus<EntityContainer, OperationStatusType>(container, OperationStatusType.Success, evtMsgs));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Attempt<int>.Fail(ex);
|
||||
return Attempt.Fail(new OperationStatus<EntityContainer, OperationStatusType>(null, OperationStatusType.FailedExceptionThrown, evtMsgs), ex);
|
||||
}
|
||||
//TODO: Audit trail ?
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveContentTypeContainer(EntityContainer container, int userId = 0)
|
||||
public Attempt<OperationStatus> SaveContentTypeContainer(EntityContainer container, int userId = 0)
|
||||
{
|
||||
SaveContainer(container, Constants.ObjectTypes.DocumentTypeContainerGuid, "document type", userId);
|
||||
return SaveContainer(
|
||||
SavingContentTypeContainer, SavedContentTypeContainer,
|
||||
container, Constants.ObjectTypes.DocumentTypeContainerGuid, "document type", userId);
|
||||
}
|
||||
|
||||
public void SaveMediaTypeContainer(EntityContainer container, int userId = 0)
|
||||
public Attempt<OperationStatus> SaveMediaTypeContainer(EntityContainer container, int userId = 0)
|
||||
{
|
||||
SaveContainer(container, Constants.ObjectTypes.MediaTypeContainerGuid, "media type", userId);
|
||||
return SaveContainer(
|
||||
SavingMediaTypeContainer, SavedMediaTypeContainer,
|
||||
container, Constants.ObjectTypes.MediaTypeContainerGuid, "media type", userId);
|
||||
}
|
||||
|
||||
private void SaveContainer(EntityContainer container, Guid containerObjectType, string objectTypeName, int userId)
|
||||
private Attempt<OperationStatus> SaveContainer(
|
||||
TypedEventHandler<IContentTypeService, SaveEventArgs<EntityContainer>> savingEvent,
|
||||
TypedEventHandler<IContentTypeService, SaveEventArgs<EntityContainer>> savedEvent,
|
||||
EntityContainer container,
|
||||
Guid containerObjectType,
|
||||
string objectTypeName, int userId)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
if (container.ContainedObjectType != containerObjectType)
|
||||
throw new InvalidOperationException("Not a " + objectTypeName + " container.");
|
||||
{
|
||||
var ex = new InvalidOperationException("Not a " + objectTypeName + " container.");
|
||||
return OperationStatus.Exception(evtMsgs, ex);
|
||||
}
|
||||
|
||||
if (container.HasIdentity && container.IsPropertyDirty("ParentId"))
|
||||
throw new InvalidOperationException("Cannot save a container with a modified parent, move the container instead.");
|
||||
{
|
||||
var ex = new InvalidOperationException("Cannot save a container with a modified parent, move the container instead.");
|
||||
return OperationStatus.Exception(evtMsgs, ex);
|
||||
}
|
||||
|
||||
if (savingEvent.IsRaisedEventCancelled(
|
||||
new SaveEventArgs<EntityContainer>(container, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var repo = RepositoryFactory.CreateEntityContainerRepository(uow, containerObjectType))
|
||||
{
|
||||
repo.AddOrUpdate(container);
|
||||
uow.Commit();
|
||||
//TODO: Audit trail ?
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
savedEvent.RaiseEvent(new SaveEventArgs<EntityContainer>(container, evtMsgs), this);
|
||||
|
||||
//TODO: Audit trail ?
|
||||
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
|
||||
public EntityContainer GetContentTypeContainer(int containerId)
|
||||
@@ -226,28 +280,54 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteContentTypeContainer(int containerId, int userId = 0)
|
||||
public Attempt<OperationStatus> DeleteContentTypeContainer(int containerId, int userId = 0)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DocumentTypeContainerGuid))
|
||||
{
|
||||
var container = repo.Get(containerId);
|
||||
if (container == null) return;
|
||||
if (container == null) return OperationStatus.NoOperation(evtMsgs);
|
||||
|
||||
if (DeletingContentTypeContainer.IsRaisedEventCancelled(
|
||||
new DeleteEventArgs<EntityContainer>(container, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(new OperationStatus(OperationStatusType.FailedCancelledByEvent, evtMsgs));
|
||||
}
|
||||
|
||||
repo.Delete(container);
|
||||
uow.Commit();
|
||||
|
||||
DeletedContentTypeContainer.RaiseEvent(new DeleteEventArgs<EntityContainer>(container, evtMsgs), this);
|
||||
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
//TODO: Audit trail ?
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteMediaTypeContainer(int containerId, int userId = 0)
|
||||
public Attempt<OperationStatus> DeleteMediaTypeContainer(int containerId, int userId = 0)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.MediaTypeContainerGuid))
|
||||
{
|
||||
var container = repo.Get(containerId);
|
||||
if (container == null) return;
|
||||
if (container == null) return OperationStatus.NoOperation(evtMsgs);
|
||||
|
||||
if (DeletingMediaTypeContainer.IsRaisedEventCancelled(
|
||||
new DeleteEventArgs<EntityContainer>(container, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(new OperationStatus(OperationStatusType.FailedCancelledByEvent, evtMsgs));
|
||||
}
|
||||
|
||||
repo.Delete(container);
|
||||
uow.Commit();
|
||||
|
||||
DeletedMediaTypeContainer.RaiseEvent(new DeleteEventArgs<EntityContainer>(container, evtMsgs), this);
|
||||
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
//TODO: Audit trail ?
|
||||
}
|
||||
}
|
||||
@@ -1172,13 +1252,23 @@ namespace Umbraco.Core.Services
|
||||
uow.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IContentType>> DeletingContentType;
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<EntityContainer>> SavingContentTypeContainer;
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<EntityContainer>> SavedContentTypeContainer;
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<EntityContainer>> DeletingContentTypeContainer;
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<EntityContainer>> DeletedContentTypeContainer;
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<EntityContainer>> SavingMediaTypeContainer;
|
||||
public static event TypedEventHandler<IContentTypeService, SaveEventArgs<EntityContainer>> SavedMediaTypeContainer;
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<EntityContainer>> DeletingMediaTypeContainer;
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<EntityContainer>> DeletedMediaTypeContainer;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Delete
|
||||
/// </summary>
|
||||
public static event TypedEventHandler<IContentTypeService, DeleteEventArgs<IContentType>> DeletingContentType;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs after Delete
|
||||
|
||||
@@ -29,8 +29,9 @@ namespace Umbraco.Core.Services
|
||||
|
||||
#region Containers
|
||||
|
||||
public Attempt<int> CreateContainer(int parentId, string name, int userId = 0)
|
||||
public Attempt<OperationStatus<EntityContainer, OperationStatusType>> CreateContainer(int parentId, string name, int userId = 0)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DataTypeContainerGuid))
|
||||
{
|
||||
@@ -42,15 +43,26 @@ namespace Umbraco.Core.Services
|
||||
ParentId = parentId,
|
||||
CreatorId = userId
|
||||
};
|
||||
|
||||
if (SavingContainer.IsRaisedEventCancelled(
|
||||
new SaveEventArgs<EntityContainer>(container, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(new OperationStatus<EntityContainer, OperationStatusType>(container, OperationStatusType.FailedCancelledByEvent, evtMsgs));
|
||||
}
|
||||
|
||||
repo.AddOrUpdate(container);
|
||||
uow.Commit();
|
||||
return Attempt.Succeed(container.Id);
|
||||
|
||||
SavedContainer.RaiseEvent(new SaveEventArgs<EntityContainer>(container, evtMsgs), this);
|
||||
//TODO: Audit trail ?
|
||||
|
||||
return Attempt.Succeed(new OperationStatus<EntityContainer, OperationStatusType>(container, OperationStatusType.Success, evtMsgs));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Attempt<int>.Fail(ex);
|
||||
return Attempt.Fail(new OperationStatus<EntityContainer, OperationStatusType>(null, OperationStatusType.FailedExceptionThrown, evtMsgs), ex);
|
||||
}
|
||||
//TODO: Audit trail ?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,31 +119,65 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveContainer(EntityContainer container, int userId = 0)
|
||||
public Attempt<OperationStatus> SaveContainer(EntityContainer container, int userId = 0)
|
||||
{
|
||||
if (container.ContainedObjectType != Constants.ObjectTypes.DataTypeGuid)
|
||||
throw new InvalidOperationException("Not a data type container.");
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
if (container.ContainedObjectType != Constants.ObjectTypes.DataTypeGuid)
|
||||
{
|
||||
var ex = new InvalidOperationException("Not a " + Constants.ObjectTypes.DataTypeGuid + " container.");
|
||||
return OperationStatus.Exception(evtMsgs, ex);
|
||||
}
|
||||
|
||||
if (container.HasIdentity && container.IsPropertyDirty("ParentId"))
|
||||
throw new InvalidOperationException("Cannot save a container with a modified parent, move the container instead.");
|
||||
{
|
||||
var ex = new InvalidOperationException("Cannot save a container with a modified parent, move the container instead.");
|
||||
return OperationStatus.Exception(evtMsgs, ex);
|
||||
}
|
||||
|
||||
if (SavingContainer.IsRaisedEventCancelled(
|
||||
new SaveEventArgs<EntityContainer>(container, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DataTypeContainerGuid))
|
||||
{
|
||||
repo.AddOrUpdate(container);
|
||||
uow.Commit();
|
||||
//TODO: Audit trail ?
|
||||
}
|
||||
|
||||
SavedContainer.RaiseEvent(new SaveEventArgs<EntityContainer>(container, evtMsgs), this);
|
||||
|
||||
//TODO: Audit trail ?
|
||||
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
|
||||
public void DeleteContainer(int containerId, int userId = 0)
|
||||
public Attempt<OperationStatus> DeleteContainer(int containerId, int userId = 0)
|
||||
{
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var repo = RepositoryFactory.CreateEntityContainerRepository(uow, Constants.ObjectTypes.DataTypeContainerGuid))
|
||||
{
|
||||
var container = repo.Get(containerId);
|
||||
if (container == null) return;
|
||||
if (container == null) return OperationStatus.NoOperation(evtMsgs);
|
||||
|
||||
if (DeletingContainer.IsRaisedEventCancelled(
|
||||
new DeleteEventArgs<EntityContainer>(container, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(new OperationStatus(OperationStatusType.FailedCancelledByEvent, evtMsgs));
|
||||
}
|
||||
|
||||
repo.Delete(container);
|
||||
uow.Commit();
|
||||
|
||||
DeletedContainer.RaiseEvent(new DeleteEventArgs<EntityContainer>(container, evtMsgs), this);
|
||||
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
//TODO: Audit trail ?
|
||||
}
|
||||
}
|
||||
@@ -537,6 +583,12 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
public static event TypedEventHandler<IDataTypeService, SaveEventArgs<EntityContainer>> SavingContainer;
|
||||
public static event TypedEventHandler<IDataTypeService, SaveEventArgs<EntityContainer>> SavedContainer;
|
||||
public static event TypedEventHandler<IDataTypeService, DeleteEventArgs<EntityContainer>> DeletingContainer;
|
||||
public static event TypedEventHandler<IDataTypeService, DeleteEventArgs<EntityContainer>> DeletedContainer;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs before Delete
|
||||
/// </summary>
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Umbraco.Core.Services
|
||||
new DeleteEventArgs<IDomain>(domain, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
@@ -45,7 +45,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
var args = new DeleteEventArgs<IDomain>(domain, false, evtMsgs);
|
||||
Deleted.RaiseEvent(args, this);
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
|
||||
public IDomain GetByName(string name)
|
||||
@@ -91,7 +91,7 @@ namespace Umbraco.Core.Services
|
||||
new SaveEventArgs<IDomain>(domainEntity, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
@@ -102,7 +102,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
Saved.RaiseEvent(new SaveEventArgs<IDomain>(domainEntity, false, evtMsgs), this);
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
@@ -21,10 +21,11 @@ namespace Umbraco.Core.Services
|
||||
/// <returns></returns>
|
||||
Attempt<string[]> ValidateComposition(IContentTypeComposition compo);
|
||||
|
||||
Attempt<int> CreateContentTypeContainer(int parentId, string name, int userId = 0);
|
||||
Attempt<int> CreateMediaTypeContainer(int parentId, string name, int userId = 0);
|
||||
void SaveContentTypeContainer(EntityContainer container, int userId = 0);
|
||||
void SaveMediaTypeContainer(EntityContainer container, int userId = 0);
|
||||
Attempt<OperationStatus<EntityContainer, OperationStatusType>> CreateContentTypeContainer(int parentId, string name, int userId = 0);
|
||||
Attempt<OperationStatus<EntityContainer, OperationStatusType>> CreateMediaTypeContainer(int parentId, string name, int userId = 0);
|
||||
Attempt<OperationStatus> SaveContentTypeContainer(EntityContainer container, int userId = 0);
|
||||
Attempt<OperationStatus> SaveMediaTypeContainer(EntityContainer container, int userId = 0);
|
||||
|
||||
EntityContainer GetContentTypeContainer(int containerId);
|
||||
EntityContainer GetContentTypeContainer(Guid containerId);
|
||||
IEnumerable<EntityContainer> GetContentTypeContainers(int[] containerIds);
|
||||
@@ -35,8 +36,8 @@ namespace Umbraco.Core.Services
|
||||
IEnumerable<EntityContainer> GetMediaTypeContainers(int[] containerIds);
|
||||
IEnumerable<EntityContainer> GetMediaTypeContainers(string folderName, int level);
|
||||
IEnumerable<EntityContainer> GetMediaTypeContainers(IMediaType mediaType);
|
||||
void DeleteMediaTypeContainer(int folderId, int userId = 0);
|
||||
void DeleteContentTypeContainer(int containerId, int userId = 0);
|
||||
Attempt<OperationStatus> DeleteMediaTypeContainer(int folderId, int userId = 0);
|
||||
Attempt<OperationStatus> DeleteContentTypeContainer(int containerId, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all property type aliases.
|
||||
|
||||
@@ -10,14 +10,14 @@ namespace Umbraco.Core.Services
|
||||
/// </summary>
|
||||
public interface IDataTypeService : IService
|
||||
{
|
||||
Attempt<int> CreateContainer(int parentId, string name, int userId = 0);
|
||||
void SaveContainer(EntityContainer container, int userId = 0);
|
||||
Attempt<OperationStatus<EntityContainer, OperationStatusType>> CreateContainer(int parentId, string name, int userId = 0);
|
||||
Attempt<OperationStatus> SaveContainer(EntityContainer container, int userId = 0);
|
||||
EntityContainer GetContainer(int containerId);
|
||||
EntityContainer GetContainer(Guid containerId);
|
||||
IEnumerable<EntityContainer> GetContainers(string folderName, int level);
|
||||
IEnumerable<EntityContainer> GetContainers(IDataTypeDefinition dataTypeDefinition);
|
||||
IEnumerable<EntityContainer> GetContainers(int[] containerIds);
|
||||
void DeleteContainer(int containerId, int userId = 0);
|
||||
Attempt<OperationStatus> DeleteContainer(int containerId, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="IDataTypeDefinition"/> by its Name
|
||||
|
||||
@@ -747,7 +747,7 @@ namespace Umbraco.Core.Services
|
||||
if (Deleting.IsRaisedEventCancelled(
|
||||
new DeleteEventArgs<IMedia>(media, evtMsgs), this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
|
||||
//Delete children before deleting the 'possible parent'
|
||||
@@ -772,7 +772,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Audit(AuditType.Delete, "Delete Media performed by user", userId, media.Id);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -791,7 +791,7 @@ namespace Umbraco.Core.Services
|
||||
new SaveEventArgs<IMedia>(media, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -816,7 +816,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Audit(AuditType.Save, "Save Media performed by user", userId, media.Id);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -836,7 +836,7 @@ namespace Umbraco.Core.Services
|
||||
new SaveEventArgs<IMedia>(asArray, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -864,7 +864,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Audit(AuditType.Save, "Save Media items performed by user", userId, -1);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -966,7 +966,7 @@ namespace Umbraco.Core.Services
|
||||
if (Trashing.IsRaisedEventCancelled(
|
||||
new MoveEventArgs<IMedia>(new MoveEventInfo<IMedia>(media, originalPath, Constants.System.RecycleBinMedia)), this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
|
||||
var moveInfo = new List<MoveEventInfo<IMedia>>
|
||||
@@ -1008,7 +1008,7 @@ namespace Umbraco.Core.Services
|
||||
|
||||
Audit(AuditType.Move, "Move Media to Recycle Bin performed by user", userId, media.Id);
|
||||
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -45,14 +45,25 @@ namespace Umbraco.Core.Services
|
||||
|
||||
#region Static Helper methods
|
||||
|
||||
internal static OperationStatus Cancelled(EventMessages eventMessages)
|
||||
internal static Attempt<OperationStatus> Exception(EventMessages eventMessages, Exception ex)
|
||||
{
|
||||
return new OperationStatus(OperationStatusType.FailedCancelledByEvent, eventMessages);
|
||||
eventMessages.Add(new EventMessage("", ex.Message, EventMessageType.Error));
|
||||
return Attempt.Fail(new OperationStatus(OperationStatusType.FailedExceptionThrown, eventMessages), ex);
|
||||
}
|
||||
|
||||
internal static OperationStatus Success(EventMessages eventMessages)
|
||||
internal static Attempt<OperationStatus> Cancelled(EventMessages eventMessages)
|
||||
{
|
||||
return new OperationStatus(OperationStatusType.Success, eventMessages);
|
||||
return Attempt.Fail(new OperationStatus(OperationStatusType.FailedCancelledByEvent, eventMessages));
|
||||
}
|
||||
|
||||
internal static Attempt<OperationStatus> Success(EventMessages eventMessages)
|
||||
{
|
||||
return Attempt.Succeed(new OperationStatus(OperationStatusType.Success, eventMessages));
|
||||
}
|
||||
|
||||
internal static Attempt<OperationStatus> NoOperation(EventMessages eventMessages)
|
||||
{
|
||||
return Attempt.Succeed(new OperationStatus(OperationStatusType.NoOperation, eventMessages));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -12,11 +12,21 @@ namespace Umbraco.Core.Services
|
||||
/// The saving was successful.
|
||||
/// </summary>
|
||||
Success = 0,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The saving has been cancelled by a 3rd party add-in
|
||||
/// </summary>
|
||||
FailedCancelledByEvent = 14
|
||||
FailedCancelledByEvent = 14,
|
||||
|
||||
/// <summary>
|
||||
/// Failed, an exception was thrown/handled
|
||||
/// </summary>
|
||||
FailedExceptionThrown = 15,
|
||||
|
||||
/// <summary>
|
||||
/// When no operation is executed because it was not needed (i.e. deleting an item that doesn't exist)
|
||||
/// </summary>
|
||||
NoOperation = 100,
|
||||
|
||||
//TODO: In the future, we might need to add more operations statuses, potentially like 'FailedByPermissions', etc...
|
||||
}
|
||||
|
||||
@@ -480,7 +480,7 @@ namespace Umbraco.Core.Services
|
||||
_logger.Error<PackagingService>("Could not create folder: " + rootFolder, tryCreateFolder.Exception);
|
||||
throw tryCreateFolder.Exception;
|
||||
}
|
||||
var rootFolderId = tryCreateFolder.Result;
|
||||
var rootFolderId = tryCreateFolder.Result.Entity.Id;
|
||||
current = _contentTypeService.GetContentTypeContainer(rootFolderId);
|
||||
}
|
||||
|
||||
@@ -514,7 +514,7 @@ namespace Umbraco.Core.Services
|
||||
_logger.Error<PackagingService>("Could not create folder: " + folderName, tryCreateFolder.Exception);
|
||||
throw tryCreateFolder.Exception;
|
||||
}
|
||||
return _contentTypeService.GetContentTypeContainer(tryCreateFolder.Result);
|
||||
return _contentTypeService.GetContentTypeContainer(tryCreateFolder.Result.Entity.Id);
|
||||
}
|
||||
|
||||
private IContentType CreateContentTypeFromXml(XElement documentType)
|
||||
@@ -982,7 +982,7 @@ namespace Umbraco.Core.Services
|
||||
_logger.Error<PackagingService>("Could not create folder: " + rootFolder, tryCreateFolder.Exception);
|
||||
throw tryCreateFolder.Exception;
|
||||
}
|
||||
current = _dataTypeService.GetContainer(tryCreateFolder.Result);
|
||||
current = _dataTypeService.GetContainer(tryCreateFolder.Result.Entity.Id);
|
||||
}
|
||||
|
||||
importedFolders.Add(name, current.Id);
|
||||
@@ -1015,7 +1015,7 @@ namespace Umbraco.Core.Services
|
||||
_logger.Error<PackagingService>("Could not create folder: " + folderName, tryCreateFolder.Exception);
|
||||
throw tryCreateFolder.Exception;
|
||||
}
|
||||
return _dataTypeService.GetContainer(tryCreateFolder.Result);
|
||||
return _dataTypeService.GetContainer(tryCreateFolder.Result.Entity.Id);
|
||||
}
|
||||
|
||||
private void SavePrevaluesFromXml(List<IDataTypeDefinition> dataTypes, IEnumerable<XElement> dataTypeElements)
|
||||
|
||||
@@ -183,7 +183,7 @@ namespace Umbraco.Core.Services
|
||||
new SaveEventArgs<PublicAccessEntry>(entry, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
|
||||
repo.AddOrUpdate(entry);
|
||||
@@ -191,7 +191,7 @@ namespace Umbraco.Core.Services
|
||||
uow.Commit();
|
||||
|
||||
Saved.RaiseEvent(new SaveEventArgs<PublicAccessEntry>(entry, false, evtMsgs), this);
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -207,7 +207,7 @@ namespace Umbraco.Core.Services
|
||||
new SaveEventArgs<PublicAccessEntry>(entry, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
@@ -218,7 +218,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
Saved.RaiseEvent(new SaveEventArgs<PublicAccessEntry>(entry, false, evtMsgs), this);
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -232,7 +232,7 @@ namespace Umbraco.Core.Services
|
||||
new DeleteEventArgs<PublicAccessEntry>(entry, evtMsgs),
|
||||
this))
|
||||
{
|
||||
return Attempt.Fail(OperationStatus.Cancelled(evtMsgs));
|
||||
return OperationStatus.Cancelled(evtMsgs);
|
||||
}
|
||||
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
@@ -243,7 +243,7 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
Deleted.RaiseEvent(new DeleteEventArgs<PublicAccessEntry>(entry, false, evtMsgs), this);
|
||||
return Attempt.Succeed(OperationStatus.Success(evtMsgs));
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.AreEqual(@"@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
|
||||
@{
|
||||
" + "\t" + @"Layout = null;
|
||||
}", template.Content);
|
||||
}".Lf(), template.Content.Lf());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -209,7 +209,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.AreEqual(@"@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
|
||||
@{
|
||||
" + "\t" + @"Layout = ""test.cshtml"";
|
||||
}", template2.Content);
|
||||
}".Lf(), template2.Content.Lf());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function SelectWhen($timeout) {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
attr.$observe("umbSelectWhen", function(newValue) {
|
||||
if (newValue === "true") {
|
||||
$timeout(function() {
|
||||
el.select();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'A',
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbSelectWhen', SelectWhen);
|
||||
|
||||
})();
|
||||
@@ -24,12 +24,10 @@
|
||||
// scope object, but that would mean we'd have to watch that value too in order to set the outer
|
||||
// ngModelCtrl.$modelValue. It's seems like less overhead to just do this and not have 2x watches.
|
||||
scope.lockedFieldForm.lockedField.$modelValue = undefined;
|
||||
scope.lockedFieldForm.lockedField.$setViewValue(newValue);
|
||||
scope.lockedFieldForm.lockedField.$render();
|
||||
scope.lockedFieldForm.lockedField.$render();
|
||||
}
|
||||
scope.lockedFieldForm.lockedField.$setViewValue(scope.lockedFieldForm.lockedField.$modelValue);
|
||||
});
|
||||
|
||||
var input = el.find('.umb-locked-field__input');
|
||||
|
||||
function activate() {
|
||||
|
||||
@@ -57,36 +55,14 @@
|
||||
|
||||
scope.lock = function() {
|
||||
scope.locked = true;
|
||||
input.unbind("blur");
|
||||
};
|
||||
|
||||
scope.unlock = function() {
|
||||
scope.locked = false;
|
||||
autoFocusField();
|
||||
};
|
||||
|
||||
function autoFocusField() {
|
||||
|
||||
var onBlurHandler = function() {
|
||||
scope.$apply(function(){
|
||||
scope.lock();
|
||||
});
|
||||
};
|
||||
|
||||
$timeout(function() {
|
||||
input.focus();
|
||||
input.select();
|
||||
input.on("blur", onBlurHandler);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
activate();
|
||||
|
||||
scope.$on('$destroy', function() {
|
||||
input.unbind('blur');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
var directive = {
|
||||
|
||||
@@ -1,167 +1,194 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
'use strict';
|
||||
|
||||
function MediaGridDirective($filter, mediaHelper) {
|
||||
function MediaGridDirective($filter, mediaHelper) {
|
||||
|
||||
function link(scope, el, attr, ctrl) {
|
||||
function link(scope, el, attr, ctrl) {
|
||||
|
||||
var itemDefaultHeight = 200;
|
||||
var itemDefaultWidth = 200;
|
||||
var itemMaxWidth = 200;
|
||||
var itemMaxHeight = 200;
|
||||
var itemDefaultHeight = 200;
|
||||
var itemDefaultWidth = 200;
|
||||
var itemMaxWidth = 200;
|
||||
var itemMaxHeight = 200;
|
||||
var itemMinWidth = 125;
|
||||
var itemMinHeight = 125;
|
||||
|
||||
function activate() {
|
||||
function activate() {
|
||||
|
||||
for (var i = 0; scope.items.length > i; i++) {
|
||||
var item = scope.items[i];
|
||||
setItemData(item);
|
||||
setOriginalSize(item, itemMaxHeight);
|
||||
}
|
||||
if (scope.itemMaxWidth) {
|
||||
itemMaxWidth = scope.itemMaxWidth;
|
||||
}
|
||||
|
||||
if(scope.items.length > 0) {
|
||||
setFlexValues(scope.items);
|
||||
}
|
||||
if (scope.itemMaxHeight) {
|
||||
itemMaxHeight = scope.itemMaxHeight;
|
||||
}
|
||||
|
||||
}
|
||||
if (scope.itemMinWidth) {
|
||||
itemMinWidth = scope.itemMinWidth;
|
||||
}
|
||||
|
||||
function setItemData(item) {
|
||||
item.isFolder = !mediaHelper.hasFilePropertyType(item);
|
||||
if(!item.isFolder){
|
||||
item.thumbnail = mediaHelper.resolveFile(item, true);
|
||||
item.image = mediaHelper.resolveFile(item, false);
|
||||
}
|
||||
}
|
||||
if (scope.itemMinWidth) {
|
||||
itemMinHeight = scope.itemMinHeight;
|
||||
}
|
||||
|
||||
function setOriginalSize(item, maxHeight) {
|
||||
for (var i = 0; scope.items.length > i; i++) {
|
||||
var item = scope.items[i];
|
||||
setItemData(item);
|
||||
setOriginalSize(item, itemMaxHeight);
|
||||
}
|
||||
|
||||
//set to a square by default
|
||||
item.width = itemDefaultWidth;
|
||||
item.height = itemDefaultHeight;
|
||||
item.aspectRatio = 1;
|
||||
|
||||
var widthProp = _.find(item.properties, function(v) { return (v.alias === "umbracoWidth"); });
|
||||
|
||||
if (widthProp && widthProp.value) {
|
||||
item.width = parseInt(widthProp.value, 10);
|
||||
if (isNaN(item.width)) {
|
||||
item.width = itemDefaultWidth;
|
||||
}
|
||||
}
|
||||
|
||||
var heightProp = _.find(item.properties, function(v) { return (v.alias === "umbracoHeight"); });
|
||||
|
||||
if (heightProp && heightProp.value) {
|
||||
item.height = parseInt(heightProp.value, 10);
|
||||
if (isNaN(item.height)) {
|
||||
item.height = itemDefaultWidth;
|
||||
}
|
||||
}
|
||||
|
||||
item.aspectRatio = item.width / item.height;
|
||||
|
||||
// set max width and height
|
||||
// landscape
|
||||
if(item.aspectRatio >= 1) {
|
||||
if(item.width > itemMaxWidth) {
|
||||
item.width = itemMaxWidth;
|
||||
item.height = itemMaxWidth / item.aspectRatio;
|
||||
}
|
||||
// portrait
|
||||
} else {
|
||||
if(item.height > itemMaxHeight) {
|
||||
item.height = itemMaxHeight;
|
||||
item.width = itemMaxHeight * item.aspectRatio;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function setFlexValues(mediaItems) {
|
||||
|
||||
var flexSortArray = mediaItems;
|
||||
var smallestImageWidth = null;
|
||||
var widestImageAspectRatio = null;
|
||||
|
||||
// sort array after image width with the widest image first
|
||||
flexSortArray = $filter('orderBy')(flexSortArray, 'width', true);
|
||||
|
||||
// find widest image aspect ratio
|
||||
widestImageAspectRatio = flexSortArray[0].aspectRatio;
|
||||
|
||||
// find smallest image width
|
||||
smallestImageWidth = flexSortArray[flexSortArray.length - 1].width;
|
||||
|
||||
for (var i = 0; flexSortArray.length > i; i++) {
|
||||
|
||||
var mediaItem = flexSortArray[i];
|
||||
var flex = 1 / (widestImageAspectRatio / mediaItem.aspectRatio);
|
||||
|
||||
if (flex === 0) {
|
||||
flex = 1;
|
||||
}
|
||||
|
||||
var imageMinWidth = smallestImageWidth * flex;
|
||||
|
||||
var flexStyle = {
|
||||
"flex": flex + " 1 " + imageMinWidth + "px",
|
||||
"max-width": mediaItem.width + "px",
|
||||
"min-width": "125px"
|
||||
};
|
||||
|
||||
mediaItem.flexStyle = flexStyle;
|
||||
if (scope.items.length > 0) {
|
||||
setFlexValues(scope.items);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
scope.clickItem = function(item, $event, $index) {
|
||||
if(scope.onClick) {
|
||||
scope.onClick(item, $event, $index);
|
||||
function setItemData(item) {
|
||||
item.isFolder = !mediaHelper.hasFilePropertyType(item);
|
||||
if (!item.isFolder) {
|
||||
item.thumbnail = mediaHelper.resolveFile(item, true);
|
||||
item.image = mediaHelper.resolveFile(item, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
scope.clickItemName = function(item, $event, $index) {
|
||||
if(scope.onClickName) {
|
||||
scope.onClickName(item, $event, $index);
|
||||
$event.stopPropagation();
|
||||
function setOriginalSize(item, maxHeight) {
|
||||
|
||||
//set to a square by default
|
||||
item.width = itemDefaultWidth;
|
||||
item.height = itemDefaultHeight;
|
||||
item.aspectRatio = 1;
|
||||
|
||||
var widthProp = _.find(item.properties, function(v) {
|
||||
return (v.alias === "umbracoWidth");
|
||||
});
|
||||
|
||||
if (widthProp && widthProp.value) {
|
||||
item.width = parseInt(widthProp.value, 10);
|
||||
if (isNaN(item.width)) {
|
||||
item.width = itemDefaultWidth;
|
||||
}
|
||||
}
|
||||
|
||||
var heightProp = _.find(item.properties, function(v) {
|
||||
return (v.alias === "umbracoHeight");
|
||||
});
|
||||
|
||||
if (heightProp && heightProp.value) {
|
||||
item.height = parseInt(heightProp.value, 10);
|
||||
if (isNaN(item.height)) {
|
||||
item.height = itemDefaultWidth;
|
||||
}
|
||||
}
|
||||
|
||||
item.aspectRatio = item.width / item.height;
|
||||
|
||||
// set max width and height
|
||||
// landscape
|
||||
if (item.aspectRatio >= 1) {
|
||||
if (item.width > itemMaxWidth) {
|
||||
item.width = itemMaxWidth;
|
||||
item.height = itemMaxWidth / item.aspectRatio;
|
||||
}
|
||||
// portrait
|
||||
} else {
|
||||
if (item.height > itemMaxHeight) {
|
||||
item.height = itemMaxHeight;
|
||||
item.width = itemMaxHeight * item.aspectRatio;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
scope.hoverItemDetails = function(item, $event, hover) {
|
||||
if(scope.onDetailsHover) {
|
||||
scope.onDetailsHover(item, $event, hover);
|
||||
function setFlexValues(mediaItems) {
|
||||
|
||||
var flexSortArray = mediaItems;
|
||||
var smallestImageWidth = null;
|
||||
var widestImageAspectRatio = null;
|
||||
|
||||
// sort array after image width with the widest image first
|
||||
flexSortArray = $filter('orderBy')(flexSortArray, 'width', true);
|
||||
|
||||
// find widest image aspect ratio
|
||||
widestImageAspectRatio = flexSortArray[0].aspectRatio;
|
||||
|
||||
// find smallest image width
|
||||
smallestImageWidth = flexSortArray[flexSortArray.length - 1].width;
|
||||
|
||||
for (var i = 0; flexSortArray.length > i; i++) {
|
||||
|
||||
var mediaItem = flexSortArray[i];
|
||||
var flex = 1 / (widestImageAspectRatio / mediaItem.aspectRatio);
|
||||
|
||||
if (flex === 0) {
|
||||
flex = 1;
|
||||
}
|
||||
|
||||
var imageMinFlexWidth = smallestImageWidth * flex;
|
||||
|
||||
var flexStyle = {
|
||||
"flex": flex + " 1 " + imageMinFlexWidth + "px",
|
||||
"max-width": mediaItem.width + "px",
|
||||
"min-width": itemMinWidth + "px",
|
||||
"min-height": itemMinHeight + "px"
|
||||
};
|
||||
|
||||
mediaItem.flexStyle = flexStyle;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
var unbindItemsWatcher = scope.$watch('items', function(newValue, oldValue){
|
||||
if(angular.isArray(newValue)) {
|
||||
activate();
|
||||
}
|
||||
});
|
||||
scope.clickItem = function(item, $event, $index) {
|
||||
if (scope.onClick) {
|
||||
scope.onClick(item, $event, $index);
|
||||
}
|
||||
};
|
||||
|
||||
scope.$on('$destroy', function(){
|
||||
unbindItemsWatcher();
|
||||
});
|
||||
scope.clickItemName = function(item, $event, $index) {
|
||||
if (scope.onClickName) {
|
||||
scope.onClickName(item, $event, $index);
|
||||
$event.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
scope.hoverItemDetails = function(item, $event, hover) {
|
||||
if (scope.onDetailsHover) {
|
||||
scope.onDetailsHover(item, $event, hover);
|
||||
}
|
||||
};
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/umb-media-grid.html',
|
||||
scope: {
|
||||
items: '=',
|
||||
onDetailsHover: "=",
|
||||
onClick: '=',
|
||||
onClickName: "=",
|
||||
filterBy: "="
|
||||
},
|
||||
link: link
|
||||
};
|
||||
var unbindItemsWatcher = scope.$watch('items', function(newValue, oldValue) {
|
||||
if (angular.isArray(newValue)) {
|
||||
activate();
|
||||
}
|
||||
});
|
||||
|
||||
return directive;
|
||||
}
|
||||
scope.$on('$destroy', function() {
|
||||
unbindItemsWatcher();
|
||||
});
|
||||
|
||||
angular.module('umbraco.directives').directive('umbMediaGrid', MediaGridDirective);
|
||||
}
|
||||
|
||||
var directive = {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/components/umb-media-grid.html',
|
||||
scope: {
|
||||
items: '=',
|
||||
onDetailsHover: "=",
|
||||
onClick: '=',
|
||||
onClickName: "=",
|
||||
filterBy: "=",
|
||||
itemMaxWidth: "@",
|
||||
itemMaxHeight: "@",
|
||||
itemMinWidth: "@",
|
||||
itemMinHeight: "@"
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbMediaGrid', MediaGridDirective);
|
||||
|
||||
})();
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
.umb-card-icons{
|
||||
text-align: center;
|
||||
vertical-align: center;
|
||||
vertical-align: middle;
|
||||
display: block;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
|
||||
@@ -27,7 +27,7 @@ label.control-label {
|
||||
}
|
||||
|
||||
|
||||
.controls-row label{padding: 0 10px 0 10px; vertical-align: center}
|
||||
.controls-row label{padding: 0 10px 0 10px; vertical-align: middle;}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ body {
|
||||
line-height: @baseLineHeight;
|
||||
color: @textColor;
|
||||
|
||||
vertical-align: center;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +140,10 @@ h5.-black {
|
||||
|
||||
/* LABELS*/
|
||||
.umb-control-group label.control-label {
|
||||
text-align: left
|
||||
text-align: left;
|
||||
}
|
||||
.umb-control-group label.control-label > div > label {
|
||||
padding-left: 0;
|
||||
}
|
||||
.umb-control-group label .help-block,
|
||||
.umb-control-group label small {
|
||||
@@ -150,7 +153,7 @@ h5.-black {
|
||||
padding-top: 5px;
|
||||
}
|
||||
.umb-nolabel .controls {
|
||||
margin-left: 0px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.controls-row {
|
||||
@@ -159,11 +162,15 @@ h5.-black {
|
||||
}
|
||||
|
||||
.umb-user-panel .controls-row {
|
||||
margin-left: 0px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.controls-row label {
|
||||
display: inline-block
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.controls-row > div > label {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.block-form .controls-row {
|
||||
@@ -171,10 +178,24 @@ h5.-black {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.hidelabel > div > .controls-row, .hidelabel > .controls-row, .hidelabel .controls {
|
||||
padding: 0px;
|
||||
.hidelabel > div > .controls-row, .hidelabel > .controls-row, .hidelabel > div > .controls {
|
||||
padding: 0;
|
||||
border: none;
|
||||
margin: 0px !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.controls-row > .vertical-align-items {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.controls-row > .vertical-align-items > input.umb-editor-tiny {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.controls-row > .vertical-align-items > input.umb-editor-tiny:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.thumbnails .selected {
|
||||
|
||||
@@ -76,7 +76,11 @@
|
||||
items="images"
|
||||
filter-by="searchTerm"
|
||||
on-click="clickHandler"
|
||||
on-click-name="clickItemName">
|
||||
on-click-name="clickItemName"
|
||||
item-max-width="150"
|
||||
item-max-height="150"
|
||||
item-min-width="100"
|
||||
item-min-height="100">
|
||||
</umb-media-grid>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,10 @@
|
||||
umb-auto-resize
|
||||
required
|
||||
val-server-field="{{serverValidationField}}"
|
||||
title="{{ngModel}}" />
|
||||
title="{{ngModel}}"
|
||||
focus-when="{{!locked}}"
|
||||
umb-select-when="{{!locked}}"
|
||||
on-blur="lock()" />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
<div class="umb-media-grid">
|
||||
<div class="umb-media-grid__item" ng-click="clickItem(item, $event, $index)" ng-repeat="item in items | filter:filterBy" ng-style="item.flexStyle" ng-class="{'-selected': item.selected, '-file': !item.thumbnail}">
|
||||
<div>
|
||||
|
||||
<div class="umb-media-grid__item" ng-click="clickItem(item, $event, $index)" ng-repeat="item in items | filter:filterBy" ng-style="item.flexStyle" ng-class="{'-selected': item.selected, '-file': !item.thumbnail}">
|
||||
<i ng-show="item.selected" class="icon-check umb-media-grid__checkmark"></i>
|
||||
|
||||
<i ng-show="item.selected" class="icon-check umb-media-grid__checkmark"></i>
|
||||
<div class="umb-media-grid__item-overlay" ng-class="{'-locked': item.selected}" ng-click="clickItemName(item, $event, $index)">
|
||||
<i ng-if="onDetailsHover" class="icon-info umb-media-grid__info" ng-mouseover="hoverItemDetails(item, $event, true)" ng-mouseleave="hoverItemDetails(item, $event, false)"></i>
|
||||
<div class="umb-media-grid__item-name">{{item.name}}</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-media-grid__item-overlay" ng-class="{'-locked': item.selected}" ng-click="clickItemName(item, $event, $index)">
|
||||
<i ng-if="onDetailsHover" class="icon-info umb-media-grid__info" ng-mouseover="hoverItemDetails(item, $event, true)" ng-mouseleave="hoverItemDetails(item, $event, false)"></i>
|
||||
<div class="umb-media-grid__item-name">{{item.name}}</div>
|
||||
</div>
|
||||
<div class="umb-media-grid__image-background" ng-if="item.thumbnail"></div>
|
||||
<img class="umb-media-grid__item-image" width="{{item.width}}" height="{{item.height}}" ng-if="item.thumbnail" ng-src="{{item.thumbnail}}" alt="{{item.name}}" draggable="false"/>
|
||||
<img class="umb-media-grid__item-image-placeholder" ng-if="!item.thumbnail" src="assets/img/transparent.png" alt="{{item.name}}" draggable="false"/>
|
||||
|
||||
<div class="umb-media-grid__image-background" ng-if="item.thumbnail"></div>
|
||||
<img class="umb-media-grid__item-image" width="{{item.width}}" height="{{item.height}}" ng-if="item.thumbnail" ng-src="{{item.thumbnail}}" alt="{{item.name}}" draggable="false" />
|
||||
<img class="umb-media-grid__item-image-placeholder" ng-if="!item.thumbnail" src="assets/img/transparent.png" alt="{{item.name}}" draggable="false" />
|
||||
|
||||
<i class="umb-media-grid__item-icon {{ item.icon }}" ng-if="!item.thumbnail"></i>
|
||||
|
||||
</div>
|
||||
<i class="umb-media-grid__item-icon {{ item.icon }}" ng-if="!item.thumbnail"></i>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
ng-if="entityType !== 'media'">
|
||||
|
||||
<umb-content-grid
|
||||
ng-if="items || !items && !options.filter"
|
||||
ng-if="items"
|
||||
content="items"
|
||||
content-properties="options.includeProperties"
|
||||
on-click="vm.selectContentItem"
|
||||
@@ -12,9 +12,15 @@
|
||||
</umb-content-grid>
|
||||
|
||||
<umb-empty-state
|
||||
ng-if="!items && options.filter"
|
||||
ng-if="!items && options.filter.length > 0"
|
||||
position="center">
|
||||
Sorry, we can not find what you are looking for
|
||||
<localize key="general_searchNoResult"></localize>
|
||||
</umb-empty-state>
|
||||
|
||||
<umb-empty-state
|
||||
ng-if="!items && vm.isRecycleBin"
|
||||
position="center">
|
||||
<localize key="general_recycleBinEmpty"></localize>
|
||||
</umb-empty-state>
|
||||
|
||||
</div>
|
||||
@@ -31,7 +37,7 @@
|
||||
files-uploaded="vm.onUploadComplete"
|
||||
accept="{{vm.acceptedFileTypes}}"
|
||||
max-file-size="{{vm.maxFileSize}}"
|
||||
hide-dropzone="{{!vm.activeDrag && items.length > 0 || !items && options.filter }}"
|
||||
hide-dropzone="{{ options.filter.length > 0 }}"
|
||||
compact="{{ items.length > 0 }}"
|
||||
files-queued="vm.onFilesQueue">
|
||||
</umb-file-dropzone>
|
||||
@@ -68,9 +74,9 @@
|
||||
</umb-empty-state>
|
||||
|
||||
<umb-empty-state
|
||||
ng-if="vm.itemsWithoutFolders.length === 0 && options.filter"
|
||||
ng-if="vm.itemsWithoutFolders.length === 0 && options.filter.length > 0"
|
||||
position="center">
|
||||
Sorry, we can not find what you are looking for
|
||||
<localize key="general_searchNoResult"></localize>
|
||||
</umb-empty-state>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
vm.activeDrag = false;
|
||||
vm.mediaDetailsTooltip = {};
|
||||
vm.itemsWithoutFolders = [];
|
||||
vm.isRecycleBin = $scope.contentId === '-21';
|
||||
vm.isRecycleBin = $scope.contentId === '-21' || $scope.contentId === '-20';
|
||||
|
||||
vm.dragEnter = dragEnter;
|
||||
vm.dragLeave = dragLeave;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
files-uploaded="vm.onUploadComplete"
|
||||
accept="{{vm.acceptedFileTypes}}"
|
||||
max-file-size="{{vm.maxFileSize}}"
|
||||
hide-dropzone="{{!vm.activeDrag && items.length > 0 || !items && options.filter }}"
|
||||
hide-dropzone="{{options.filter.length > 0}}"
|
||||
compact="{{ items.length > 0 }}"
|
||||
files-queued="vm.onFilesQueue">
|
||||
</umb-file-dropzone>
|
||||
@@ -31,18 +31,12 @@
|
||||
on-sort="vm.sort">
|
||||
</umb-table>
|
||||
|
||||
<umb-empty-state
|
||||
ng-if="!items && vm.isRecycleBin"
|
||||
position="center">
|
||||
<localize key="general_recycleBinEmpty"></localize>
|
||||
</umb-empty-state>
|
||||
|
||||
</div>
|
||||
|
||||
<div ng-if="entityType !== 'media'">
|
||||
|
||||
<umb-table
|
||||
ng-if="items || !items && !options.filter"
|
||||
ng-if="items"
|
||||
items="items"
|
||||
item-properties="options.includeProperties"
|
||||
on-select="vm.selectItem"
|
||||
@@ -56,9 +50,15 @@
|
||||
</div>
|
||||
|
||||
<umb-empty-state
|
||||
ng-if="!items && options.filter"
|
||||
ng-if="!items && options.filter.length > 0"
|
||||
position="center">
|
||||
Sorry, we can not find what you are looking for
|
||||
<localize key="general_searchNoResult"></localize>
|
||||
</umb-empty-state>
|
||||
|
||||
<umb-empty-state
|
||||
ng-if="!items && vm.isRecycleBin"
|
||||
position="center">
|
||||
<localize key="general_recycleBinEmpty"></localize>
|
||||
</umb-empty-state>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes);
|
||||
vm.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB";
|
||||
vm.activeDrag = false;
|
||||
vm.isRecycleBin = $scope.contentId === '-21';
|
||||
vm.isRecycleBin = $scope.contentId === '-21' || $scope.contentId === '-20';
|
||||
|
||||
vm.selectItem = selectItem;
|
||||
vm.clickItem = clickItem;
|
||||
|
||||
@@ -2,35 +2,41 @@
|
||||
|
||||
<umb-control-group label="Toolbar" hide-label="false">
|
||||
<div ng-repeat="cmd in tinyMceConfig.commands">
|
||||
<input type="checkbox"
|
||||
ng-checked="selected(cmd, cmd.frontEndCommand, model.value.toolbar)"
|
||||
ng-model="cmd.selected"
|
||||
ng-change="selectCommand(cmd)"
|
||||
/>
|
||||
<label>
|
||||
<input type="checkbox"
|
||||
ng-checked="selected(cmd, cmd.frontEndCommand, model.value.toolbar)"
|
||||
ng-model="cmd.selected"
|
||||
ng-change="selectCommand(cmd)" />
|
||||
|
||||
<img ng-src="{{cmd.icon}}" />
|
||||
|
||||
{{cmd.frontEndCommand}}
|
||||
</label>
|
||||
</div>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="Stylesheets" hide-label="0">
|
||||
<div ng-repeat="css in stylesheets">
|
||||
<input type="checkbox"
|
||||
ng-checked="selected(css, css.name, model.value.stylesheets)"
|
||||
ng-model="css.selected"
|
||||
ng-change="selectStylesheet(css)"
|
||||
/>
|
||||
{{css.name}}
|
||||
<label>
|
||||
<input type="checkbox"
|
||||
ng-checked="selected(css, css.name, model.value.stylesheets)"
|
||||
ng-model="css.selected"
|
||||
ng-change="selectStylesheet(css)" />
|
||||
{{css.name}}
|
||||
</label>
|
||||
</div>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="Dimensions" description="Width x Height">
|
||||
<input type="number" ng-model="model.value.dimensions.width" class="umb-editor-tiny" placeholder="Width" /> ×
|
||||
<input type="number" ng-model="model.value.dimensions.height" class="umb-editor-tiny" placeholder="Height" /> Pixels
|
||||
<div class="vertical-align-items">
|
||||
<input type="number" min="0" ng-model="model.value.dimensions.width" class="umb-editor-tiny" placeholder="Width" /> ×
|
||||
<input type="number" min="0" ng-model="model.value.dimensions.height" class="umb-editor-tiny" placeholder="Height" /> Pixels
|
||||
</div>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="Maximum size for inserted images" description="0 to disable resizing">
|
||||
<input type="number" ng-model="model.value.maxImageSize" class="umb-editor-tiny" placeholder="Width/Height" /> Pixels
|
||||
<div class="vertical-align-items">
|
||||
<input type="number" min="0" ng-model="model.value.maxImageSize" class="umb-editor-tiny" placeholder="Width/Height" /> Pixels
|
||||
</div>
|
||||
</umb-control-group>
|
||||
</div>
|
||||
@@ -448,6 +448,7 @@
|
||||
<key alias="retry">Retry</key>
|
||||
<key alias="rights">Permissions</key>
|
||||
<key alias="search">Search</key>
|
||||
<key alias="searchNoResult">Sorry, we can not find what you are looking for</key>
|
||||
<key alias="server">Server</key>
|
||||
<key alias="show">Show</key>
|
||||
<key alias="showPageOnSend">Show page on Send</key>
|
||||
|
||||
@@ -141,9 +141,7 @@ namespace Umbraco.Web.Cache
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.ContentTypeCacheKey);
|
||||
//clear static object cache
|
||||
global::umbraco.cms.businesslogic.ContentType.RemoveAllDataTypeCache();
|
||||
|
||||
PublishedContentType.ClearAll();
|
||||
|
||||
|
||||
base.RefreshAll();
|
||||
}
|
||||
|
||||
@@ -280,9 +278,7 @@ namespace Umbraco.Web.Cache
|
||||
|
||||
//clears the dictionary object cache of the legacy ContentType
|
||||
global::umbraco.cms.businesslogic.ContentType.RemoveFromDataTypeCache(payload.Alias);
|
||||
|
||||
PublishedContentType.ClearContentType(payload.Id);
|
||||
|
||||
|
||||
//need to recursively clear the cache for each child content type
|
||||
foreach (var descendant in payload.DescendantPayloads)
|
||||
{
|
||||
|
||||
@@ -108,7 +108,6 @@ namespace Umbraco.Web.Cache
|
||||
if (dataTypeCache)
|
||||
dataTypeCache.Result.ClearCacheByKeySearch(string.Format("{0}{1}", CacheKeys.DataTypePreValuesCacheKey, payload.Id));
|
||||
|
||||
PublishedContentType.ClearDataType(payload.Id);
|
||||
});
|
||||
|
||||
base.Refresh(jsonPayload);
|
||||
|
||||
@@ -81,7 +81,8 @@ namespace Umbraco.Web.Editors
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[EnsureUserPermissionForContent("id")]
|
||||
[OutgoingEditorModelEvent]
|
||||
[EnsureUserPermissionForContent("id")]
|
||||
public ContentItemDisplay GetById(int id)
|
||||
{
|
||||
var foundContent = GetObjectFromRequest(() => Services.ContentService.GetById(id));
|
||||
@@ -116,6 +117,7 @@ namespace Umbraco.Web.Editors
|
||||
/// If this is a container type, we'll remove the umbContainerView tab for a new item since
|
||||
/// it cannot actually list children if it doesn't exist yet.
|
||||
/// </returns>
|
||||
[OutgoingEditorModelEvent]
|
||||
public ContentItemDisplay GetEmpty(string contentTypeAlias, int parentId)
|
||||
{
|
||||
var contentType = Services.ContentTypeService.GetContentType(contentTypeAlias);
|
||||
|
||||
85
src/Umbraco.Web/Editors/EditorModelEventManager.cs
Normal file
85
src/Umbraco.Web/Editors/EditorModelEventManager.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Web.Http.Filters;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
public abstract class EditorModelEventArgs : EventArgs
|
||||
{
|
||||
protected EditorModelEventArgs(object model, UmbracoContext umbracoContext)
|
||||
{
|
||||
Model = model;
|
||||
UmbracoContext = umbracoContext;
|
||||
}
|
||||
|
||||
public object Model { get; private set; }
|
||||
public UmbracoContext UmbracoContext { get; private set; }
|
||||
}
|
||||
|
||||
public sealed class EditorModelEventArgs<T> : EditorModelEventArgs
|
||||
{
|
||||
public EditorModelEventArgs(T model, UmbracoContext umbracoContext)
|
||||
: base(model, umbracoContext)
|
||||
{
|
||||
Model = model;
|
||||
}
|
||||
|
||||
public new T Model { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to emit events for editor models in the back office
|
||||
/// </summary>
|
||||
public sealed class EditorModelEventManager
|
||||
{
|
||||
public static event TypedEventHandler<HttpActionExecutedContext, EditorModelEventArgs<ContentItemDisplay>> SendingContentModel;
|
||||
public static event TypedEventHandler<HttpActionExecutedContext, EditorModelEventArgs<MediaItemDisplay>> SendingMediaModel;
|
||||
public static event TypedEventHandler<HttpActionExecutedContext, EditorModelEventArgs<MemberDisplay>> SendingMemberModel;
|
||||
|
||||
private static void OnSendingContentModel(HttpActionExecutedContext sender, EditorModelEventArgs<ContentItemDisplay> e)
|
||||
{
|
||||
var handler = SendingContentModel;
|
||||
if (handler != null) handler(sender, e);
|
||||
}
|
||||
|
||||
private static void OnSendingMediaModel(HttpActionExecutedContext sender, EditorModelEventArgs<MediaItemDisplay> e)
|
||||
{
|
||||
var handler = SendingMediaModel;
|
||||
if (handler != null) handler(sender, e);
|
||||
}
|
||||
|
||||
private static void OnSendingMemberModel(HttpActionExecutedContext sender, EditorModelEventArgs<MemberDisplay> e)
|
||||
{
|
||||
var handler = SendingMemberModel;
|
||||
if (handler != null) handler(sender, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Based on the type, emit's a specific event
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
internal static void EmitEvent(HttpActionExecutedContext sender, EditorModelEventArgs e)
|
||||
{
|
||||
var contentItemDisplay = e.Model as ContentItemDisplay;
|
||||
if (contentItemDisplay != null)
|
||||
{
|
||||
OnSendingContentModel(sender, (EditorModelEventArgs<ContentItemDisplay>) e);
|
||||
}
|
||||
|
||||
var mediaItemDisplay = e.Model as MediaItemDisplay;
|
||||
if (mediaItemDisplay != null)
|
||||
{
|
||||
OnSendingMediaModel(sender, (EditorModelEventArgs<MediaItemDisplay>)e);
|
||||
}
|
||||
|
||||
var memberItemDisplay = e.Model as MemberDisplay;
|
||||
if (memberItemDisplay != null)
|
||||
{
|
||||
OnSendingMemberModel(sender, (EditorModelEventArgs<MemberDisplay>)e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -63,13 +63,14 @@ namespace Umbraco.Web.Editors
|
||||
: base(umbracoContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets an empty content item for the
|
||||
/// </summary>
|
||||
/// <param name="contentTypeAlias"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <returns></returns>
|
||||
[OutgoingEditorModelEvent]
|
||||
public MediaItemDisplay GetEmpty(string contentTypeAlias, int parentId)
|
||||
{
|
||||
var contentType = Services.ContentTypeService.GetMediaType(contentTypeAlias);
|
||||
@@ -92,6 +93,7 @@ namespace Umbraco.Web.Editors
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[OutgoingEditorModelEvent]
|
||||
[EnsureUserPermissionForMedia("id")]
|
||||
public MediaItemDisplay GetById(int id)
|
||||
{
|
||||
|
||||
@@ -145,6 +145,7 @@ namespace Umbraco.Web.Editors
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
[OutgoingEditorModelEvent]
|
||||
public MemberDisplay GetByKey(Guid key)
|
||||
{
|
||||
MembershipUser foundMembershipMember;
|
||||
@@ -196,6 +197,7 @@ namespace Umbraco.Web.Editors
|
||||
/// </summary>
|
||||
/// <param name="contentTypeAlias"></param>
|
||||
/// <returns></returns>
|
||||
[OutgoingEditorModelEvent]
|
||||
public MemberDisplay GetEmpty(string contentTypeAlias = null)
|
||||
{
|
||||
IMember emptyContent;
|
||||
|
||||
@@ -40,9 +40,14 @@ namespace Umbraco.Web.Install.InstallSteps
|
||||
var clientDependencyConfig = new ClientDependencyConfiguration(_applicationContext.ProfilingLogger.Logger);
|
||||
var clientDependencyUpdated = clientDependencyConfig.IncreaseVersionNumber();
|
||||
|
||||
var security = new WebSecurity(_httpContext, _applicationContext);
|
||||
security.PerformLogin(0);
|
||||
|
||||
//During a new install we'll log the default user in (which is id = 0).
|
||||
// During an upgrade, the user will already need to be logged in in order to run the installer.
|
||||
if (InstallTypeTarget == InstallationType.NewInstall)
|
||||
{
|
||||
var security = new WebSecurity(_httpContext, _applicationContext);
|
||||
security.PerformLogin(0);
|
||||
}
|
||||
|
||||
//reports the ended install
|
||||
var ih = new InstallHelper(UmbracoContext.Current);
|
||||
ih.InstallStatus(true, "");
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Web.PublishedContentModels
|
||||
{
|
||||
class Empty
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,8 @@ using Umbraco.Web.Models;
|
||||
|
||||
namespace Umbraco.Web.Mvc
|
||||
{
|
||||
public class RenderModelBinder : IModelBinder
|
||||
{
|
||||
public class RenderModelBinder : IModelBinder, IModelBinderProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Binds the model to a value by using the specified controller context and binding context.
|
||||
/// </summary>
|
||||
@@ -18,14 +18,13 @@ namespace Umbraco.Web.Mvc
|
||||
/// <param name="controllerContext">The controller context.</param><param name="bindingContext">The binding context.</param>
|
||||
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
|
||||
{
|
||||
if (bindingContext.ModelType != typeof (RenderModel)) return null;
|
||||
|
||||
object model;
|
||||
if (controllerContext.RouteData.DataTokens.TryGetValue("umbraco", out model) == false)
|
||||
return null;
|
||||
|
||||
return model as RenderModel;
|
||||
}
|
||||
var culture = UmbracoContext.Current.PublishedContentRequest.Culture;
|
||||
return BindModel(model, bindingContext.ModelType, culture);
|
||||
}
|
||||
|
||||
// source is the model that we have
|
||||
// modelType is the type of the model that we need to bind to
|
||||
@@ -103,5 +102,18 @@ namespace Umbraco.Web.Mvc
|
||||
throw new ModelBindingException(string.Format("Cannot bind source type {0} to model type {1}.",
|
||||
sourceType, modelType));
|
||||
}
|
||||
|
||||
public IModelBinder GetBinder(Type modelType)
|
||||
{
|
||||
// can bind to RenderModel
|
||||
if (modelType == typeof(RenderModel)) return this;
|
||||
|
||||
// can bind to RenderModel<TContent>
|
||||
if (modelType.IsGenericType && modelType.GetGenericTypeDefinition() == typeof(RenderModel<>)) return this;
|
||||
|
||||
// can bind to TContent where TContent : IPublishedContent
|
||||
if (typeof(IPublishedContent).IsAssignableFrom(modelType)) return this;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -319,6 +319,7 @@
|
||||
<Compile Include="Editors\EditorValidationResolver.cs" />
|
||||
<Compile Include="Editors\EditorValidator.cs" />
|
||||
<Compile Include="Editors\IEditorValidator.cs" />
|
||||
<Compile Include="Editors\EditorModelEventManager.cs" />
|
||||
<Compile Include="HtmlHelperBackOfficeExtensions.cs" />
|
||||
<Compile Include="Install\InstallSteps\Version73FileCleanup.cs" />
|
||||
<Compile Include="Models\ContentEditing\DocumentTypeDisplay.cs" />
|
||||
@@ -686,6 +687,7 @@
|
||||
<Compile Include="WebApi\Filters\EnableOverrideAuthorizationAttribute.cs" />
|
||||
<Compile Include="WebApi\Filters\FilterGrouping.cs" />
|
||||
<Compile Include="WebApi\Filters\LegacyTreeAuthorizeAttribute.cs" />
|
||||
<Compile Include="WebApi\Filters\OutgoingEditorModelEventAttribute.cs" />
|
||||
<Compile Include="WebApi\Filters\OutgoingNoHyphenGuidFormatAttribute.cs" />
|
||||
<Compile Include="WebApi\Filters\OverridableAuthorizationAttribute.cs" />
|
||||
<Compile Include="WebApi\Filters\SetAngularAntiForgeryTokensAttribute.cs" />
|
||||
|
||||
@@ -125,6 +125,7 @@ namespace Umbraco.Web
|
||||
if (umbracoSettings == null) throw new ArgumentNullException("umbracoSettings");
|
||||
if (urlProviders == null) throw new ArgumentNullException("urlProviders");
|
||||
|
||||
//if there's already a singleton, and we're not replacing then there's no need to ensure anything
|
||||
if (UmbracoContext.Current != null)
|
||||
{
|
||||
if (replaceContext == false)
|
||||
@@ -132,6 +133,39 @@ namespace Umbraco.Web
|
||||
UmbracoContext.Current._replacing = true;
|
||||
}
|
||||
|
||||
var umbracoContext = CreateContext(httpContext, applicationContext, webSecurity, umbracoSettings, urlProviders, preview ?? false);
|
||||
|
||||
//assign the singleton
|
||||
UmbracoContext.Current = umbracoContext;
|
||||
return UmbracoContext.Current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a standalone UmbracoContext instance
|
||||
/// </summary>
|
||||
/// <param name="httpContext"></param>
|
||||
/// <param name="applicationContext"></param>
|
||||
/// <param name="webSecurity"></param>
|
||||
/// <param name="umbracoSettings"></param>
|
||||
/// <param name="urlProviders"></param>
|
||||
/// <param name="preview"></param>
|
||||
/// <returns>
|
||||
/// A new instance of UmbracoContext
|
||||
/// </returns>
|
||||
public static UmbracoContext CreateContext(
|
||||
HttpContextBase httpContext,
|
||||
ApplicationContext applicationContext,
|
||||
WebSecurity webSecurity,
|
||||
IUmbracoSettingsSection umbracoSettings,
|
||||
IEnumerable<IUrlProvider> urlProviders,
|
||||
bool preview)
|
||||
{
|
||||
if (httpContext == null) throw new ArgumentNullException("httpContext");
|
||||
if (applicationContext == null) throw new ArgumentNullException("applicationContext");
|
||||
if (webSecurity == null) throw new ArgumentNullException("webSecurity");
|
||||
if (umbracoSettings == null) throw new ArgumentNullException("umbracoSettings");
|
||||
if (urlProviders == null) throw new ArgumentNullException("urlProviders");
|
||||
|
||||
var umbracoContext = new UmbracoContext(
|
||||
httpContext,
|
||||
applicationContext,
|
||||
@@ -142,15 +176,15 @@ namespace Umbraco.Web
|
||||
// create the RoutingContext, and assign
|
||||
var routingContext = new RoutingContext(
|
||||
umbracoContext,
|
||||
|
||||
|
||||
//TODO: Until the new cache is done we can't really expose these to override/mock
|
||||
new Lazy<IEnumerable<IContentFinder>>(() => ContentFinderResolver.Current.Finders),
|
||||
new Lazy<IContentFinder>(() => ContentLastChanceFinderResolver.Current.Finder),
|
||||
|
||||
|
||||
// create the nice urls provider
|
||||
// there's one per request because there are some behavior parameters that can be changed
|
||||
new Lazy<UrlProvider>(
|
||||
() => new UrlProvider(
|
||||
() => new UrlProvider(
|
||||
umbracoContext,
|
||||
umbracoSettings.WebRouting,
|
||||
urlProviders),
|
||||
@@ -159,9 +193,7 @@ namespace Umbraco.Web
|
||||
//assign the routing context back
|
||||
umbracoContext.RoutingContext = routingContext;
|
||||
|
||||
//assign the singleton
|
||||
UmbracoContext.Current = umbracoContext;
|
||||
return UmbracoContext.Current;
|
||||
return umbracoContext;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -460,17 +492,9 @@ namespace Umbraco.Web
|
||||
protected override void DisposeResources()
|
||||
{
|
||||
Security.DisposeIfDisposable();
|
||||
Security = null;
|
||||
_umbracoContext = null;
|
||||
|
||||
//Before we set these to null but in fact these are application lifespan singletons so
|
||||
//there's no reason we need to set them to null and this also caused a problem with packages
|
||||
//trying to access the cache properties on RequestEnd.
|
||||
//http://issues.umbraco.org/issue/U4-2734
|
||||
//http://our.umbraco.org/projects/developer-tools/301-url-tracker/version-2/44327-Issues-with-URL-Tracker-in-614
|
||||
//ContentCache = null;
|
||||
//MediaCache = null;
|
||||
//Application = null;
|
||||
//If not running in a web ctx, ensure the thread based instance is nulled
|
||||
_umbracoContext = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Web.Http.Filters;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Editors;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Web.WebApi.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to emit outgoing editor model events
|
||||
/// </summary>
|
||||
internal sealed class OutgoingEditorModelEventAttribute : ActionFilterAttribute
|
||||
{
|
||||
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
|
||||
{
|
||||
if (actionExecutedContext.Response == null) return;
|
||||
|
||||
var user = UmbracoContext.Current.Security.CurrentUser;
|
||||
if (user == null) return;
|
||||
|
||||
var objectContent = actionExecutedContext.Response.Content as ObjectContent;
|
||||
if (objectContent != null)
|
||||
{
|
||||
var model = objectContent.Value;
|
||||
|
||||
if (model != null)
|
||||
{
|
||||
EditorModelEventManager.EmitEvent(actionExecutedContext, new EditorModelEventArgs<ContentItemDisplay>(
|
||||
(dynamic)model,
|
||||
UmbracoContext.Current));
|
||||
}
|
||||
}
|
||||
|
||||
base.OnActionExecuted(actionExecutedContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ namespace Umbraco.Web
|
||||
ViewEngines.Engines.Add(new PluginViewEngine());
|
||||
|
||||
//set model binder
|
||||
ModelBinders.Binders.Add(new KeyValuePair<Type, IModelBinder>(typeof(RenderModel), new RenderModelBinder()));
|
||||
ModelBinderProviders.BinderProviders.Add(new RenderModelBinder()); // is a provider
|
||||
|
||||
////add the profiling action filter
|
||||
//GlobalFilters.Filters.Add(new ProfilingActionFilter());
|
||||
|
||||
@@ -161,7 +161,9 @@ namespace umbraco.cms.businesslogic.media
|
||||
protected override void setupNode()
|
||||
{
|
||||
var mediaType = ApplicationContext.Current.Services.ContentTypeService.GetMediaType(Id);
|
||||
SetupNode(mediaType);
|
||||
// If it's null, it's probably a folder
|
||||
if (mediaType != null)
|
||||
SetupNode(mediaType);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Reference in New Issue
Block a user