Browse Source

Restructuring

pull/1/head
Sebastian Stehle 10 years ago
parent
commit
fcfd97b3b5
  1. 1
      src/PinkParrot/Startup.cs
  2. 109
      src/pinkparrot_core/PinkParrot.Core/Schema/ModelField.cs
  3. 31
      src/pinkparrot_core/PinkParrot.Core/Schema/ModelFieldFactory.cs
  4. 39
      src/pinkparrot_core/PinkParrot.Core/Schema/ModelFieldProperties.cs
  5. 71
      src/pinkparrot_core/PinkParrot.Core/Schema/ModelField_Generic.cs
  6. 55
      src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchema.cs
  7. 81
      src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchemaMetadata.cs
  8. 20
      src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchemaProperties.cs
  9. 59
      src/pinkparrot_core/PinkParrot.Core/Schema/NamedElementProperties.cs
  10. 30
      src/pinkparrot_core/PinkParrot.Core/Schema/NumberField.cs
  11. 42
      src/pinkparrot_core/PinkParrot.Core/Schema/NumberFieldProperties.cs
  12. 6
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldAdded.cs
  13. 1
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDeleted.cs
  14. 1
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDisabled.cs
  15. 1
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldEnabled.cs
  16. 1
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldHidden.cs
  17. 1
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldShown.cs
  18. 4
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldUpdated.cs
  19. 4
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaCreated.cs
  20. 1
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaDeleted.cs
  21. 6
      src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaUpdated.cs
  22. 1
      src/pinkparrot_events/PinkParrot.Events/project.json
  23. 2
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/CollectionExtensionsTests.cs
  24. 1
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/DispatchingTests.cs
  25. 2
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/EnumExtensionsTests.cs
  26. 8
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandContext.cs
  27. 1
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/ICommand.cs
  28. 1
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Events/IEventConsumer.cs
  29. 12
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/GetEventStore/GetEventStoreDomainObjectRepository.cs
  30. 4
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionContextDispatcher.cs
  31. 2
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionContextDispatcherFactory.cs
  32. 2
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionDispatcher.cs
  33. 2
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionDispatcherFactory.cs
  34. 4
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncContextDispatcher.cs
  35. 2
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncContextDispatcherFactory.cs
  36. 2
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncDispatcher.cs
  37. 2
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncDispatcherFactory.cs
  38. 25
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/DomainException.cs
  39. 2
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Json/PropertiesBagConverter.cs
  40. 71
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Json/TypeNameSerializationBinder.cs
  41. 17
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/TypeNameAttribute.cs
  42. 38
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ValidationError.cs
  43. 21
      src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ValidationException.cs
  44. 13
      src/pinkparrot_read/PinkParrot.Read/Models/ModelSchemaRM.cs
  45. 1
      src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/MongoDbModelSchemaRepository.cs
  46. 12
      src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/Utils/BaseRepository.cs
  47. 5
      src/pinkparrot_write/PinkParrot.Write/Schema/Commands/AddModelField.cs
  48. 3
      src/pinkparrot_write/PinkParrot.Write/Schema/Commands/CreateModelSchema.cs
  49. 4
      src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelField.cs
  50. 6
      src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelSchema.cs
  51. 24
      src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaDomainObject.cs
  52. 70
      src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaNameMap.cs

1
src/PinkParrot/Startup.cs

@ -16,6 +16,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using PinkParrot.Infrastructure.CQRS.Autofac; using PinkParrot.Infrastructure.CQRS.Autofac;
using PinkParrot.Infrastructure.CQRS.Commands; using PinkParrot.Infrastructure.CQRS.Commands;
// ReSharper disable AccessToModifiedClosure // ReSharper disable AccessToModifiedClosure
namespace PinkParrot namespace PinkParrot

109
src/pinkparrot_core/PinkParrot.Core/Schema/ModelField.cs

@ -6,6 +6,7 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using PinkParrot.Infrastructure; using PinkParrot.Infrastructure;
@ -18,10 +19,6 @@ namespace PinkParrot.Core.Schema
public abstract class ModelField public abstract class ModelField
{ {
private readonly long id; private readonly long id;
private string name;
private string hint;
private string displayName;
private bool isRequired;
private bool isDisabled; private bool isDisabled;
private bool isHidden; private bool isHidden;
@ -30,25 +27,15 @@ namespace PinkParrot.Core.Schema
get { return id; } get { return id; }
} }
public string Name public abstract ModelFieldProperties RawProperties { get; }
{
get { return name; }
}
public string Hint public abstract string Name { get; }
{
get { return hint; }
}
public string DisplayName public abstract string Label { get; }
{
get { return displayName; }
}
public bool IsRequired public abstract string Hints { get; }
{
get { return isRequired; } public abstract bool IsRequired { get; }
}
public bool IsHidden public bool IsHidden
{ {
@ -60,61 +47,22 @@ namespace PinkParrot.Core.Schema
get { return isDisabled; } get { return isDisabled; }
} }
protected ModelField(long id, string name) protected ModelField(long id)
{ {
Guard.GreaterThan(id, 0, nameof(id)); Guard.GreaterThan(id, 0, nameof(id));
Guard.ValidSlug(name, nameof(name));
this.id = id; this.id = id;
this.name = name;
} }
public ModelField Configure(dynamic settings, ICollection<string> errors) public abstract ModelField Configure(ModelFieldProperties newProperties, IList<ValidationError> errors);
{
var clone = Clone();
if (settings.Contains("Name"))
{
clone.name = settings.Name;
if (!clone.name.IsSlug())
{
errors.Add("Field name must be a slug");
}
}
if (settings.Contains("hint"))
{
clone.hint = settings.Hint?.Trim();
}
if (settings.Contains("displayName"))
{
clone.displayName = settings.DisplayName?.Trim();
}
if (settings.Contains("IsRequired"))
{
clone.isRequired = settings.IsRequired;
}
clone.ConfigureCore(settings, errors);
return clone;
}
protected virtual void ConfigureCore(dynamic settings, ICollection<string> errors)
{
}
public Task ValidateAsync(PropertyValue property, ICollection<string> errors) public Task ValidateAsync(PropertyValue property, ICollection<string> errors)
{ {
Guard.NotNull(property, nameof(property)); Guard.NotNull(property, nameof(property));
if (isRequired && property.RawValue == null) if (IsRequired && property.RawValue == null)
{ {
errors.Add("<Field> is required"); errors.Add("Field is required");
} }
if (property.RawValue == null) if (property.RawValue == null)
@ -134,54 +82,47 @@ namespace PinkParrot.Core.Schema
{ {
if (isHidden) if (isHidden)
{ {
throw new ValidationException($"The field '{name} is already hidden."); throw new DomainException($"The field '{Name} is already hidden.");
} }
var clone = Clone(); return Update<ModelField>(clone => clone.isHidden = true);
clone.isHidden = true;
return Clone();
} }
public ModelField Show() public ModelField Show()
{ {
if (!isHidden) if (!isHidden)
{ {
throw new ValidationException($"The field '{name} is already visible."); throw new DomainException($"The field '{Name} is already visible.");
} }
var clone = Clone(); return Update<ModelField>(clone => clone.isHidden = false);
clone.isHidden = false;
return Clone();
} }
public ModelField Disable() public ModelField Disable()
{ {
if (isDisabled) if (isDisabled)
{ {
throw new ValidationException($"The field '{name} is already disabled."); throw new DomainException($"The field '{Name} is already disabled.");
} }
var clone = Clone(); return Update<ModelField>(clone => clone.isDisabled = true);
clone.isDisabled = true;
return clone;
} }
public ModelField Enable() public ModelField Enable()
{ {
if (!isDisabled) if (!isDisabled)
{ {
throw new ValidationException($"The field '{name} is already enabled."); throw new DomainException($"The field '{Name} is already enabled.");
} }
return Update<ModelField>(clone => clone.isDisabled = false);
}
var clone = Clone(); protected T Update<T>(Action<T> updater) where T : ModelField
{
var clone = (T)Clone();
clone.isDisabled = false; updater(clone);
return clone; return clone;
} }

31
src/pinkparrot_core/PinkParrot.Core/Schema/ModelFieldFactory.cs

@ -6,13 +6,40 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System;
using System.Collections.Generic;
using PinkParrot.Infrastructure;
namespace PinkParrot.Core.Schema namespace PinkParrot.Core.Schema
{ {
public class ModelFieldFactory public class ModelFieldFactory
{ {
public virtual ModelField CreateField(long id, string type, string fieldName) private readonly Dictionary<Type, Func<long, ModelField>> factories = new Dictionary<Type, Func<long, ModelField>>();
public ModelFieldFactory()
{
AddFactory<NumberFieldProperties>(id => new NumberField(id));
}
public void AddFactory<T>(Func<long, ModelField> factory) where T : ModelFieldProperties
{
Guard.NotNull(factory, nameof(factory));
factories[typeof(T)] = factory;
}
public virtual ModelField CreateField(long id, ModelFieldProperties properties)
{ {
return new NumberField(id, fieldName); Guard.NotNull(properties, nameof(properties));
var factory = factories.GetOrDefault(properties.GetType());
if (factory == null)
{
throw new InvalidOperationException("Field type is not supported.");
}
return factory(id);
} }
} }
} }

39
src/pinkparrot_core/PinkParrot.Core/Schema/ModelFieldProperties.cs

@ -0,0 +1,39 @@
// ==========================================================================
// ModelFieldProperties.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using PinkParrot.Infrastructure;
namespace PinkParrot.Core.Schema
{
public abstract class ModelFieldProperties : NamedElementProperties
{
public bool IsRequired { get; }
protected ModelFieldProperties(
bool isRequired,
string name,
string label,
string hints)
: base(name, label, hints)
{
IsRequired = isRequired;
}
public override void Validate(IList<ValidationError> errors)
{
base.Validate(errors);
ValidateCore(errors);
}
protected virtual void ValidateCore(IList<ValidationError> errors)
{
}
}
}

71
src/pinkparrot_core/PinkParrot.Core/Schema/ModelField_Generic.cs

@ -0,0 +1,71 @@
// ==========================================================================
// ModelField_Generic.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using PinkParrot.Infrastructure;
namespace PinkParrot.Core.Schema
{
public abstract class ModelField<T> : ModelField where T : ModelFieldProperties
{
private T properties;
public override ModelFieldProperties RawProperties
{
get { return properties; }
}
public override string Name
{
get { return properties.Name; }
}
public override string Label
{
get { return properties.Label; }
}
public override string Hints
{
get { return properties.Hints; }
}
public override bool IsRequired
{
get { return properties.IsRequired; }
}
public T Properties
{
get { return properties; }
}
protected ModelField(long id)
: base(id)
{
}
public override ModelField Configure(ModelFieldProperties newProperties, IList<ValidationError> errors)
{
Guard.NotNull(newProperties, nameof(newProperties));
Guard.NotNull(errors, nameof(errors));
var typedProperties = newProperties as T;
if (typedProperties == null)
{
throw new ArgumentException($"Properties must be of type '{typeof(T)}", nameof(newProperties));
}
newProperties.Validate(errors);
return Update<ModelField<T>>(clone => clone.properties = typedProperties);
}
}
}

55
src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchema.cs

@ -17,30 +17,34 @@ namespace PinkParrot.Core.Schema
{ {
public sealed class ModelSchema public sealed class ModelSchema
{ {
private readonly ModelSchemaMetadata metadata; private readonly ModelSchemaProperties properties;
private readonly ImmutableDictionary<long, ModelField> fields; private readonly ImmutableDictionary<long, ModelField> fields;
private readonly Dictionary<string, ModelField> fieldsByName; private readonly Dictionary<string, ModelField> fieldsByName;
public ModelSchema(ModelSchemaMetadata metadata, ImmutableDictionary<long, ModelField> fields) public ModelSchema(ModelSchemaProperties properties, ImmutableDictionary<long, ModelField> fields)
{ {
Guard.NotNull(fields, nameof(fields)); Guard.NotNull(fields, nameof(fields));
Guard.NotNull(metadata, nameof(metadata)); Guard.NotNull(properties, nameof(properties));
this.fields = fields; this.fields = fields;
this.metadata = metadata; this.properties = properties;
fieldsByName = fields.Values.ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase); fieldsByName = fields.Values.ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase);
} }
public static ModelSchema Create(string name) public static ModelSchema Create(ModelSchemaProperties metadata)
{ {
if (!name.IsSlug()) var errors = new List<ValidationError>();
metadata.Validate(errors);
if (errors.Any())
{ {
throw new ValidationException("Cannot create the schema.", $"'{name}' is not a valid slug."); throw new ValidationException("Failed to create a new model schema.", errors);
} }
return new ModelSchema(new ModelSchemaMetadata(name), ImmutableDictionary<long, ModelField>.Empty); return new ModelSchema(metadata, ImmutableDictionary<long, ModelField>.Empty);
} }
public IReadOnlyDictionary<long, ModelField> Fields public IReadOnlyDictionary<long, ModelField> Fields
@ -48,34 +52,34 @@ namespace PinkParrot.Core.Schema
get { return fields; } get { return fields; }
} }
public ModelSchemaMetadata Metadata public ModelSchemaProperties Properties
{ {
get { return metadata; } get { return properties; }
} }
public ModelSchema Update(ModelSchemaMetadata newMetadata) public ModelSchema Update(ModelSchemaProperties newMetadata)
{ {
Guard.NotNull(newMetadata, nameof(newMetadata)); Guard.NotNull(newMetadata, nameof(newMetadata));
return new ModelSchema(newMetadata, fields); return new ModelSchema(newMetadata, fields);
} }
public ModelSchema AddField(long id, string type, string fieldName, ModelFieldFactory factory) public ModelSchema AddField(long id, ModelFieldProperties properties, ModelFieldFactory factory)
{ {
var field = factory.CreateField(id, type, fieldName); var field = factory.CreateField(id, properties);
return SetField(field); return SetField(field);
} }
public ModelSchema SetField(long fieldId, PropertiesBag settings) public ModelSchema SetField(long fieldId, ModelFieldProperties properties)
{ {
Guard.NotNull(settings, nameof(settings)); Guard.NotNull(properties, nameof(properties));
return UpdateField(fieldId, field => return UpdateField(fieldId, field =>
{ {
var errors = new List<string>(); var errors = new List<ValidationError>();
var newField = field.Configure(settings, errors); var newField = field.Configure(properties, errors);
if (errors.Any()) if (errors.Any())
{ {
@ -115,7 +119,7 @@ namespace PinkParrot.Core.Schema
throw new ValidationException($"A field with name '{field.Name}' already exists."); throw new ValidationException($"A field with name '{field.Name}' already exists.");
} }
return new ModelSchema(metadata, fields.SetItem(field.Id, field)); return new ModelSchema(properties, fields.SetItem(field.Id, field));
} }
public ModelSchema DeleteField(long fieldId) public ModelSchema DeleteField(long fieldId)
@ -125,7 +129,7 @@ namespace PinkParrot.Core.Schema
throw new ValidationException($"A field with id {fieldId} does not exist."); throw new ValidationException($"A field with id {fieldId} does not exist.");
} }
return new ModelSchema(metadata, fields.Remove(fieldId)); return new ModelSchema(properties, fields.Remove(fieldId));
} }
private ModelSchema UpdateField(long fieldId, Func<ModelField, ModelField> updater) private ModelSchema UpdateField(long fieldId, Func<ModelField, ModelField> updater)
@ -134,7 +138,8 @@ namespace PinkParrot.Core.Schema
if (!fields.TryGetValue(fieldId, out field)) if (!fields.TryGetValue(fieldId, out field))
{ {
throw new ValidationException($"Cannot update field with id '{fieldId}'.", "Field does not exist."); throw new ValidationException($"Cannot update field with id '{fieldId}'.",
new ValidationError("Field does not exist.", "fieldId"));
} }
var newField = updater(field); var newField = updater(field);
@ -146,10 +151,12 @@ namespace PinkParrot.Core.Schema
{ {
Guard.NotNull(data, nameof(data)); Guard.NotNull(data, nameof(data));
var errors = new List<string>(); var errors = new List<ValidationError>();
foreach (var kvp in data.Properties) foreach (var kvp in data.Properties)
{ {
var fieldErrors = new List<string>();
ModelField field; ModelField field;
if (fieldsByName.TryGetValue(kvp.Key, out field)) if (fieldsByName.TryGetValue(kvp.Key, out field))
@ -157,13 +164,13 @@ namespace PinkParrot.Core.Schema
var newErrors = new List<string>(); var newErrors = new List<string>();
await field.ValidateAsync(kvp.Value, newErrors); await field.ValidateAsync(kvp.Value, newErrors);
errors.AddRange(newErrors.Select(e => e.Replace("<Field>", "'" + field.Name + "'")));
} }
else else
{ {
errors.Add($"'{kvp.Key}' is not a known field"); fieldErrors.Add($"'{kvp.Key}' is not a known field");
} }
errors.AddRange(fieldErrors.Select(x => new ValidationError(x, kvp.Key)));
} }
if (errors.Any()) if (errors.Any())

81
src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchemaMetadata.cs

@ -1,81 +0,0 @@
// ==========================================================================
// ModelSchemaMetadata.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using PinkParrot.Infrastructure;
namespace PinkParrot.Core.Schema
{
public sealed class ModelSchemaMetadata
{
private string name;
private string displayName;
private string hint;
private string itemTitle;
public string Name
{
get { return name; }
}
public string DisplayName
{
get { return displayName; }
}
public string Hint
{
get { return hint; }
}
public string ItemTitle
{
get { return itemTitle; }
}
public ModelSchemaMetadata(string name)
{
Guard.ValidSlug(name, nameof(name));
this.name = name;
}
public ModelSchemaMetadata Configure(string newName, PropertiesBag properties)
{
Guard.NotNull(properties, nameof(properties));
var clone = (ModelSchemaMetadata) MemberwiseClone();
if (newName != null)
{
if (!newName.IsSlug())
{
throw new ValidationException("Cannot update the schema.", $"'{newName}' is not a valid slug.");
}
clone.name = newName;
}
if (properties.Contains("Hint"))
{
clone.hint = properties["Hint"].ToString()?.Trim();
}
if (properties.Contains("DisplayName"))
{
clone.displayName = properties["DisplayName"].ToString()?.Trim();
}
if (properties.Contains("ItemTitle"))
{
clone.itemTitle = properties["ItemTitle"].ToString()?.Trim();
}
return clone;
}
}
}

20
src/pinkparrot_core/PinkParrot.Core/Schema/ModelSchemaProperties.cs

@ -0,0 +1,20 @@
// ==========================================================================
// ModelSchemaMetadata.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
namespace PinkParrot.Core.Schema
{
public sealed class ModelSchemaProperties : NamedElementProperties
{
public ModelSchemaProperties(
string name,
string label,
string hints)
: base(name, label, hints)
{
}
}
}

59
src/pinkparrot_core/PinkParrot.Core/Schema/NamedElementProperties.cs

@ -0,0 +1,59 @@
// ==========================================================================
// NamedElementProperties.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using PinkParrot.Infrastructure;
namespace PinkParrot.Core.Schema
{
public abstract class NamedElementProperties
{
private readonly string name;
private readonly string label;
private readonly string hints;
public string Name
{
get { return name; }
}
public string Label
{
get { return string.IsNullOrWhiteSpace(label) ? name : label; }
}
public string Hints
{
get { return hints; }
}
protected NamedElementProperties(
string name,
string label,
string hints)
{
this.name = name;
this.label = label;
this.hints = hints;
}
public virtual void Validate(IList<ValidationError> errors)
{
Guard.NotNull(errors, nameof(errors));
if (string.IsNullOrWhiteSpace(Name))
{
errors.Add(new ValidationError("Name cannot be empty.", "Name"));
}
else if (!Name.IsSlug())
{
errors.Add(new ValidationError("Name must be a valid slug.", "Name"));
}
}
}
}

30
src/pinkparrot_core/PinkParrot.Core/Schema/NumberField.cs

@ -15,35 +15,21 @@ using PinkParrot.Infrastructure.Tasks;
namespace PinkParrot.Core.Schema namespace PinkParrot.Core.Schema
{ {
public sealed class NumberField : ModelField public sealed class NumberField : ModelField<NumberFieldProperties>
{ {
private double? maxValue;
private double? minValue;
public double? MaxValue public double? MaxValue
{ {
get { return maxValue; } get { return Properties.MaxValue; }
} }
public double? MinValue public double? MinValue
{ {
get { return minValue; } get { return Properties.MinValue; }
}
public NumberField(long id, string name)
: base(id, name)
{
} }
protected override void ConfigureCore(dynamic settings, ICollection<string> errors) public NumberField(long id)
: base(id)
{ {
maxValue = settings.MaxValue;
minValue = settings.MinValue;
if (maxValue.HasValue && minValue.HasValue && minValue.Value > maxValue.Value)
{
errors.Add("MinValue cannot be larger than max value");
}
} }
protected override Task ValidateCoreAsync(PropertyValue property, ICollection<string> errors) protected override Task ValidateCoreAsync(PropertyValue property, ICollection<string> errors)
@ -54,17 +40,17 @@ namespace PinkParrot.Core.Schema
if (MinValue.HasValue && value < MinValue.Value) if (MinValue.HasValue && value < MinValue.Value)
{ {
errors.Add($"<Field> must be greater than {MinValue}"); errors.Add($"Must be greater than {MinValue}");
} }
if (MaxValue.HasValue && value > MaxValue.Value) if (MaxValue.HasValue && value > MaxValue.Value)
{ {
errors.Add($"<Field> must be less than {MaxValue}"); errors.Add($"Must be less than {MaxValue}");
} }
} }
catch (InvalidCastException) catch (InvalidCastException)
{ {
errors.Add("<Field> is not a valid number"); errors.Add("Value is not a valid number");
} }
return TaskHelper.Done; return TaskHelper.Done;

42
src/pinkparrot_core/PinkParrot.Core/Schema/NumberFieldProperties.cs

@ -0,0 +1,42 @@
// ==========================================================================
// NumberFieldProperties.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
using PinkParrot.Infrastructure;
namespace PinkParrot.Core.Schema
{
[TypeName("Number")]
public sealed class NumberFieldProperties : ModelFieldProperties
{
public double? MaxValue { get; }
public double? MinValue { get; }
public NumberFieldProperties(
bool isRequired,
string name,
string label,
string hints,
double? minValue,
double? maxValue)
: base(isRequired, name, label, hints)
{
MinValue = minValue;
MaxValue = maxValue;
}
protected override void ValidateCore(IList<ValidationError> errors)
{
if (MaxValue.HasValue && MinValue.HasValue && MinValue.Value > MaxValue.Value)
{
errors.Add(new ValidationError("MinValue cannot be larger than max value", "MinValue", "MaxValue"));
}
}
}
}

6
src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldAdded.cs

@ -6,14 +6,14 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using PinkParrot.Core.Schema;
namespace PinkParrot.Events.Schema namespace PinkParrot.Events.Schema
{ {
public class ModelFieldAdded : TenantEvent public class ModelFieldAdded : TenantEvent
{ {
public long FieldId; public long FieldId;
public string FieldType; public ModelFieldProperties Properties;
public string FieldName;
} }
} }

1
src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDeleted.cs

@ -5,7 +5,6 @@
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
namespace PinkParrot.Events.Schema namespace PinkParrot.Events.Schema
{ {
public class ModelFieldDeleted : TenantEvent public class ModelFieldDeleted : TenantEvent

1
src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldDisabled.cs

@ -5,7 +5,6 @@
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
namespace PinkParrot.Events.Schema namespace PinkParrot.Events.Schema
{ {
public class ModelFieldDisabled : TenantEvent public class ModelFieldDisabled : TenantEvent

1
src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldEnabled.cs

@ -5,7 +5,6 @@
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
namespace PinkParrot.Events.Schema namespace PinkParrot.Events.Schema
{ {
public class ModelFieldEnabled : TenantEvent public class ModelFieldEnabled : TenantEvent

1
src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldHidden.cs

@ -5,7 +5,6 @@
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
namespace PinkParrot.Events.Schema namespace PinkParrot.Events.Schema
{ {
public class ModelFieldHidden : TenantEvent public class ModelFieldHidden : TenantEvent

1
src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldShown.cs

@ -5,7 +5,6 @@
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
namespace PinkParrot.Events.Schema namespace PinkParrot.Events.Schema
{ {
public class ModelFieldShown : TenantEvent public class ModelFieldShown : TenantEvent

4
src/pinkparrot_events/PinkParrot.Events/Schema/ModelFieldUpdated.cs

@ -6,7 +6,7 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using PinkParrot.Infrastructure; using PinkParrot.Core.Schema;
namespace PinkParrot.Events.Schema namespace PinkParrot.Events.Schema
{ {
@ -14,6 +14,6 @@ namespace PinkParrot.Events.Schema
{ {
public long FieldId; public long FieldId;
public PropertiesBag Settings { get; set; } public ModelFieldProperties Properties;
} }
} }

4
src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaCreated.cs

@ -6,10 +6,12 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using PinkParrot.Core.Schema;
namespace PinkParrot.Events.Schema namespace PinkParrot.Events.Schema
{ {
public class ModelSchemaCreated : TenantEvent public class ModelSchemaCreated : TenantEvent
{ {
public string Name; public ModelSchemaProperties Properties;
} }
} }

1
src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaDeleted.cs

@ -5,7 +5,6 @@
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
namespace PinkParrot.Events.Schema namespace PinkParrot.Events.Schema
{ {
public class ModelSchemaDeleted : TenantEvent public class ModelSchemaDeleted : TenantEvent

6
src/pinkparrot_events/PinkParrot.Events/Schema/ModelSchemaUpdated.cs

@ -6,14 +6,12 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using PinkParrot.Infrastructure; using PinkParrot.Core.Schema;
namespace PinkParrot.Events.Schema namespace PinkParrot.Events.Schema
{ {
public class ModelSchemaUpdated : TenantEvent public class ModelSchemaUpdated : TenantEvent
{ {
public string NewName; public ModelSchemaProperties Properties;
public PropertiesBag Settings { get; set; }
} }
} }

1
src/pinkparrot_events/PinkParrot.Events/project.json

@ -4,6 +4,7 @@
"dependencies": { "dependencies": {
"NETStandard.Library": "1.6.0", "NETStandard.Library": "1.6.0",
"NodaTime": "2.0.0-alpha20160729", "NodaTime": "2.0.0-alpha20160729",
"PinkParrot.Core": "1.0.0-*",
"PinkParrot.Infrastructure": "1.0.0-*" "PinkParrot.Infrastructure": "1.0.0-*"
}, },

2
src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/CollectionExtensionsTests.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// CollectionExtensionsTest.cs // CollectionExtensionsTests.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group

1
src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/DispatchingTests.cs

@ -10,6 +10,7 @@ using System.Threading.Tasks;
using PinkParrot.Infrastructure.Dispatching; using PinkParrot.Infrastructure.Dispatching;
using PinkParrot.Infrastructure.Tasks; using PinkParrot.Infrastructure.Tasks;
using Xunit; using Xunit;
// ReSharper disable UnusedMethodReturnValue.Local // ReSharper disable UnusedMethodReturnValue.Local
// ReSharper disable UnusedParameter.Local // ReSharper disable UnusedParameter.Local
// ReSharper disable UnusedMember.Local // ReSharper disable UnusedMember.Local

2
src/pinkparrot_infrastructure/PinkParrot.Infrastructure.Tests/EnumExtensionsTests.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// EnumExtensionsTest.cs // EnumExtensionsTests.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group

8
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/CommandContext.cs

@ -1,9 +1,9 @@
// ========================================================================== // ==========================================================================
// CommandContext.cs // CommandContext.cs
// Green Parrot Framework // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Sebastian Stehle // Copyright (c) PinkParrot Group
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System; using System;

1
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Commands/ICommand.cs

@ -5,7 +5,6 @@
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
namespace PinkParrot.Infrastructure.CQRS.Commands namespace PinkParrot.Infrastructure.CQRS.Commands
{ {
public interface ICommand public interface ICommand

1
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/Events/IEventConsumer.cs

@ -5,7 +5,6 @@
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
namespace PinkParrot.Infrastructure.CQRS.Events namespace PinkParrot.Infrastructure.CQRS.Events
{ {
public interface IEventConsumer public interface IEventConsumer

12
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/CQRS/GetEventStore/GetEventStoreDomainObjectRepository.cs

@ -1,8 +1,10 @@
using System; // ==========================================================================
using System.Collections.Generic; // GetEventStoreDomainObjectRepository.cs
using System.Linq; // PinkParrot Headless CMS
using System.Threading.Tasks; // ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
namespace PinkParrot.Infrastructure.CQRS.GetEventStore namespace PinkParrot.Infrastructure.CQRS.GetEventStore
{ {
public class GetEventStoreDomainObjectRepository public class GetEventStoreDomainObjectRepository

4
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionContextDispatcher.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// ActionDispatcher.cs // ActionContextDispatcher.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
@ -25,7 +25,7 @@ namespace PinkParrot.Infrastructure.Dispatching
.Where(Helper.HasRightName) .Where(Helper.HasRightName)
.Where(Helper.HasRightParameters<TIn, TContext>) .Where(Helper.HasRightParameters<TIn, TContext>)
.Select(ActionContextDispatcherFactory.CreateActionHandler<TTarget, TContext>) .Select(ActionContextDispatcherFactory.CreateActionHandler<TTarget, TContext>)
.ToDictionary(h => h.Item1, h => h.Item2); .ToDictionary<Tuple<Type, Action<TTarget, object, TContext>>, Type, Action<TTarget, object, TContext>>(h => h.Item1, h => h.Item2);
} }
public static bool Dispatch(TTarget target, TIn input, TContext context) public static bool Dispatch(TTarget target, TIn input, TContext context)

2
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionContextDispatcherFactory.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// ActionHandlerFactory.cs // ActionContextDispatcherFactory.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group

2
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionDispatcher.cs

@ -25,7 +25,7 @@ namespace PinkParrot.Infrastructure.Dispatching
.Where(Helper.HasRightName) .Where(Helper.HasRightName)
.Where(Helper.HasRightParameters<TIn>) .Where(Helper.HasRightParameters<TIn>)
.Select(ActionDispatcherFactory.CreateActionHandler<TTarget>) .Select(ActionDispatcherFactory.CreateActionHandler<TTarget>)
.ToDictionary(h => h.Item1, h => h.Item2); .ToDictionary<Tuple<Type, Action<TTarget, object>>, Type, Action<TTarget, object>>(h => h.Item1, h => h.Item2);
} }
public static bool Dispatch(TTarget target, TIn item) public static bool Dispatch(TTarget target, TIn item)

2
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/ActionDispatcherFactory.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// ActionHandlerFactory.cs // ActionDispatcherFactory.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group

4
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncContextDispatcher.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// FuncDispatcher.cs // FuncContextDispatcher.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
@ -26,7 +26,7 @@ namespace PinkParrot.Infrastructure.Dispatching
.Where(Helper.HasRightParameters<TIn, TContext>) .Where(Helper.HasRightParameters<TIn, TContext>)
.Where(Helper.HasRightReturnType<TOut>) .Where(Helper.HasRightReturnType<TOut>)
.Select(FuncContextDispatcherFactory.CreateFuncHandler<TTarget, TContext, TOut >) .Select(FuncContextDispatcherFactory.CreateFuncHandler<TTarget, TContext, TOut >)
.ToDictionary(h => h.Item1, h => h.Item2); .ToDictionary<Tuple<Type, Func<TTarget, object, TContext, TOut>>, Type, Func<TTarget, object, TContext, TOut>>(h => h.Item1, h => h.Item2);
} }
public static TOut Dispatch(TTarget target, TIn item, TContext context) public static TOut Dispatch(TTarget target, TIn item, TContext context)

2
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncContextDispatcherFactory.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// HandlerFactory.cs // FuncContextDispatcherFactory.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group

2
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncDispatcher.cs

@ -26,7 +26,7 @@ namespace PinkParrot.Infrastructure.Dispatching
.Where(Helper.HasRightParameters<TIn>) .Where(Helper.HasRightParameters<TIn>)
.Where(Helper.HasRightReturnType<TOut>) .Where(Helper.HasRightReturnType<TOut>)
.Select(FuncDispatcherFactory.CreateFuncHandler<TTarget, TOut>) .Select(FuncDispatcherFactory.CreateFuncHandler<TTarget, TOut>)
.ToDictionary(h => h.Item1, h => h.Item2); .ToDictionary<Tuple<Type, Func<TTarget, object, TOut>>, Type, Func<TTarget, object, TOut>>(h => h.Item1, h => h.Item2);
} }
public static TOut Dispatch(TTarget target, TIn item) public static TOut Dispatch(TTarget target, TIn item)

2
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Dispatching/FuncDispatcherFactory.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// HandlerFactory.cs // FuncDispatcherFactory.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group

25
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/DomainException.cs

@ -0,0 +1,25 @@
// ==========================================================================
// DomainException.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System;
namespace PinkParrot.Infrastructure
{
public class DomainException : Exception
{
public DomainException(string message)
: base(message)
{
}
public DomainException(string message, Exception inner)
: base(message, inner)
{
}
}
}

2
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Json/JsonPropertiesBagConverter.cs → src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Json/PropertiesBagConverter.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// JsonPropertiesBagConverter.cs // PropertiesBagConverter.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group

71
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/Json/TypeNameSerializationBinder.cs

@ -0,0 +1,71 @@
// ==========================================================================
// TypeNameSerializationBinder.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Reflection;
using Newtonsoft.Json.Serialization;
namespace PinkParrot.Infrastructure.Json
{
public class TypeNameSerializationBinder : DefaultSerializationBinder
{
private readonly Dictionary<Type, string> namesByType = new Dictionary<Type, string>();
private readonly Dictionary<string, Type> typesByName = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
public TypeNameSerializationBinder Map(Type type, string name)
{
Guard.NotNull(type, nameof(type));
Guard.NotNull(name, nameof(name));
namesByType.Add(type, name);
typesByName.Add(name, type);
return this;
}
public TypeNameSerializationBinder Map(Assembly assembly)
{
foreach (var type in assembly.GetTypes())
{
var typeNameAttribute = type.GetTypeInfo().GetCustomAttribute<TypeNameAttribute>();
if (!string.IsNullOrWhiteSpace(typeNameAttribute?.TypeName))
{
Map(type, typeNameAttribute.TypeName);
}
}
return this;
}
public override Type BindToType(string assemblyName, string typeName)
{
var type = typesByName.GetOrDefault(typeName);
return type ?? base.BindToType(assemblyName, typeName);
}
public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
{
assemblyName = null;
var name = namesByType.GetOrDefault(serializedType);
if (name != null)
{
typeName = name;
}
else
{
base.BindToName(serializedType, out assemblyName, out typeName);
}
}
}
}

17
src/pinkparrot_write/PinkParrot.Write/Schema/ISchemaIdProvider.cs → src/pinkparrot_infrastructure/PinkParrot.Infrastructure/TypeNameAttribute.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// ISchemaIdProvider.cs // TypeNameAttribute.cs
// PinkParrot Headless CMS // PinkParrot Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) PinkParrot Group // Copyright (c) PinkParrot Group
@ -7,12 +7,17 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Threading.Tasks;
namespace PinkParrot.Write.Schema namespace PinkParrot.Infrastructure
{ {
public interface ISchemaIdProvider [AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class TypeNameAttribute : Attribute
{ {
Task<Guid> FindSchemaId(string name); public string TypeName { get; }
public TypeNameAttribute(string typeName)
{
TypeName = typeName;
}
} }
} }

38
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ValidationError.cs

@ -0,0 +1,38 @@
// ==========================================================================
// ValidationError.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System.Collections.Generic;
namespace PinkParrot.Infrastructure
{
public sealed class ValidationError
{
private static readonly string[] FalbackProperties = new string[0];
private readonly string message;
private readonly string[] propertyNames;
public string Message
{
get { return message; }
}
public IEnumerable<string> PropertyNames
{
get { return propertyNames; }
}
public ValidationError(string message, params string[] propertyNames)
{
Guard.NotNullOrEmpty(message, nameof(message));
this.message = message;
this.propertyNames = propertyNames ?? FalbackProperties;
}
}
}

21
src/pinkparrot_infrastructure/PinkParrot.Infrastructure/ValidationException.cs

@ -14,35 +14,36 @@ namespace PinkParrot.Infrastructure
{ {
public class ValidationException : Exception public class ValidationException : Exception
{ {
private readonly IReadOnlyList<string> errors; private static readonly List<ValidationError> FallbackErrors = new List<ValidationError>();
private readonly IReadOnlyList<ValidationError> errors;
public IReadOnlyList<string> Errors public IReadOnlyList<ValidationError> Errors
{ {
get { return errors; } get { return errors; }
} }
public ValidationException(string message, params string[] errors) public ValidationException(string message, params ValidationError[] errors)
: base(message) : base(message)
{ {
this.errors = errors != null ? errors.ToList() : new List<string>(); this.errors = errors != null ? errors.ToList() : FallbackErrors;
} }
public ValidationException(string message, IReadOnlyList<string> errors) public ValidationException(string message, IReadOnlyList<ValidationError> errors)
: base(message) : base(message)
{ {
this.errors = errors ?? new List<string>(); this.errors = errors ?? FallbackErrors;
} }
public ValidationException(string message, Exception inner, params string[] errors) public ValidationException(string message, Exception inner, params ValidationError[] errors)
: base(message, inner) : base(message, inner)
{ {
this.errors = errors != null ? errors.ToList() : new List<string>(); this.errors = errors != null ? errors.ToList() : FallbackErrors;
} }
public ValidationException(string message, Exception inner, IReadOnlyList<string> errors) public ValidationException(string message, Exception inner, IReadOnlyList<ValidationError> errors)
: base(message, inner) : base(message, inner)
{ {
this.errors = errors ?? new List<string>(); this.errors = errors ?? FallbackErrors;
} }
} }
} }

13
src/pinkparrot_read/PinkParrot.Read/Models/ModelSchemaRM.cs

@ -1,7 +1,12 @@
using System; // ==========================================================================
using System.Collections.Generic; // ModelSchemaRM.cs
using System.Linq; // PinkParrot Headless CMS
using System.Threading.Tasks; // ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System;
namespace PinkParrot.Read.Models namespace PinkParrot.Read.Models
{ {

1
src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/MongoDbModelSchemaRepository.cs

@ -9,7 +9,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver; using MongoDB.Driver;
using PinkParrot.Read.Models; using PinkParrot.Read.Models;
using PinkParrot.Read.Repositories.MongoDb.Utils; using PinkParrot.Read.Repositories.MongoDb.Utils;

12
src/pinkparrot_read/PinkParrot.Read/Repositories/MongoDb/Utils/BaseRepository.cs

@ -1,7 +1,11 @@
using System; // ==========================================================================
using System.Collections.Generic; // BaseRepository.cs
using System.Linq; // PinkParrot Headless CMS
using System.Threading.Tasks; // ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using MongoDB.Driver; using MongoDB.Driver;
using PinkParrot.Infrastructure; using PinkParrot.Infrastructure;

5
src/pinkparrot_write/PinkParrot.Write/Schema/Commands/AddModelField.cs

@ -6,14 +6,13 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using PinkParrot.Core.Schema;
using PinkParrot.Infrastructure.CQRS.Commands; using PinkParrot.Infrastructure.CQRS.Commands;
namespace PinkParrot.Write.Schema.Commands namespace PinkParrot.Write.Schema.Commands
{ {
public class AddModelField : AggregateCommand public class AddModelField : AggregateCommand
{ {
public string FieldType; public ModelFieldProperties Properties;
public string FieldName;
} }
} }

3
src/pinkparrot_write/PinkParrot.Write/Schema/Commands/CreateModelSchema.cs

@ -6,12 +6,13 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using PinkParrot.Core.Schema;
using PinkParrot.Infrastructure.CQRS.Commands; using PinkParrot.Infrastructure.CQRS.Commands;
namespace PinkParrot.Write.Schema.Commands namespace PinkParrot.Write.Schema.Commands
{ {
public class CreateModelSchema : AggregateCommand public class CreateModelSchema : AggregateCommand
{ {
public string Name; public ModelSchemaProperties Properties;
} }
} }

4
src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelField.cs

@ -6,7 +6,7 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using PinkParrot.Infrastructure; using PinkParrot.Core.Schema;
using PinkParrot.Infrastructure.CQRS.Commands; using PinkParrot.Infrastructure.CQRS.Commands;
namespace PinkParrot.Write.Schema.Commands namespace PinkParrot.Write.Schema.Commands
@ -15,6 +15,6 @@ namespace PinkParrot.Write.Schema.Commands
{ {
public long FieldId; public long FieldId;
public PropertiesBag Settings; public ModelFieldProperties Properties;
} }
} }

6
src/pinkparrot_write/PinkParrot.Write/Schema/Commands/UpdateModelSchema.cs

@ -6,15 +6,13 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using PinkParrot.Infrastructure; using PinkParrot.Core.Schema;
using PinkParrot.Infrastructure.CQRS.Commands; using PinkParrot.Infrastructure.CQRS.Commands;
namespace PinkParrot.Write.Schema.Commands namespace PinkParrot.Write.Schema.Commands
{ {
public class UpdateModelSchema : AggregateCommand public class UpdateModelSchema : AggregateCommand
{ {
public string NewName; public ModelSchemaProperties Properties;
public PropertiesBag Settings { get; set; }
} }
} }

24
src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaDomainObject.cs

@ -41,19 +41,19 @@ namespace PinkParrot.Write.Schema
protected void Apply(ModelFieldAdded @event) protected void Apply(ModelFieldAdded @event)
{ {
schema = schema.AddField(@event.FieldId, @event.FieldType, @event.FieldName, fieldFactory); schema = schema.AddField(@event.FieldId, @event.Properties, fieldFactory);
totalFields++; totalFields++;
} }
protected void Apply(ModelSchemaCreated @event) protected void Apply(ModelSchemaCreated @event)
{ {
schema = ModelSchema.Create(@event.Name); schema = ModelSchema.Create(@event.Properties);
} }
protected void Apply(ModelFieldUpdated @event) protected void Apply(ModelFieldUpdated @event)
{ {
schema = schema.SetField(@event.FieldId, @event.Settings); schema = schema.SetField(@event.FieldId, @event.Properties);
} }
public void Apply(ModelFieldHidden @event) public void Apply(ModelFieldHidden @event)
@ -78,7 +78,7 @@ namespace PinkParrot.Write.Schema
protected void Apply(ModelSchemaUpdated @event) protected void Apply(ModelSchemaUpdated @event)
{ {
schema = schema.Update(schema.Metadata.Configure(@event.NewName, @event.Settings)); schema = schema.Update(@event.Properties);
} }
protected void Apply(ModelFieldDeleted @event) protected void Apply(ModelFieldDeleted @event)
@ -97,36 +97,36 @@ namespace PinkParrot.Write.Schema
var id = ++totalFields; var id = ++totalFields;
schema = schema.AddField(id, command.FieldType, command.FieldName, fieldFactory); schema = schema.AddField(id, command.Properties, fieldFactory);
RaiseEvent(new ModelFieldAdded { FieldId = id, FieldType = command.FieldType, FieldName = command.FieldName }, true); RaiseEvent(new ModelFieldAdded { FieldId = id, Properties = command.Properties }, true);
} }
public void Create(CreateModelSchema command) public void Create(CreateModelSchema command)
{ {
VerifyNotCreated(); VerifyNotCreated();
schema = ModelSchema.Create(command.Name); schema = ModelSchema.Create(command.Properties);
RaiseEvent(new ModelSchemaCreated { Name = command.Name }, true); RaiseEvent(new ModelSchemaCreated { Properties = command.Properties }, true);
} }
public void Update(UpdateModelSchema command) public void Update(UpdateModelSchema command)
{ {
VerifyCreatedAndNotDeleted(); VerifyCreatedAndNotDeleted();
schema = schema.Update(schema.Metadata.Configure(command.NewName, command.Settings)); schema = schema.Update(command.Properties);
RaiseEvent(new ModelSchemaUpdated { NewName = command.NewName, Settings = command.Settings }, true); RaiseEvent(new ModelSchemaUpdated { Properties = command.Properties }, true);
} }
public void UpdateField(UpdateModelField command) public void UpdateField(UpdateModelField command)
{ {
VerifyCreatedAndNotDeleted(); VerifyCreatedAndNotDeleted();
schema = schema.SetField(command.FieldId, command.Settings); schema = schema.SetField(command.FieldId, command.Properties);
RaiseEvent(new ModelFieldUpdated { FieldId = command.FieldId, Settings = command.Settings }, true); RaiseEvent(new ModelFieldUpdated { FieldId = command.FieldId, Properties = command.Properties }, true);
} }
public void HideField(HideModelField command) public void HideField(HideModelField command)

70
src/pinkparrot_write/PinkParrot.Write/Schema/ModelSchemaNameMap.cs

@ -1,70 +0,0 @@
// ==========================================================================
// ModelSchemaNameMap.cs
// PinkParrot Headless CMS
// ==========================================================================
// Copyright (c) PinkParrot Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using PinkParrot.Events.Schema;
using PinkParrot.Infrastructure.CQRS;
using PinkParrot.Infrastructure.CQRS.Events;
using PinkParrot.Infrastructure.Dispatching;
// ReSharper disable InvertIf
namespace PinkParrot.Write.Schema
{
public class ModelSchemaNameMap : DomainObject
{
private readonly Dictionary<string, Guid> schemaIdsByName = new Dictionary<string, Guid>();
private readonly Dictionary<Guid, string> schemaNamesByIds = new Dictionary<Guid, string>();
public ModelSchemaNameMap(Guid id, int version)
: base(id, version)
{
}
protected void On(ModelSchemaDeleted @event, EnvelopeHeaders headers)
{
var aggregateId = headers.AggregateId();
string oldName;
if (schemaNamesByIds.TryGetValue(aggregateId, out oldName))
{
schemaIdsByName.Remove(oldName);
schemaNamesByIds.Remove(aggregateId);
}
}
protected void On(ModelSchemaUpdated @event, EnvelopeHeaders headers)
{
var aggregateId = headers.AggregateId();
string oldName;
if (schemaNamesByIds.TryGetValue(aggregateId, out oldName))
{
schemaIdsByName.Remove(oldName);
schemaIdsByName[@event.NewName] = aggregateId;
}
}
protected void On(ModelSchemaCreated @event, EnvelopeHeaders headers)
{
schemaIdsByName[@event.Name] = headers.AggregateId();
}
public void Apply(Envelope<IEvent> @event)
{
ApplyEvent(@event);
}
protected override void ApplyEvent(Envelope<IEvent> @event)
{
this.DispatchAction(@event.Payload, @event.Headers);
}
}
}
Loading…
Cancel
Save