Browse Source

Code simplified and styles finalized.

pull/243/head
Sebastian Stehle 8 years ago
parent
commit
bb5fcf9766
  1. 18
      src/Squidex.Domain.Apps.Entities/Apps/AppCommandMiddleware.cs
  2. 17
      src/Squidex.Domain.Apps.Entities/Apps/IAppTemplateBuilder.cs
  3. 55
      src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateBlogCommandMiddleware.cs
  4. 4
      src/Squidex.Domain.Apps.Entities/Contents/ContentCommandMiddleware.cs
  5. 4
      src/Squidex.Domain.Apps.Entities/Rules/RuleCommandMiddleware.cs
  6. 4
      src/Squidex.Domain.Apps.Entities/Schemas/SchemaCommandMiddleware.cs
  7. 10
      src/Squidex.Infrastructure/Commands/InMemoryCommandBus.cs
  8. 6
      src/Squidex/Config/Domain/WriteServices.cs
  9. 4
      src/Squidex/app/features/apps/pages/apps-page.component.html
  10. 4
      src/Squidex/app/features/rules/pages/rules/rule-wizard.component.html
  11. 4
      src/Squidex/app/features/rules/pages/rules/rules-page.component.html
  12. 28
      src/Squidex/app/shared/services/rules.service.ts
  13. BIN
      src/Squidex/wwwroot/images/add-blog.png
  14. 33
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppCommandMiddlewareTests.cs

18
src/Squidex.Domain.Apps.Entities/Apps/AppCommandMiddleware.cs

@ -25,29 +25,25 @@ namespace Squidex.Domain.Apps.Entities.Apps
private readonly IAppPlansProvider appPlansProvider;
private readonly IAppPlanBillingManager appPlansBillingManager;
private readonly IUserResolver userResolver;
private readonly IEnumerable<IAppTemplateBuilder> templateBuilders;
public AppCommandMiddleware(
IAggregateHandler handler,
IAppProvider appProvider,
IAppPlansProvider appPlansProvider,
IAppPlanBillingManager appPlansBillingManager,
IUserResolver userResolver,
IEnumerable<IAppTemplateBuilder> templateBuilders)
IUserResolver userResolver)
{
Guard.NotNull(handler, nameof(handler));
Guard.NotNull(appProvider, nameof(appProvider));
Guard.NotNull(userResolver, nameof(userResolver));
Guard.NotNull(appPlansProvider, nameof(appPlansProvider));
Guard.NotNull(appPlansBillingManager, nameof(appPlansBillingManager));
Guard.NotNull(templateBuilders, nameof(templateBuilders));
this.handler = handler;
this.userResolver = userResolver;
this.appProvider = appProvider;
this.appPlansProvider = appPlansProvider;
this.appPlansBillingManager = appPlansBillingManager;
this.templateBuilders = templateBuilders;
}
protected async Task On(CreateApp command, CommandContext context)
@ -60,14 +56,6 @@ namespace Squidex.Domain.Apps.Entities.Apps
context.Complete(EntityCreatedResult.Create(command.AppId, a.Version));
});
if (!string.IsNullOrWhiteSpace(command.Template))
{
foreach (var templateBuilder in templateBuilders)
{
await templateBuilder.PopulateTemplate(app.Snapshot, command.Template, context.CommandBus);
}
}
}
protected Task On(AssignContributor command, CommandContext context)
@ -206,10 +194,8 @@ namespace Squidex.Domain.Apps.Entities.Apps
public async Task HandleAsync(CommandContext context, Func<Task> next)
{
if (!await this.DispatchActionAsync(context.Command, context))
{
await this.DispatchActionAsync(context.Command, context);
await next();
}
}
}
}

17
src/Squidex.Domain.Apps.Entities/Apps/IAppTemplateBuilder.cs

@ -1,17 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading.Tasks;
using Squidex.Infrastructure.Commands;
namespace Squidex.Domain.Apps.Entities.Apps
{
public interface IAppTemplateBuilder
{
Task PopulateTemplate(IAppEntity app, string name, ICommandBus bus);
}
}

55
src/Squidex.Domain.Apps.Entities/Apps/Templates/Blog.cs → src/Squidex.Domain.Apps.Entities/Apps/Templates/CreateBlogCommandMiddleware.cs

@ -16,11 +16,13 @@ using Squidex.Domain.Apps.Entities.Contents.Commands;
using Squidex.Domain.Apps.Entities.Schemas.Commands;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.Tasks;
namespace Squidex.Domain.Apps.Entities.Apps.Templates
{
public sealed class Blog : IAppTemplateBuilder
public sealed class CreateBlogCommandMiddleware : ICommandMiddleware
{
private const string TemplateName = "Blog";
private const string SlugScript = @"
var data = ctx.data;
@ -28,52 +30,71 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
replace(data);";
public async Task PopulateTemplate(IAppEntity app, string name, ICommandBus bus)
public Task HandleAsync(CommandContext context, Func<Task> next)
{
if (string.Equals("Blog", name, StringComparison.OrdinalIgnoreCase))
if (context.IsCompleted &&
context.Command is CreateApp createApp &&
string.Equals(createApp.Template, TemplateName, StringComparison.OrdinalIgnoreCase))
{
var appId = new NamedId<Guid>(app.Id, app.Name);
var appId = new NamedId<Guid>(createApp.AppId, createApp.Name);
Task publishAsync(AppCommand command)
{
command.AppId = appId;
return bus.PublishAsync(command);
return context.CommandBus.PublishAsync(command);
}
var pagesId = await CreatePagesSchema(publishAsync);
return Task.WhenAll(
CreatePagesAsync(publishAsync, appId),
CreatePostsAsync(publishAsync, appId),
CreateClientAsync(publishAsync, appId));
}
return TaskHelper.Done;
}
private static async Task CreateClientAsync(Func<AppCommand, Task> publishAsync, NamedId<Guid> appId)
{
await publishAsync(new AttachClient { Id = "sample-client" });
}
private async Task CreatePostsAsync(Func<AppCommand, Task> publishAsync, NamedId<Guid> appId)
{
var postsId = await CreatePostsSchema(publishAsync);
await publishAsync(new CreateContent
{
SchemaId = pagesId,
SchemaId = postsId,
Data =
new NamedContentData()
.AddField("title",
new ContentFieldData()
.AddValue("iv", "About Me"))
.AddValue("iv", "My first post with Squidex"))
.AddField("text",
new ContentFieldData()
.AddValue("iv", "I love Squidex and SciFi!")),
Publish = true
.AddValue("iv", "Just created a blog with Squidex. I love it!")),
Publish = true,
});
}
private async Task CreatePagesAsync(Func<AppCommand, Task> publishAsync, NamedId<Guid> appId)
{
var pagesId = await CreatePagesSchema(publishAsync);
await publishAsync(new CreateContent
{
SchemaId = postsId,
SchemaId = pagesId,
Data =
new NamedContentData()
.AddField("title",
new ContentFieldData()
.AddValue("iv", "My first post with Squidex"))
.AddValue("iv", "About Me"))
.AddField("text",
new ContentFieldData()
.AddValue("iv", "Just created a blog with Squidex. I love it!")),
Publish = true,
.AddValue("iv", "I love Squidex and SciFi!")),
Publish = true
});
await publishAsync(new AttachClient { Id = "sample-client" });
}
}
private async Task<NamedId<Guid>> CreatePostsSchema(Func<AppCommand, Task> publishAsync)

4
src/Squidex.Domain.Apps.Entities/Contents/ContentCommandMiddleware.cs

@ -133,11 +133,9 @@ namespace Squidex.Domain.Apps.Entities.Contents
public async Task HandleAsync(CommandContext context, Func<Task> next)
{
if (!await this.DispatchActionAsync(context.Command, context))
{
await this.DispatchActionAsync(context.Command, context);
await next();
}
}
private async Task<ContentOperationContext> CreateContext(ContentCommand command, ContentDomainObject content, Func<string> message)
{

4
src/Squidex.Domain.Apps.Entities/Rules/RuleCommandMiddleware.cs

@ -82,10 +82,8 @@ namespace Squidex.Domain.Apps.Entities.Rules
public async Task HandleAsync(CommandContext context, Func<Task> next)
{
if (!await this.DispatchActionAsync(context.Command, context))
{
await this.DispatchActionAsync(context.Command, context);
await next();
}
}
}
}

4
src/Squidex.Domain.Apps.Entities/Schemas/SchemaCommandMiddleware.cs

@ -187,10 +187,8 @@ namespace Squidex.Domain.Apps.Entities.Schemas
public async Task HandleAsync(CommandContext context, Func<Task> next)
{
if (!await this.DispatchActionAsync(context.Command, context))
{
await this.DispatchActionAsync(context.Command, context);
await next();
}
}
}
}

10
src/Squidex.Infrastructure/Commands/InMemoryCommandBus.cs

@ -15,13 +15,13 @@ namespace Squidex.Infrastructure.Commands
{
public sealed class InMemoryCommandBus : ICommandBus
{
private readonly List<ICommandMiddleware> handlers;
private readonly List<ICommandMiddleware> middlewares;
public InMemoryCommandBus(IEnumerable<ICommandMiddleware> handlers)
public InMemoryCommandBus(IEnumerable<ICommandMiddleware> middlewares)
{
Guard.NotNull(handlers, nameof(handlers));
Guard.NotNull(middlewares, nameof(middlewares));
this.handlers = handlers.Reverse().ToList();
this.middlewares = middlewares.Reverse().ToList();
}
public async Task<CommandContext> PublishAsync(ICommand command)
@ -32,7 +32,7 @@ namespace Squidex.Infrastructure.Commands
var next = new Func<Task>(() => TaskHelper.Done);
foreach (var handler in handlers)
foreach (var handler in middlewares)
{
next = Join(handler, context, next);
}

6
src/Squidex/Config/Domain/WriteServices.cs

@ -64,6 +64,9 @@ namespace Squidex.Config.Domain
services.AddSingletonAs<RuleCommandMiddleware>()
.As<ICommandMiddleware>();
services.AddSingletonAs<CreateBlogCommandMiddleware>()
.As<ICommandMiddleware>();
services.AddTransientAs<Migration01_FromCqrs>()
.As<IMigration>();
@ -76,9 +79,6 @@ namespace Squidex.Config.Domain
services.AddTransientAs<Migration04_FlattenAssetEntity>()
.As<IMigration>();
services.AddTransientAs<Blog>()
.As<IAppTemplateBuilder>();
services.AddTransientAs<Rebuilder>()
.AsSelf();

4
src/Squidex/app/features/apps/pages/apps-page.component.html

@ -42,10 +42,10 @@
<div class="card card-template card-href" (click)="createNewApp('Blog')">
<div class="card-body">
<div class="card-image">
<img src="/images/add-app.png" />
<img src="/images/add-blog.png" />
</div>
<h4 class="card-title">Blog Sample</h4>
<h4 class="card-title">New Blog Sample</h4>
<div class="card-text">
<div>Start with our ready to use blog.</div>

4
src/Squidex/app/features/rules/pages/rules/rule-wizard.component.html

@ -32,7 +32,7 @@
<i class="icon-trigger-{{trigger}}"></i>
</span>
<span class="rule-element-text">
{{ruleTriggers[trigger]}}
{{ruleTriggers[trigger].name}}
</span>
</span>
</div>
@ -61,7 +61,7 @@
<i class="icon-action-{{action}}"></i>
</span>
<span class="rule-element-text">
{{ruleActions[action]}}
{{ruleActions[action].name}}
</span>
</span>
</div>

4
src/Squidex/app/features/rules/pages/rules/rules-page.component.html

@ -43,7 +43,7 @@
<i class="icon-trigger-{{rule.triggerType}}"></i>
</span>
<span class="rule-element-text">
{{ruleTriggers[rule.triggerType]}}
{{ruleTriggers[rule.triggerType].name}}
</span>
</span>
</td>
@ -56,7 +56,7 @@
<i class="icon-action-{{rule.actionType}}"></i>
</span>
<span class="rule-element-text">
{{ruleActions[rule.actionType]}}
{{ruleActions[rule.actionType].name}}
</span>
</span>
</td>

28
src/Squidex/app/shared/services/rules.service.ts

@ -21,16 +21,30 @@ import {
} from 'framework';
export const ruleTriggers: any = {
'AssetChanged': 'Asset changed',
'ContentChanged': 'Content changed'
'AssetChanged': {
name: 'Asset changed'
},
'ContentChanged': {
name: 'Content changed'
}
};
export const ruleActions: any = {
'Algolia': 'Populate Algolia Index',
'AzureQueue': 'Send to Azure Queue',
'Fastly': 'Purge fastly Cache',
'Slack': 'Send to Slack',
'Webhook': 'Send Webhook'
'Algolia': {
name: 'Populate Algolia Index'
},
'AzureQueue': {
name: 'Send to Azure Queue'
},
'Fastly': {
name: 'Purge fastly Cache'
},
'Slack': {
name: 'Send to Slack'
},
'Webhook': {
name: 'Send Webhook'
}
};
export class RuleDto {

BIN
src/Squidex/wwwroot/images/add-blog.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

33
tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppCommandMiddlewareTests.cs

@ -25,8 +25,6 @@ namespace Squidex.Domain.Apps.Entities.Apps
private readonly IAppPlansProvider appPlansProvider = A.Fake<IAppPlansProvider>();
private readonly IAppPlanBillingManager appPlansBillingManager = A.Fake<IAppPlanBillingManager>();
private readonly IUserResolver userResolver = A.Fake<IUserResolver>();
private readonly IAppTemplateBuilder templateBuilder1 = A.Fake<IAppTemplateBuilder>();
private readonly IAppTemplateBuilder templateBuilder2 = A.Fake<IAppTemplateBuilder>();
private readonly Language language = Language.DE;
private readonly string contributorId = Guid.NewGuid().ToString();
private readonly string clientName = "client";
@ -47,13 +45,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
A.CallTo(() => userResolver.FindByIdAsync(contributorId))
.Returns(A.Fake<IUser>());
var templateBuilders = new[]
{
templateBuilder1,
templateBuilder2
};
sut = new AppCommandMiddleware(Handler, appProvider, appPlansProvider, appPlansBillingManager, userResolver, templateBuilders);
sut = new AppCommandMiddleware(Handler, appProvider, appPlansProvider, appPlansBillingManager, userResolver);
}
[Fact]
@ -67,29 +59,6 @@ namespace Squidex.Domain.Apps.Entities.Apps
});
Assert.Equal(AppId, context.Result<EntityCreatedResult<Guid>>().IdOrValue);
A.CallTo(() => templateBuilder1.PopulateTemplate(A<IAppEntity>.Ignored, A<string>.Ignored, context.CommandBus))
.MustNotHaveHappened();
A.CallTo(() => templateBuilder2.PopulateTemplate(A<IAppEntity>.Ignored, A<string>.Ignored, context.CommandBus))
.MustNotHaveHappened();
}
[Fact]
public async Task Create_should_call_template_builders_with_template_name()
{
var context = CreateContextForCommand(new CreateApp { Name = AppName, AppId = AppId, Template = "Blog" });
await TestCreate(app, async _ =>
{
await sut.HandleAsync(context);
});
Assert.Equal(AppId, context.Result<EntityCreatedResult<Guid>>().IdOrValue);
A.CallTo(() => templateBuilder1.PopulateTemplate(A<IAppEntity>.Ignored, "Blog", context.CommandBus))
.MustHaveHappened();
A.CallTo(() => templateBuilder2.PopulateTemplate(A<IAppEntity>.Ignored, "Blog", context.CommandBus))
.MustHaveHappened();
}
[Fact]

Loading…
Cancel
Save