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 IAppPlansProvider appPlansProvider;
private readonly IAppPlanBillingManager appPlansBillingManager; private readonly IAppPlanBillingManager appPlansBillingManager;
private readonly IUserResolver userResolver; private readonly IUserResolver userResolver;
private readonly IEnumerable<IAppTemplateBuilder> templateBuilders;
public AppCommandMiddleware( public AppCommandMiddleware(
IAggregateHandler handler, IAggregateHandler handler,
IAppProvider appProvider, IAppProvider appProvider,
IAppPlansProvider appPlansProvider, IAppPlansProvider appPlansProvider,
IAppPlanBillingManager appPlansBillingManager, IAppPlanBillingManager appPlansBillingManager,
IUserResolver userResolver, IUserResolver userResolver)
IEnumerable<IAppTemplateBuilder> templateBuilders)
{ {
Guard.NotNull(handler, nameof(handler)); Guard.NotNull(handler, nameof(handler));
Guard.NotNull(appProvider, nameof(appProvider)); Guard.NotNull(appProvider, nameof(appProvider));
Guard.NotNull(userResolver, nameof(userResolver)); Guard.NotNull(userResolver, nameof(userResolver));
Guard.NotNull(appPlansProvider, nameof(appPlansProvider)); Guard.NotNull(appPlansProvider, nameof(appPlansProvider));
Guard.NotNull(appPlansBillingManager, nameof(appPlansBillingManager)); Guard.NotNull(appPlansBillingManager, nameof(appPlansBillingManager));
Guard.NotNull(templateBuilders, nameof(templateBuilders));
this.handler = handler; this.handler = handler;
this.userResolver = userResolver; this.userResolver = userResolver;
this.appProvider = appProvider; this.appProvider = appProvider;
this.appPlansProvider = appPlansProvider; this.appPlansProvider = appPlansProvider;
this.appPlansBillingManager = appPlansBillingManager; this.appPlansBillingManager = appPlansBillingManager;
this.templateBuilders = templateBuilders;
} }
protected async Task On(CreateApp command, CommandContext context) 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)); 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) 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) public async Task HandleAsync(CommandContext context, Func<Task> next)
{ {
if (!await this.DispatchActionAsync(context.Command, context)) await this.DispatchActionAsync(context.Command, context);
{
await next(); 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.Domain.Apps.Entities.Schemas.Commands;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.Commands;
using Squidex.Infrastructure.Tasks;
namespace Squidex.Domain.Apps.Entities.Apps.Templates 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 = @" private const string SlugScript = @"
var data = ctx.data; var data = ctx.data;
@ -28,52 +30,71 @@ namespace Squidex.Domain.Apps.Entities.Apps.Templates
replace(data);"; 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) Task publishAsync(AppCommand command)
{ {
command.AppId = appId; 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); var postsId = await CreatePostsSchema(publishAsync);
await publishAsync(new CreateContent await publishAsync(new CreateContent
{ {
SchemaId = pagesId, SchemaId = postsId,
Data = Data =
new NamedContentData() new NamedContentData()
.AddField("title", .AddField("title",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", "About Me")) .AddValue("iv", "My first post with Squidex"))
.AddField("text", .AddField("text",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", "I love Squidex and SciFi!")), .AddValue("iv", "Just created a blog with Squidex. I love it!")),
Publish = true Publish = true,
}); });
}
private async Task CreatePagesAsync(Func<AppCommand, Task> publishAsync, NamedId<Guid> appId)
{
var pagesId = await CreatePagesSchema(publishAsync);
await publishAsync(new CreateContent await publishAsync(new CreateContent
{ {
SchemaId = postsId, SchemaId = pagesId,
Data = Data =
new NamedContentData() new NamedContentData()
.AddField("title", .AddField("title",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", "My first post with Squidex")) .AddValue("iv", "About Me"))
.AddField("text", .AddField("text",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", "Just created a blog with Squidex. I love it!")), .AddValue("iv", "I love Squidex and SciFi!")),
Publish = true, Publish = true
}); });
await publishAsync(new AttachClient { Id = "sample-client" });
}
} }
private async Task<NamedId<Guid>> CreatePostsSchema(Func<AppCommand, Task> publishAsync) 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) public async Task HandleAsync(CommandContext context, Func<Task> next)
{ {
if (!await this.DispatchActionAsync(context.Command, context)) await this.DispatchActionAsync(context.Command, context);
{
await next(); await next();
} }
}
private async Task<ContentOperationContext> CreateContext(ContentCommand command, ContentDomainObject content, Func<string> message) 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) public async Task HandleAsync(CommandContext context, Func<Task> next)
{ {
if (!await this.DispatchActionAsync(context.Command, context)) await this.DispatchActionAsync(context.Command, context);
{
await next(); 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) public async Task HandleAsync(CommandContext context, Func<Task> next)
{ {
if (!await this.DispatchActionAsync(context.Command, context)) await this.DispatchActionAsync(context.Command, context);
{
await next(); await next();
} }
} }
}
} }

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

@ -15,13 +15,13 @@ namespace Squidex.Infrastructure.Commands
{ {
public sealed class InMemoryCommandBus : ICommandBus 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) public async Task<CommandContext> PublishAsync(ICommand command)
@ -32,7 +32,7 @@ namespace Squidex.Infrastructure.Commands
var next = new Func<Task>(() => TaskHelper.Done); var next = new Func<Task>(() => TaskHelper.Done);
foreach (var handler in handlers) foreach (var handler in middlewares)
{ {
next = Join(handler, context, next); next = Join(handler, context, next);
} }

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

@ -64,6 +64,9 @@ namespace Squidex.Config.Domain
services.AddSingletonAs<RuleCommandMiddleware>() services.AddSingletonAs<RuleCommandMiddleware>()
.As<ICommandMiddleware>(); .As<ICommandMiddleware>();
services.AddSingletonAs<CreateBlogCommandMiddleware>()
.As<ICommandMiddleware>();
services.AddTransientAs<Migration01_FromCqrs>() services.AddTransientAs<Migration01_FromCqrs>()
.As<IMigration>(); .As<IMigration>();
@ -76,9 +79,6 @@ namespace Squidex.Config.Domain
services.AddTransientAs<Migration04_FlattenAssetEntity>() services.AddTransientAs<Migration04_FlattenAssetEntity>()
.As<IMigration>(); .As<IMigration>();
services.AddTransientAs<Blog>()
.As<IAppTemplateBuilder>();
services.AddTransientAs<Rebuilder>() services.AddTransientAs<Rebuilder>()
.AsSelf(); .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 card-template card-href" (click)="createNewApp('Blog')">
<div class="card-body"> <div class="card-body">
<div class="card-image"> <div class="card-image">
<img src="/images/add-app.png" /> <img src="/images/add-blog.png" />
</div> </div>
<h4 class="card-title">Blog Sample</h4> <h4 class="card-title">New Blog Sample</h4>
<div class="card-text"> <div class="card-text">
<div>Start with our ready to use blog.</div> <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> <i class="icon-trigger-{{trigger}}"></i>
</span> </span>
<span class="rule-element-text"> <span class="rule-element-text">
{{ruleTriggers[trigger]}} {{ruleTriggers[trigger].name}}
</span> </span>
</span> </span>
</div> </div>
@ -61,7 +61,7 @@
<i class="icon-action-{{action}}"></i> <i class="icon-action-{{action}}"></i>
</span> </span>
<span class="rule-element-text"> <span class="rule-element-text">
{{ruleActions[action]}} {{ruleActions[action].name}}
</span> </span>
</span> </span>
</div> </div>

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

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

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

@ -21,16 +21,30 @@ import {
} from 'framework'; } from 'framework';
export const ruleTriggers: any = { export const ruleTriggers: any = {
'AssetChanged': 'Asset changed', 'AssetChanged': {
'ContentChanged': 'Content changed' name: 'Asset changed'
},
'ContentChanged': {
name: 'Content changed'
}
}; };
export const ruleActions: any = { export const ruleActions: any = {
'Algolia': 'Populate Algolia Index', 'Algolia': {
'AzureQueue': 'Send to Azure Queue', name: 'Populate Algolia Index'
'Fastly': 'Purge fastly Cache', },
'Slack': 'Send to Slack', 'AzureQueue': {
'Webhook': 'Send Webhook' name: 'Send to Azure Queue'
},
'Fastly': {
name: 'Purge fastly Cache'
},
'Slack': {
name: 'Send to Slack'
},
'Webhook': {
name: 'Send Webhook'
}
}; };
export class RuleDto { 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 IAppPlansProvider appPlansProvider = A.Fake<IAppPlansProvider>();
private readonly IAppPlanBillingManager appPlansBillingManager = A.Fake<IAppPlanBillingManager>(); private readonly IAppPlanBillingManager appPlansBillingManager = A.Fake<IAppPlanBillingManager>();
private readonly IUserResolver userResolver = A.Fake<IUserResolver>(); 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 Language language = Language.DE;
private readonly string contributorId = Guid.NewGuid().ToString(); private readonly string contributorId = Guid.NewGuid().ToString();
private readonly string clientName = "client"; private readonly string clientName = "client";
@ -47,13 +45,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
A.CallTo(() => userResolver.FindByIdAsync(contributorId)) A.CallTo(() => userResolver.FindByIdAsync(contributorId))
.Returns(A.Fake<IUser>()); .Returns(A.Fake<IUser>());
var templateBuilders = new[] sut = new AppCommandMiddleware(Handler, appProvider, appPlansProvider, appPlansBillingManager, userResolver);
{
templateBuilder1,
templateBuilder2
};
sut = new AppCommandMiddleware(Handler, appProvider, appPlansProvider, appPlansBillingManager, userResolver, templateBuilders);
} }
[Fact] [Fact]
@ -67,29 +59,6 @@ namespace Squidex.Domain.Apps.Entities.Apps
}); });
Assert.Equal(AppId, context.Result<EntityCreatedResult<Guid>>().IdOrValue); 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] [Fact]

Loading…
Cancel
Save