mirror of https://github.com/Squidex/squidex.git
44 changed files with 1120 additions and 71 deletions
@ -0,0 +1,23 @@ |
|||
// ==========================================================================
|
|||
// ImageInfo.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
namespace Squidex.Infrastructure.Assets |
|||
{ |
|||
public sealed class ImageInfo |
|||
{ |
|||
public int PixelWidth { get; } |
|||
|
|||
public int PixelHeight { get; } |
|||
|
|||
public ImageInfo(int pixelWidth, int pixelHeight) |
|||
{ |
|||
PixelWidth = pixelWidth; |
|||
PixelHeight = pixelHeight; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
// ==========================================================================
|
|||
// AssetCommandHandler.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.CQRS.Commands; |
|||
using Squidex.Infrastructure.Dispatching; |
|||
using Squidex.Infrastructure.Tasks; |
|||
using Squidex.Write.Assets.Commands; |
|||
|
|||
namespace Squidex.Write.Assets |
|||
{ |
|||
public class AssetCommandHandler : ICommandHandler |
|||
{ |
|||
private readonly IAggregateHandler handler; |
|||
|
|||
public AssetCommandHandler(IAggregateHandler handler) |
|||
{ |
|||
Guard.NotNull(handler, nameof(handler)); |
|||
|
|||
this.handler = handler; |
|||
} |
|||
|
|||
protected async Task On(CreateAsset command, CommandContext context) |
|||
{ |
|||
await handler.CreateAsync<AssetDomainObject>(context, c => |
|||
{ |
|||
c.Create(command); |
|||
|
|||
context.Succeed(EntityCreatedResult.Create(c.Id, c.Version)); |
|||
}); |
|||
} |
|||
|
|||
protected async Task On(RenameAsset command, CommandContext context) |
|||
{ |
|||
await handler.UpdateAsync<AssetDomainObject>(context, c => c.Rename(command)); |
|||
} |
|||
|
|||
protected async Task On(UpdateAsset command, CommandContext context) |
|||
{ |
|||
await handler.UpdateAsync<AssetDomainObject>(context, c => c.Update(command)); |
|||
} |
|||
|
|||
protected Task On(DeleteAsset command, CommandContext context) |
|||
{ |
|||
return handler.UpdateAsync<AssetDomainObject>(context, c => c.Delete(command)); |
|||
} |
|||
|
|||
public Task<bool> HandleAsync(CommandContext context) |
|||
{ |
|||
return context.IsHandled ? TaskHelper.False : this.DispatchActionAsync(context.Command, context); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
// ==========================================================================
|
|||
// UpdateAssetCommand.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
namespace Squidex.Write.Assets.Commands |
|||
{ |
|||
public class UpdateAsset : AssetAggregateCommand |
|||
{ |
|||
public string MimeType { get; set; } |
|||
|
|||
public long FileSize { get; set; } |
|||
|
|||
public bool IsImage { get; set; } |
|||
|
|||
public int? PixelWidth { get; set; } |
|||
|
|||
public int? PixelHeight { get; set; } |
|||
} |
|||
} |
|||
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 65 KiB |
@ -0,0 +1,107 @@ |
|||
// ==========================================================================
|
|||
// AssetDto.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using NodaTime; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.CQRS.Commands; |
|||
using Squidex.Write.Assets.Commands; |
|||
|
|||
namespace Squidex.Controllers.Api.Assets.Models |
|||
{ |
|||
public sealed class AssetDto |
|||
{ |
|||
/// <summary>
|
|||
/// The id of the asset.
|
|||
/// </summary>
|
|||
public Guid Id { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The file name.
|
|||
/// </summary>
|
|||
[Required] |
|||
public string FileName { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The mime type.
|
|||
/// </summary>
|
|||
[Required] |
|||
public string MimeType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The size of the file in bytes.
|
|||
/// </summary>
|
|||
public long FileSize { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Determines of the created file is an image.
|
|||
/// </summary>
|
|||
public bool IsImage { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The width of the image in pixels if the asset is an image.
|
|||
/// </summary>
|
|||
public int? PixelWidth { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The height of the image in pixels if the asset is an image.
|
|||
/// </summary>
|
|||
public int? PixelHeight { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The user that has created the schema.
|
|||
/// </summary>
|
|||
[Required] |
|||
public RefToken CreatedBy { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The user that has updated the asset.
|
|||
/// </summary>
|
|||
[Required] |
|||
public RefToken LastModifiedBy { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The date and time when the asset has been created.
|
|||
/// </summary>
|
|||
public Instant Created { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The date and time when the asset has been modified last.
|
|||
/// </summary>
|
|||
public Instant LastModified { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The version of the asset.
|
|||
/// </summary>
|
|||
public long Version { get; set; } |
|||
|
|||
public static AssetDto Create(CreateAsset command, EntityCreatedResult<Guid> result) |
|||
{ |
|||
var now = SystemClock.Instance.GetCurrentInstant(); |
|||
|
|||
var response = new AssetDto |
|||
{ |
|||
Id = result.IdOrValue, |
|||
Version = result.Version, |
|||
Created = now, |
|||
CreatedBy = command.Actor, |
|||
LastModified = now, |
|||
LastModifiedBy = command.Actor, |
|||
FileName = command.FileName, |
|||
FileSize = command.FileSize, |
|||
MimeType = command.MimeType, |
|||
IsImage = command.IsImage, |
|||
PixelWidth = command.PixelWidth, |
|||
PixelHeight = command.PixelHeight |
|||
}; |
|||
|
|||
return response; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
// ==========================================================================
|
|||
// AssetsDto.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
namespace Squidex.Controllers.Api.Assets.Models |
|||
{ |
|||
public sealed class AssetsDto |
|||
{ |
|||
/// <summary>
|
|||
/// The total number of assets.
|
|||
/// </summary>
|
|||
public long Total { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// The assets.
|
|||
/// </summary>
|
|||
public AssetDto[] Items { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
<div class="card"> |
|||
<div class="card-block"> |
|||
</div> |
|||
<div class="card-footer"> |
|||
{{fileInfo}} |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,11 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
$card-size: 16rem; |
|||
|
|||
.card { |
|||
width: $card-size; |
|||
height: $card-size; |
|||
margin-right: 1rem; |
|||
margin-bottom: 1rem; |
|||
} |
|||
@ -0,0 +1,77 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import { Component, Input, OnInit } from '@angular/core'; |
|||
|
|||
import { |
|||
AppComponentBase, |
|||
AppsStoreService, |
|||
AssetDto, |
|||
AssetsService, |
|||
NotificationService, |
|||
UsersProviderService |
|||
} from 'shared'; |
|||
|
|||
@Component({ |
|||
selector: 'sqx-asset', |
|||
styleUrls: ['./asset.component.scss'], |
|||
templateUrl: './asset.component.html' |
|||
}) |
|||
export class AssetComponent extends AppComponentBase implements OnInit { |
|||
@Input() |
|||
public initFile: File; |
|||
|
|||
@Input() |
|||
public asset: AssetDto; |
|||
|
|||
public get fileInfo(): string { |
|||
let result = ''; |
|||
|
|||
if (this.asset != null) { |
|||
if (this.asset.pixelWidth) { |
|||
result = `${this.asset.pixelWidth}x${this.asset.pixelHeight}px, `; |
|||
} |
|||
|
|||
result += fileSize(this.asset.fileSize); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
constructor(apps: AppsStoreService, notifications: NotificationService, users: UsersProviderService, |
|||
private readonly assetsService: AssetsService |
|||
) { |
|||
super(notifications, users, apps); |
|||
} |
|||
|
|||
public ngOnInit() { |
|||
const initFile = this.initFile; |
|||
|
|||
if (initFile) { |
|||
this.appName() |
|||
.switchMap(app => this.assetsService.uploadFile(app, initFile)) |
|||
.subscribe(result => { |
|||
if (result instanceof AssetDto) { |
|||
this.asset = result; |
|||
} |
|||
}, error => { |
|||
this.notifyError(error); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
function fileSize(b: number) { |
|||
let u = 0, s = 1024; |
|||
|
|||
while (b >= s || -b >= s) { |
|||
b /= s; |
|||
u++; |
|||
} |
|||
|
|||
return (u ? b.toFixed(1) + ' ' : b) + ' kMGTPEZY'[u] + 'B'; |
|||
} |
|||
@ -1,2 +1,24 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
.file-drop { |
|||
& { |
|||
border: 2px dashed $color-border; |
|||
background: transparent; |
|||
padding: 1rem; |
|||
text-align: center; |
|||
margin-bottom: 1rem; |
|||
} |
|||
|
|||
&-or { |
|||
font-size: .8rem; |
|||
} |
|||
|
|||
&-button { |
|||
margin: .5rem 0; |
|||
} |
|||
|
|||
&-info { |
|||
color: $color-subtext; |
|||
} |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import { Directive, EventEmitter, HostListener, Output } from '@angular/core'; |
|||
|
|||
@Directive({ |
|||
selector: '[sqxFileDrop]' |
|||
}) |
|||
export class FileDropDirective { |
|||
@Output('sqxFileDrop') |
|||
public drop = new EventEmitter<File[]>(); |
|||
|
|||
@HostListener('dragenter', ['$event']) |
|||
public onDragEnter(event: DragDropEvent) { |
|||
this.tryStopEvent(event); |
|||
} |
|||
|
|||
@HostListener('dragover', ['$event']) |
|||
public onDragOver(event: DragDropEvent) { |
|||
this.tryStopEvent(event); |
|||
} |
|||
|
|||
@HostListener('drop', ['$event']) |
|||
public onDrop(event: DragDropEvent) { |
|||
const files: File[] = []; |
|||
|
|||
// tslint:disable-next-line:prefer-for-of
|
|||
for (let i = 0; i < event.dataTransfer.files.length; i++) { |
|||
const file = event.dataTransfer.files[i]; |
|||
|
|||
files.push(file); |
|||
} |
|||
|
|||
this.drop.emit(files); |
|||
|
|||
this.stopEvent(event); |
|||
} |
|||
|
|||
private stopEvent(event: Event) { |
|||
event.preventDefault(); |
|||
event.stopPropagation(); |
|||
} |
|||
|
|||
private tryStopEvent(event: DragDropEvent) { |
|||
const hasFiles = this.hasFiles(event.dataTransfer.types); |
|||
|
|||
if (!hasFiles) { |
|||
return; |
|||
} |
|||
|
|||
this.stopEvent(event); |
|||
} |
|||
|
|||
private hasFiles(types: any): boolean { |
|||
if (!types) { |
|||
return false; |
|||
} |
|||
|
|||
if (isFunction(types.indexOf)) { |
|||
return types.indexOf('Files') !== -1; |
|||
} else if (isFunction(types.contains)) { |
|||
return types.contains('Files'); |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
function isFunction(obj: any): boolean { |
|||
return !!(obj && obj.constructor && obj.call && obj.apply); |
|||
}; |
|||
|
|||
interface DragDropEvent extends MouseEvent { |
|||
readonly dataTransfer: DataTransfer; |
|||
} |
|||
@ -0,0 +1,93 @@ |
|||
// ==========================================================================
|
|||
// AssetCommandHandlerTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Infrastructure.CQRS.Commands; |
|||
using Squidex.Write.Assets.Commands; |
|||
using Squidex.Write.TestHelpers; |
|||
using Xunit; |
|||
|
|||
// ReSharper disable ConvertToConstant.Local
|
|||
|
|||
namespace Squidex.Write.Assets |
|||
{ |
|||
public class AssetCommandHandlerTests : HandlerTestBase<AssetDomainObject> |
|||
{ |
|||
private readonly AssetCommandHandler sut; |
|||
private readonly AssetDomainObject asset; |
|||
private readonly Guid assetId = Guid.NewGuid(); |
|||
private readonly string fileName = "my-image.png"; |
|||
private readonly string mimeType = "image/png"; |
|||
private readonly long fileSize = 1024; |
|||
|
|||
public AssetCommandHandlerTests() |
|||
{ |
|||
asset = new AssetDomainObject(assetId, 0); |
|||
|
|||
sut = new AssetCommandHandler(Handler); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Create_should_create_asset() |
|||
{ |
|||
var context = CreateContextForCommand(new CreateAsset { AssetId = assetId, FileName = fileName, FileSize = fileSize, MimeType = mimeType }); |
|||
|
|||
await TestCreate(asset, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
|
|||
Assert.Equal(assetId, context.Result<EntityCreatedResult<Guid>>().IdOrValue); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Update_should_update_domain_object() |
|||
{ |
|||
CreateAsset(); |
|||
|
|||
var context = CreateContextForCommand(new UpdateAsset { AssetId = assetId, FileSize = fileSize, MimeType = mimeType }); |
|||
|
|||
await TestUpdate(asset, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Rename_should_update_domain_object() |
|||
{ |
|||
CreateAsset(); |
|||
|
|||
var context = CreateContextForCommand(new RenameAsset { AssetId = assetId, FileName = "my-new-image.png" }); |
|||
|
|||
await TestUpdate(asset, async _ => |
|||
{ |
|||
await sut.HandleAsync(context); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Delete_should_update_domain_object() |
|||
{ |
|||
CreateAsset(); |
|||
|
|||
var command = CreateContextForCommand(new DeleteAsset { AssetId = assetId }); |
|||
|
|||
await TestUpdate(asset, async _ => |
|||
{ |
|||
await sut.HandleAsync(command); |
|||
}); |
|||
} |
|||
|
|||
private void CreateAsset() |
|||
{ |
|||
asset.Create(new CreateAsset { FileName = fileName, FileSize = fileSize, MimeType = mimeType }); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,211 @@ |
|||
// ==========================================================================
|
|||
// AssetDomainObjectTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Squidex.Events.Assets; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.CQRS; |
|||
using Squidex.Write.Assets.Commands; |
|||
using Squidex.Write.TestHelpers; |
|||
using Xunit; |
|||
|
|||
// ReSharper disable ConvertToConstant.Local
|
|||
|
|||
namespace Squidex.Write.Assets |
|||
{ |
|||
public class AssetDomainObjectTests : HandlerTestBase<AssetDomainObject> |
|||
{ |
|||
private readonly AssetDomainObject sut; |
|||
private readonly string fileName = "my-image.png"; |
|||
private readonly string mimeType = "image/png"; |
|||
private readonly long fileSize = 1024; |
|||
|
|||
public Guid AssetId { get; } = Guid.NewGuid(); |
|||
|
|||
public AssetDomainObjectTests() |
|||
{ |
|||
sut = new AssetDomainObject(AssetId, 0); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_throw_if_created() |
|||
{ |
|||
sut.Create(new CreateAsset { FileName = fileName, FileSize = fileSize, MimeType = mimeType }); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Create(CreateAssetCommand(new CreateAsset { FileName = fileName, FileSize = fileSize, MimeType = mimeType })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Create_should_create_events() |
|||
{ |
|||
sut.Create(CreateAssetCommand(new CreateAsset { FileName = fileName, FileSize = fileSize, MimeType = mimeType })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateAssetEvent(new AssetCreated { FileName = fileName, FileSize = fileSize, MimeType = mimeType }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateAssetCommand(new UpdateAsset { FileSize = fileSize, MimeType = mimeType })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_throw_if_asset_is_deleted() |
|||
{ |
|||
CreateAsset(); |
|||
DeleteAsset(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateAssetCommand(new UpdateAsset())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Update_should_create_events() |
|||
{ |
|||
CreateAsset(); |
|||
|
|||
sut.Update(CreateAssetCommand(new UpdateAsset { FileSize = fileSize, MimeType = mimeType })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateAssetEvent(new AssetUpdated { FileSize = fileSize, MimeType = mimeType }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rename_should_throw_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateAssetCommand(new UpdateAsset { FileSize = fileSize, MimeType = mimeType })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rename_should_throw_if_asset_is_deleted() |
|||
{ |
|||
CreateAsset(); |
|||
DeleteAsset(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Update(CreateAssetCommand(new UpdateAsset())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rename_should_throw_if_command_is_not_valid() |
|||
{ |
|||
CreateAsset(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.Rename(CreateAssetCommand(new RenameAsset())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rename_should_throw_if_new_name_is_equal_to_old_name() |
|||
{ |
|||
CreateAsset(); |
|||
|
|||
Assert.Throws<ValidationException>(() => |
|||
{ |
|||
sut.Rename(CreateAssetCommand(new RenameAsset { FileName = fileName })); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rename_should_create_events() |
|||
{ |
|||
CreateAsset(); |
|||
|
|||
sut.Rename(CreateAssetCommand(new RenameAsset { FileName = "my-new-image.png" })); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateAssetEvent(new AssetRenamed { FileName = "my-new-image.png" }) |
|||
); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_throw_if_not_created() |
|||
{ |
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Delete(CreateAssetCommand(new DeleteAsset())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_throw_if_already_deleted() |
|||
{ |
|||
CreateAsset(); |
|||
DeleteAsset(); |
|||
|
|||
Assert.Throws<DomainException>(() => |
|||
{ |
|||
sut.Delete(CreateAssetCommand(new DeleteAsset())); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Delete_should_update_properties_create_events() |
|||
{ |
|||
CreateAsset(); |
|||
|
|||
sut.Delete(CreateAssetCommand(new DeleteAsset())); |
|||
|
|||
Assert.True(sut.IsDeleted); |
|||
|
|||
sut.GetUncomittedEvents() |
|||
.ShouldHaveSameEvents( |
|||
CreateAssetEvent(new AssetDeleted()) |
|||
); |
|||
} |
|||
|
|||
private void CreateAsset() |
|||
{ |
|||
sut.Create(CreateAssetCommand(new CreateAsset { FileName = fileName, FileSize = fileSize, MimeType = mimeType })); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
private void DeleteAsset() |
|||
{ |
|||
sut.Delete(CreateAssetCommand(new DeleteAsset())); |
|||
|
|||
((IAggregate)sut).ClearUncommittedEvents(); |
|||
} |
|||
|
|||
protected T CreateAssetEvent<T>(T @event) where T : AssetEvent |
|||
{ |
|||
@event.AssetId = AssetId; |
|||
|
|||
return CreateEvent(@event); |
|||
} |
|||
|
|||
protected T CreateAssetCommand<T>(T command) where T : AssetAggregateCommand |
|||
{ |
|||
command.AssetId = AssetId; |
|||
|
|||
return CreateCommand(command); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue