Browse Source

Workflow management started.

pull/382/head
Sebastian Stehle 7 years ago
parent
commit
d903691702
  1. 42
      src/Squidex.Domain.Apps.Entities/Apps/AppGrain.cs
  2. 14
      src/Squidex.Domain.Apps.Entities/Apps/Commands/AddWorkflow.cs
  3. 16
      src/Squidex.Domain.Apps.Entities/Apps/Commands/DeleteWorkflow.cs
  4. 5
      src/Squidex.Domain.Apps.Entities/Apps/Commands/UpdateWorkflow.cs
  5. 13
      src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppWorkflows.cs
  6. 17
      src/Squidex.Domain.Apps.Events/Apps/AppWorkflowAdded.cs
  7. 18
      src/Squidex.Domain.Apps.Events/Apps/AppWorkflowDeleted.cs
  8. 7
      src/Squidex.Domain.Apps.Events/Apps/AppWorkflowUpdated.cs
  9. 4
      src/Squidex/Areas/Api/Controllers/Apps/Models/UpsertWorkflowDto.cs
  10. 2
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppGrainTests.cs
  11. 32
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppWorkflowTests.cs
  12. 29
      tools/Migrate_01/OldEvents/AppWorkflowConfigured.cs

42
src/Squidex.Domain.Apps.Entities/Apps/AppGrain.cs

@ -119,12 +119,32 @@ namespace Squidex.Domain.Apps.Entities.Apps
return Snapshot;
});
case ConfigureWorkflow configureWorkflow:
return UpdateReturn(configureWorkflow, c =>
case AddWorkflow addWorkflow:
return UpdateReturn(addWorkflow, c =>
{
GuardAppWorkflows.CanConfigure(c);
GuardAppWorkflows.CanAdd(c);
ConfigureWorkflow(c);
AddWorkflow(c);
return Snapshot;
});
case UpdateWorkflow updateWorkflow:
return UpdateReturn(updateWorkflow, c =>
{
GuardAppWorkflows.CanUpdate(Snapshot.Workflows, c);
UpdateWorkflow(c);
return Snapshot;
});
case DeleteWorkflow deleteWorkflow:
return UpdateReturn(deleteWorkflow, c =>
{
GuardAppWorkflows.CanDelete(Snapshot.Workflows, c);
DeleteWorkflow(c);
return Snapshot;
});
@ -329,9 +349,19 @@ namespace Squidex.Domain.Apps.Entities.Apps
RaiseEvent(SimpleMapper.Map(command, new AppClientRevoked()));
}
public void ConfigureWorkflow(ConfigureWorkflow command)
public void AddWorkflow(AddWorkflow command)
{
RaiseEvent(SimpleMapper.Map(command, new AppWorkflowAdded()));
}
public void UpdateWorkflow(UpdateWorkflow command)
{
RaiseEvent(SimpleMapper.Map(command, new AppWorkflowUpdated()));
}
public void DeleteWorkflow(DeleteWorkflow command)
{
RaiseEvent(SimpleMapper.Map(command, new AppWorkflowConfigured()));
RaiseEvent(SimpleMapper.Map(command, new AppWorkflowDeleted()));
}
public void AddLanguage(AddLanguage command)

14
src/Squidex.Domain.Apps.Entities/Apps/Commands/AddWorkflow.cs

@ -0,0 +1,14 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
namespace Squidex.Domain.Apps.Entities.Apps.Commands
{
public sealed class AddWorkflow : AppCommand
{
public string Name { get; set; }
}
}

16
src/Squidex.Domain.Apps.Entities/Apps/Commands/DeleteWorkflow.cs

@ -0,0 +1,16 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
namespace Squidex.Domain.Apps.Entities.Apps.Commands
{
public sealed class DeleteWorkflow : AppCommand
{
public Guid WorkflowId { get; set; }
}
}

5
src/Squidex.Domain.Apps.Entities/Apps/Commands/ConfigureWorkflow.cs → src/Squidex.Domain.Apps.Entities/Apps/Commands/UpdateWorkflow.cs

@ -5,12 +5,15 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using Squidex.Domain.Apps.Core.Contents;
namespace Squidex.Domain.Apps.Entities.Apps.Commands
{
public sealed class ConfigureWorkflow : AppCommand
public sealed class UpdateWorkflow : AppCommand
{
public Guid WorkflowId { get; set; }
public Workflow Workflow { get; set; }
}
}

13
src/Squidex.Domain.Apps.Entities/Apps/Guards/GuardAppWorkflows.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Entities.Apps.Commands;
using Squidex.Infrastructure;
@ -13,7 +14,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
{
public static class GuardAppWorkflows
{
public static void CanConfigure(ConfigureWorkflow command)
public static void CanUpdate(Workflows workflows, UpdateWorkflow command)
{
Guard.NotNull(command, nameof(command));
@ -72,5 +73,15 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
}
});
}
internal static void CanAdd(AddWorkflow c)
{
throw new NotImplementedException();
}
internal static void CanDelete(Workflows workflows, DeleteWorkflow c)
{
throw new NotImplementedException();
}
}
}

17
src/Squidex.Domain.Apps.Events/Apps/AppWorkflowAdded.cs

@ -0,0 +1,17 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Squidex.Infrastructure.EventSourcing;
namespace Squidex.Domain.Apps.Events.Apps
{
[EventType(nameof(AppWorkflowAdded))]
public sealed class AppWorkflowAdded : AppEvent
{
public string Name { get; set; }
}
}

18
src/Squidex.Domain.Apps.Events/Apps/AppWorkflowDeleted.cs

@ -0,0 +1,18 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using Squidex.Infrastructure.EventSourcing;
namespace Squidex.Domain.Apps.Events.Apps
{
[EventType(nameof(AppWorkflowDeleted))]
public sealed class AppWorkflowDeleted : AppEvent
{
public Guid WorkflowId { get; set; }
}
}

7
src/Squidex.Domain.Apps.Events/Apps/AppWorkflowConfigured.cs → src/Squidex.Domain.Apps.Events/Apps/AppWorkflowUpdated.cs

@ -5,14 +5,17 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Infrastructure.EventSourcing;
namespace Squidex.Domain.Apps.Events.Apps
{
[EventType(nameof(AppWorkflowConfigured))]
public sealed class AppWorkflowConfigured : AppEvent
[EventType(nameof(AppWorkflowUpdated))]
public sealed class AppWorkflowUpdated : AppEvent
{
public Guid WorkflowId { get; set; }
public Workflow Workflow { get; set; }
}
}

4
src/Squidex/Areas/Api/Controllers/Apps/Models/UpsertWorkflowDto.cs

@ -26,7 +26,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models
/// </summary>
public Status Initial { get; set; }
public ConfigureWorkflow ToCommand()
public UpdateWorkflow ToCommand()
{
var workflow = new Workflow(
Steps?.ToDictionary(
@ -39,7 +39,7 @@ namespace Squidex.Areas.Api.Controllers.Apps.Models
x.Value.NoUpdate)),
Initial);
return new ConfigureWorkflow { Workflow = workflow };
return new UpdateWorkflow { Workflow = workflow };
}
}
}

2
tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppGrainTests.cs

@ -301,7 +301,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
[Fact]
public async Task ConfigureWorkflow_should_create_events_and_update_state()
{
var command = new ConfigureWorkflow { Workflow = Workflow.Default };
var command = new UpdateWorkflow { Workflow = Workflow.Default };
await ExecuteCreateAsync();

32
tests/Squidex.Domain.Apps.Entities.Tests/Apps/Guards/GuardAppWorkflowTests.cs

@ -19,16 +19,16 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
[Fact]
public void CanConfigure_should_throw_exception_if_workflow_is_not_defined()
{
var command = new ConfigureWorkflow();
var command = new UpdateWorkflow();
ValidationAssert.Throws(() => GuardAppWorkflows.CanConfigure(command),
ValidationAssert.Throws(() => GuardAppWorkflows.CanUpdate(command),
new ValidationError("Workflow is required.", "Workflow"));
}
[Fact]
public void CanConfigure_should_throw_exception_if_workflow_has_no_initial_step()
{
var command = new ConfigureWorkflow
var command = new UpdateWorkflow
{
Workflow = new Workflow(
new Dictionary<Status, WorkflowStep>
@ -38,14 +38,14 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
default)
};
ValidationAssert.Throws(() => GuardAppWorkflows.CanConfigure(command),
ValidationAssert.Throws(() => GuardAppWorkflows.CanUpdate(command),
new ValidationError("Initial step is required.", "Workflow.Initial"));
}
[Fact]
public void CanConfigure_should_throw_exception_if_initial_step_is_published()
{
var command = new ConfigureWorkflow
var command = new UpdateWorkflow
{
Workflow = new Workflow(
new Dictionary<Status, WorkflowStep>
@ -55,14 +55,14 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
Status.Published)
};
ValidationAssert.Throws(() => GuardAppWorkflows.CanConfigure(command),
ValidationAssert.Throws(() => GuardAppWorkflows.CanUpdate(command),
new ValidationError("Initial step cannot be published step.", "Workflow.Initial"));
}
[Fact]
public void CanConfigure_should_throw_exception_if_workflow_does_not_have_published_state()
{
var command = new ConfigureWorkflow
var command = new UpdateWorkflow
{
Workflow = new Workflow(
new Dictionary<Status, WorkflowStep>
@ -72,14 +72,14 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
Status.Draft)
};
ValidationAssert.Throws(() => GuardAppWorkflows.CanConfigure(command),
ValidationAssert.Throws(() => GuardAppWorkflows.CanUpdate(command),
new ValidationError("Workflow must have a published step.", "Workflow.Steps"));
}
[Fact]
public void CanConfigure_should_throw_exception_if_workflow_step_is_not_defined()
{
var command = new ConfigureWorkflow
var command = new UpdateWorkflow
{
Workflow = new Workflow(
new Dictionary<Status, WorkflowStep>
@ -90,14 +90,14 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
Status.Draft)
};
ValidationAssert.Throws(() => GuardAppWorkflows.CanConfigure(command),
ValidationAssert.Throws(() => GuardAppWorkflows.CanUpdate(command),
new ValidationError("Step is required.", "Workflow.Steps.Published"));
}
[Fact]
public void CanConfigure_should_throw_exception_if_workflow_transition_is_invalid()
{
var command = new ConfigureWorkflow
var command = new UpdateWorkflow
{
Workflow = new Workflow(
new Dictionary<Status, WorkflowStep>
@ -113,14 +113,14 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
Status.Draft)
};
ValidationAssert.Throws(() => GuardAppWorkflows.CanConfigure(command),
ValidationAssert.Throws(() => GuardAppWorkflows.CanUpdate(command),
new ValidationError("Transition has an invalid target.", "Workflow.Steps.Published.Transitions.Archived"));
}
[Fact]
public void CanConfigure_should_throw_exception_if_workflow_transition_is_not_defined()
{
var command = new ConfigureWorkflow
var command = new UpdateWorkflow
{
Workflow = new Workflow(
new Dictionary<Status, WorkflowStep>
@ -137,16 +137,16 @@ namespace Squidex.Domain.Apps.Entities.Apps.Guards
Status.Draft)
};
ValidationAssert.Throws(() => GuardAppWorkflows.CanConfigure(command),
ValidationAssert.Throws(() => GuardAppWorkflows.CanUpdate(command),
new ValidationError("Transition is required.", "Workflow.Steps.Published.Transitions.Draft"));
}
[Fact]
public void CanConfigure_should_not_throw_exception_if_workflow_is_valid()
{
var command = new ConfigureWorkflow { Workflow = Workflow.Default };
var command = new UpdateWorkflow { Workflow = Workflow.Default };
GuardAppWorkflows.CanConfigure(command);
GuardAppWorkflows.CanUpdate(command);
}
}
}

29
tools/Migrate_01/OldEvents/AppWorkflowConfigured.cs

@ -0,0 +1,29 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Events;
using Squidex.Domain.Apps.Events.Apps;
using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing;
using Squidex.Infrastructure.Reflection;
namespace Migrate_01.OldEvents
{
[EventType(nameof(AppWorkflowConfigured))]
[Obsolete]
public sealed class AppWorkflowConfigured : AppEvent, IMigrated<IEvent>
{
public Workflow Workflow { get; set; }
public IEvent Migrate()
{
return SimpleMapper.Map(this, new AppWorkflowUpdated());
}
}
}
Loading…
Cancel
Save