Browse Source

Merge branch 'master' into orleans3

# Conflicts:
#	src/Squidex.Domain.Apps.Entities/Contents/ContentOperationContext.cs
#	src/Squidex.Infrastructure/Commands/DomainObjectBase.cs
pull/249/head
Sebastian Stehle 8 years ago
parent
commit
fb7c8ce139
  1. 6
      README.md
  2. 26
      src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ContentValidationExtensions.cs
  3. 6
      src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs
  4. 81
      src/Squidex.Domain.Apps.Entities/Contents/ContentOperationContext.cs
  5. 2
      src/Squidex/Pipeline/CommandMiddlewares/EnrichWithAppIdCommandMiddleware.cs
  6. 2
      src/Squidex/Pipeline/CommandMiddlewares/EnrichWithSchemaIdCommandMiddleware.cs
  7. 9
      src/Squidex/app/framework/angular/date-time-editor.component.ts

6
README.md

@ -4,7 +4,7 @@
Squidex is an open source headless CMS and content management hub. In contrast to a traditional CMS Squidex provides a rich API with OData filter and Swagger definitions. It is up to you to build your UI on top of it. It can be website, a native app or just another server. We build it with ASP.NET Core and CQRS and is tested for Windows and Linux on modern browsers.
[![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=square)](https://gitter.im/squidex-cms/Lobby) [![Slack](https://img.shields.io/badge/chat-on_slack-E01765.svg?style=square)](https://squidex-slack.herokuapp.com/) [![Build Status](http://build.squidex.io/api/badges/Squidex/squidex/status.svg)](http://build.squidex.io/Squidex/squidex)
[![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=square)](https://gitter.im/squidex-cms/Lobby) [![Slack](https://img.shields.io/badge/chat-on_slack-E01765.svg?style=square)](https://squidex-slack.herokuapp.com/) [![Build Status](http://build.squidex.io/api/badges/Squidex/squidex/status.svg)](http://build.squidex.io/Squidex/squidex) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FSquidex%2Fsquidex.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FSquidex%2Fsquidex?ref=badge_shield)
Read the docs at [https://docs.squidex.io/](https://docs.squidex.io/) (work in progress) or just check out the code and play around.
@ -40,3 +40,7 @@ Please create issues to report bugs, suggest new functionalities, ask questions
## Cloud Version
Although Squidex is free we are also working on a Saas version on [https://cloud.squidex.io](https://cloud.squidex.io) (More information coming soon). We have also have plans to sell a premium version with first class support and some exlusive features. But don't be afraid, our first priority is to deliver a state of the art, stable, fast and free content management hub to make the life for developers a little bit easier.
## License
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FSquidex%2Fsquidex.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FSquidex%2Fsquidex?ref=badge_large)

26
src/Squidex.Domain.Apps.Core.Operations/ValidateContent/ContentValidationExtensions.cs

@ -5,7 +5,9 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Schemas;
@ -27,6 +29,18 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
}
}
public static async Task ValidateAsync(this NamedContentData data, ValidationContext context, Schema schema, PartitionResolver partitionResolver, Func<string> message)
{
var validator = new ContentValidator(schema, partitionResolver, context);
await validator.ValidateAsync(data);
if (validator.Errors.Count > 0)
{
throw new ValidationException(message(), validator.Errors.ToList());
}
}
public static async Task ValidatePartialAsync(this NamedContentData data, ValidationContext context, Schema schema, PartitionResolver partitionResolver, IList<ValidationError> errors)
{
var validator = new ContentValidator(schema, partitionResolver, context);
@ -38,5 +52,17 @@ namespace Squidex.Domain.Apps.Core.ValidateContent
errors.Add(error);
}
}
public static async Task ValidatePartialAsync(this NamedContentData data, ValidationContext context, Schema schema, PartitionResolver partitionResolver, Func<string> message)
{
var validator = new ContentValidator(schema, partitionResolver, context);
await validator.ValidatePartialAsync(data);
if (validator.Errors.Count > 0)
{
throw new ValidationException(message(), validator.Errors.ToList());
}
}
}
}

6
src/Squidex.Domain.Apps.Entities/Contents/ContentGrain.cs

@ -91,7 +91,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
await operationContext.ExecuteScriptAndTransformAsync(x => x.ScriptCreate, "Create");
await operationContext.EnrichAsync();
await operationContext.ValidateAsync(false);
await operationContext.ValidateAsync();
Create(c);
@ -105,7 +105,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
var operationContext = await CreateContext(c, () => "Failed to update content.");
await operationContext.ValidateAsync(true);
await operationContext.ValidateAsync();
await operationContext.ExecuteScriptAndTransformAsync(x => x.ScriptUpdate, "Update");
Update(c);
@ -120,7 +120,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
var operationContext = await CreateContext(c, () => "Failed to patch content.");
await operationContext.ValidateAsync(true);
await operationContext.ValidatePartialAsync();
await operationContext.ExecuteScriptAndTransformAsync(x => x.ScriptUpdate, "Patch");
Patch(c);

81
src/Squidex.Domain.Apps.Entities/Contents/ContentOperationContext.cs

@ -9,6 +9,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.EnrichContent;
using Squidex.Domain.Apps.Core.Scripting;
using Squidex.Domain.Apps.Core.ValidateContent;
@ -17,7 +18,6 @@ using Squidex.Domain.Apps.Entities.Assets.Repositories;
using Squidex.Domain.Apps.Entities.Contents.Commands;
using Squidex.Domain.Apps.Entities.Contents.Repositories;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Tasks;
namespace Squidex.Domain.Apps.Entities.Contents
@ -31,6 +31,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
private IScriptEngine scriptEngine;
private ISchemaEntity schemaEntity;
private IAppEntity appEntity;
private Guid appId;
private Func<string> message;
public static async Task<ContentOperationContext> CreateAsync(
@ -56,6 +57,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
var context = new ContentOperationContext
{
appEntity = appEntity,
appId = a.Id,
assetRepository = assetRepository,
contentRepository = contentRepository,
content = content,
@ -78,54 +80,35 @@ namespace Squidex.Domain.Apps.Entities.Contents
return TaskHelper.Done;
}
public async Task ValidateAsync(bool partial)
public Task ValidateAsync()
{
if (command is ContentDataCommand dataCommand)
{
var errors = new List<ValidationError>();
var ctx =
new ValidationContext(
(contentIds, schemaId) =>
{
return QueryContentsAsync(content.AppId.Id, schemaId, contentIds);
},
assetIds =>
{
return QueryAssetsAsync(content.AppId.Id, assetIds);
});
if (partial)
{
await dataCommand.Data.ValidatePartialAsync(ctx, schemaEntity.SchemaDef, appEntity.PartitionResolver(), errors);
}
else
{
await dataCommand.Data.ValidateAsync(ctx, schemaEntity.SchemaDef, appEntity.PartitionResolver(), errors);
}
var ctx = CreateValidationContext();
if (errors.Count > 0)
{
throw new ValidationException(message(), errors.ToArray());
}
return dataCommand.Data.ValidateAsync(ctx, schemaEntity.SchemaDef, appEntity.PartitionResolver(), message);
}
}
private async Task<IReadOnlyList<IAssetInfo>> QueryAssetsAsync(Guid appId, IEnumerable<Guid> assetIds)
{
return await assetRepository.QueryAsync(appId, new HashSet<Guid>(assetIds));
return TaskHelper.Done;
}
private async Task<IReadOnlyList<Guid>> QueryContentsAsync(Guid appId, Guid schemaId, IEnumerable<Guid> contentIds)
public Task ValidatePartialAsync()
{
return await contentRepository.QueryNotFoundAsync(appId, schemaId, contentIds.ToList());
if (command is ContentDataCommand dataCommand)
{
var ctx = CreateValidationContext();
return dataCommand.Data.ValidatePartialAsync(ctx, schemaEntity.SchemaDef, appEntity.PartitionResolver(), message);
}
return TaskHelper.Done;
}
public Task ExecuteScriptAndTransformAsync(Func<ISchemaEntity, string> script, object operation)
{
if (command is ContentDataCommand dataCommand)
{
var ctx = new ScriptContext { ContentId = content.Id, OldData = content.Data, User = command.User, Operation = operation.ToString(), Data = dataCommand.Data };
var ctx = CreateScriptContext(operation, dataCommand.Data);
dataCommand.Data = scriptEngine.ExecuteAndTransform(ctx, script(schemaEntity));
}
@ -135,11 +118,39 @@ namespace Squidex.Domain.Apps.Entities.Contents
public Task ExecuteScriptAsync(Func<ISchemaEntity, string> script, object operation)
{
var ctx = new ScriptContext { ContentId = content.Id, OldData = content.Data, User = command.User, Operation = operation.ToString() };
var ctx = CreateScriptContext(operation, content.Data);
scriptEngine.Execute(ctx, script(schemaEntity));
return TaskHelper.Done;
}
private ScriptContext CreateScriptContext(object operation, NamedContentData data = null)
{
return new ScriptContext { ContentId = command.ContentId, OldData = content.Data, Data = data, User = command.User, Operation = operation.ToString() };
}
private ValidationContext CreateValidationContext()
{
return new ValidationContext(
(contentIds, schemaId) =>
{
return QueryContentsAsync(schemaId, contentIds);
},
assetIds =>
{
return QueryAssetsAsync(assetIds);
});
}
private async Task<IReadOnlyList<IAssetInfo>> QueryAssetsAsync(IEnumerable<Guid> assetIds)
{
return await assetRepository.QueryAsync(appId, new HashSet<Guid>(assetIds));
}
private async Task<IReadOnlyList<Guid>> QueryContentsAsync(Guid schemaId, IEnumerable<Guid> contentIds)
{
return await contentRepository.QueryNotFoundAsync(appId, schemaId, contentIds.ToList());
}
}
}

2
src/Squidex/Pipeline/CommandMiddlewares/EnrichWithAppIdCommandMiddleware.cs

@ -60,4 +60,4 @@ namespace Squidex.Pipeline.CommandMiddlewares
return new NamedId<Guid>(appFeature.App.Id, appFeature.App.Name);
}
}
}
}

2
src/Squidex/Pipeline/CommandMiddlewares/EnrichWithSchemaIdCommandMiddleware.cs

@ -101,4 +101,4 @@ namespace Squidex.Pipeline.CommandMiddlewares
return null;
}
}
}
}

9
src/Squidex/app/framework/angular/date-time-editor.component.ts

@ -191,19 +191,20 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnDestroy,
}
private updateControls() {
if (!this.dateValue) {
return;
}
this.suppressEvents = true;
if (this.timeValue && this.timeValue.isValid()) {
this.timeControl.setValue(this.timeValue.format('HH:mm:ss'), { emitEvent: false });
} else {
this.timeControl.setValue(null, { emitEvent: false });
}
if (this.dateValue && this.dateValue.isValid() && this.picker) {
this.dateControl.setValue(this.dateValue.format('YYYY-MM-DD'), { emitEvent: false });
this.picker.setMoment(this.dateValue);
} else {
this.dateControl.setValue(null, { emitEvent: false });
}
this.suppressEvents = false;

Loading…
Cancel
Save