Browse Source

Fix rtule creation.

pull/926/head
Sebastian 4 years ago
parent
commit
399968ef9c
  1. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj
  2. 2
      backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj
  3. 12
      backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj
  4. 67
      backend/src/Squidex.Web/ApiModelValidationAttribute.cs
  5. 1
      backend/src/Squidex/Config/Domain/SerializationServices.cs
  6. 11
      backend/src/Squidex/Config/Messaging/MessagingServices.cs
  7. 24
      backend/src/Squidex/Squidex.csproj
  8. 2
      frontend/src/app/features/administration/state/users.state.ts
  9. 20
      frontend/src/app/features/rules/pages/rule/rule-page.component.html
  10. 60
      frontend/src/app/features/rules/pages/rule/rule-page.component.ts
  11. 4
      frontend/src/app/features/rules/shared/triggers/content-changed-trigger.component.ts
  12. 3
      frontend/src/app/shared/state/languages.state.ts
  13. 4
      frontend/src/app/shared/state/rules.forms.ts

2
backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj

@ -28,7 +28,7 @@
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
<PackageReference Include="NJsonSchema" Version="10.7.2" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="Squidex.Messaging.Subscriptions" Version="4.11.0" />
<PackageReference Include="Squidex.Messaging.Subscriptions" Version="4.12.0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.Collections.Immutable" Version="6.0.0" />
<PackageReference Include="System.Linq.Async" Version="6.0.1" />

2
backend/src/Squidex.Domain.Apps.Entities/Squidex.Domain.Apps.Entities.csproj

@ -29,7 +29,7 @@
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
<PackageReference Include="Notifo.SDK" Version="1.2.0" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="Squidex.CLI.Core" Version="8.19.0" />
<PackageReference Include="Squidex.CLI.Core" Version="8.21.0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.Collections.Immutable" Version="6.0.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />

12
backend/src/Squidex.Infrastructure/Squidex.Infrastructure.csproj

@ -24,12 +24,12 @@
<PackageReference Include="NodaTime" Version="3.1.2" />
<PackageReference Include="OpenTelemetry.Api" Version="1.3.0" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="Squidex.Assets" Version="4.11.0" />
<PackageReference Include="Squidex.Caching" Version="4.11.0" />
<PackageReference Include="Squidex.Hosting.Abstractions" Version="4.11.0" />
<PackageReference Include="Squidex.Log" Version="4.11.0" />
<PackageReference Include="Squidex.Messaging" Version="4.11.0" />
<PackageReference Include="Squidex.Text" Version="4.11.0" />
<PackageReference Include="Squidex.Assets" Version="4.12.0" />
<PackageReference Include="Squidex.Caching" Version="4.12.0" />
<PackageReference Include="Squidex.Hosting.Abstractions" Version="4.12.0" />
<PackageReference Include="Squidex.Log" Version="4.12.0" />
<PackageReference Include="Squidex.Messaging" Version="4.12.0" />
<PackageReference Include="Squidex.Text" Version="4.12.0" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />
<PackageReference Include="System.Collections.Immutable" Version="6.0.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />

67
backend/src/Squidex.Web/ApiModelValidationAttribute.cs

@ -27,60 +27,57 @@ namespace Squidex.Web
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
if (context.ModelState.IsValid)
{
var errors = new List<ValidationError>();
return;
}
var errors = new List<ValidationError>();
foreach (var (key, value) in context.ModelState)
foreach (var (key, value) in context.ModelState)
{
if (value.ValidationState == ModelValidationState.Invalid)
{
if (value.ValidationState == ModelValidationState.Invalid)
foreach (var error in value.Errors)
{
foreach (var error in value.Errors)
if (error.ErrorMessage?.Contains(RequestBodyTooLarge, StringComparison.OrdinalIgnoreCase) == true)
{
if (error.ErrorMessage?.Contains(RequestBodyTooLarge, StringComparison.OrdinalIgnoreCase) == true)
{
throw new BadHttpRequestException(error.ErrorMessage, 413);
}
throw new BadHttpRequestException(error.ErrorMessage, 413);
}
}
if (string.IsNullOrWhiteSpace(key))
{
errors.Add(new ValidationError(T.Get("common.httpInvalidRequestFormat")));
}
else
{
var properties = Array.Empty<string>();
if (string.IsNullOrWhiteSpace(key))
if (!string.IsNullOrWhiteSpace(key))
{
errors.Add(new ValidationError(T.Get("common.httpInvalidRequestFormat")));
properties = new[] { key.ToCamelCase() };
}
else
{
var properties = Array.Empty<string>();
if (!string.IsNullOrWhiteSpace(key))
foreach (var error in value.Errors)
{
if (!string.IsNullOrWhiteSpace(error.ErrorMessage) && allErrors)
{
properties = new[] { key.ToCamelCase() };
errors.Add(new ValidationError(error.ErrorMessage, properties));
}
foreach (var error in value.Errors)
else if (error.Exception is JsonException jsonException)
{
if (!string.IsNullOrWhiteSpace(error.ErrorMessage) && ShouldExpose(error))
{
errors.Add(new ValidationError(error.ErrorMessage, properties));
}
else if (error.Exception is JsonException jsonException)
{
errors.Add(new ValidationError(jsonException.Message));
}
errors.Add(new ValidationError(jsonException.Message));
}
}
}
}
if (errors.Count > 0)
{
throw new ValidationException(errors);
}
}
}
private bool ShouldExpose(ModelError error)
{
return allErrors || error.Exception is JsonException;
if (errors.Count > 0)
{
throw new ValidationException(errors);
}
}
}
}

1
backend/src/Squidex/Config/Domain/SerializationServices.cs

@ -117,6 +117,7 @@ namespace Squidex.Config.Domain
ConfigureJson(c.GetRequiredService<TypeNameRegistry>(), options.JsonSerializerOptions);
options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
options.AllowInputFormatterExceptionMessages = true;
});
return builder;

11
backend/src/Squidex/Config/Messaging/MessagingServices.cs

@ -95,22 +95,25 @@ namespace Squidex.Config.Messaging
{
options.Timeout = TimeSpan.FromHours(4);
options.Scheduler = new ParallelScheduler(4);
options.LogMessage = x => true;
});
services.AddMessaging(channelBackupRestore, isWorker, options =>
{
options.Timeout = TimeSpan.FromHours(24);
options.Scheduler = InlineScheduler.Instance;
options.LogMessage = x => true;
});
services.AddMessaging(channelFallback, isWorker, options =>
services.AddMessaging(channelRules, isWorker, options =>
{
options.Scheduler = InlineScheduler.Instance;
options.Scheduler = new ParallelScheduler(4);
options.LogMessage = x => true;
});
services.AddMessaging(channelRules, isWorker, options =>
services.AddMessaging(channelFallback, isWorker, options =>
{
options.Scheduler = new ParallelScheduler(4);
options.Scheduler = InlineScheduler.Instance;
});
}
}

24
backend/src/Squidex/Squidex.csproj

@ -69,19 +69,19 @@
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.0.0-rc7" />
<PackageReference Include="RefactoringEssentials" Version="5.6.0" PrivateAssets="all" />
<PackageReference Include="ReportGenerator" Version="5.1.9" PrivateAssets="all" />
<PackageReference Include="Squidex.Assets.Azure" Version="4.11.0" />
<PackageReference Include="Squidex.Assets.GoogleCloud" Version="4.11.0" />
<PackageReference Include="Squidex.Assets.FTP" Version="4.11.0" />
<PackageReference Include="Squidex.Assets.ImageMagick" Version="4.11.0" />
<PackageReference Include="Squidex.Assets.ImageSharp" Version="4.11.0" />
<PackageReference Include="Squidex.Assets.Mongo" Version="4.11.0" />
<PackageReference Include="Squidex.Assets.S3" Version="4.11.0" />
<PackageReference Include="Squidex.Assets.TusAdapter" Version="4.11.0" />
<PackageReference Include="Squidex.Assets.Azure" Version="4.12.0" />
<PackageReference Include="Squidex.Assets.GoogleCloud" Version="4.12.0" />
<PackageReference Include="Squidex.Assets.FTP" Version="4.12.0" />
<PackageReference Include="Squidex.Assets.ImageMagick" Version="4.12.0" />
<PackageReference Include="Squidex.Assets.ImageSharp" Version="4.12.0" />
<PackageReference Include="Squidex.Assets.Mongo" Version="4.12.0" />
<PackageReference Include="Squidex.Assets.S3" Version="4.12.0" />
<PackageReference Include="Squidex.Assets.TusAdapter" Version="4.12.0" />
<PackageReference Include="Squidex.Caching.Orleans" Version="1.9.0" />
<PackageReference Include="Squidex.ClientLibrary" Version="8.27.0" />
<PackageReference Include="Squidex.Hosting" Version="4.11.0" />
<PackageReference Include="Squidex.Messaging.All" Version="4.11.0" />
<PackageReference Include="Squidex.Messaging.Subscriptions" Version="4.11.0" />
<PackageReference Include="Squidex.ClientLibrary" Version="9.2.0" />
<PackageReference Include="Squidex.Hosting" Version="4.12.0" />
<PackageReference Include="Squidex.Messaging.All" Version="4.12.0" />
<PackageReference Include="Squidex.Messaging.Subscriptions" Version="4.12.0" />
<PackageReference Include="Squidex.Namotion.Reflection" Version="2.0.10" />
<PackageReference Include="Squidex.OpenIddict.MongoDb" Version="4.0.1-dev" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" />

2
frontend/src/app/features/administration/state/users.state.ts

@ -201,7 +201,7 @@ export class UsersState extends State<Snapshot> {
private replaceUser(user: UserDto) {
return this.next(s => {
const users = s.users.map(u => (u.id === user.id ? user : u));
const users = s.users.replacedBy('id', user);
const selectedUser =
s.selectedUser?.id !== user.id ?

20
frontend/src/app/features/rules/pages/rule/rule-page.component.html

@ -49,7 +49,7 @@
</div>
<div class="col col-icon" *ngIf="currentTrigger">
<sqx-rule-element [type]="currentTrigger.type" [isSmall]="true" [element]="triggerElement" [disabled]="true"></sqx-rule-element>
<sqx-rule-element [type]="currentTrigger.triggerType" [isSmall]="true" [element]="triggerElement" [disabled]="true"></sqx-rule-element>
</div>
<div class="col text-end" *ngIf="currentTrigger && !rule">
@ -69,18 +69,18 @@
{{ 'rules.triggerHint' | sqxTranslate }}
</sqx-form-alert>
<ng-container [ngSwitch]="currentTrigger.type">
<ng-container [ngSwitch]="currentTrigger.triggerType">
<ng-container *ngSwitchCase="'AssetChanged'">
<sqx-asset-changed-trigger [triggerForm]="currentTrigger.form"></sqx-asset-changed-trigger>
<sqx-asset-changed-trigger [triggerForm]="currentTrigger"></sqx-asset-changed-trigger>
</ng-container>
<ng-container *ngSwitchCase="'Comment'">
<sqx-comment-trigger [triggerForm]="currentTrigger.form"></sqx-comment-trigger>
<sqx-comment-trigger [triggerForm]="currentTrigger"></sqx-comment-trigger>
</ng-container>
<ng-container *ngSwitchCase="'ContentChanged'">
<sqx-content-changed-trigger
[schemas]="schemasState.schemas | async"
[trigger]="currentTrigger.values"
[triggerForm]="currentTrigger.form">
[trigger]="currentTrigger.form.value"
[triggerForm]="currentTrigger">
</sqx-content-changed-trigger>
</ng-container>
<ng-container *ngSwitchCase="'SchemaChanged'">
@ -112,7 +112,7 @@
</div>
<div class="col col-icon" *ngIf="currentAction">
<sqx-rule-element [type]="currentAction.type" [isSmall]="true" [element]="actionElement" [disabled]="true"></sqx-rule-element>
<sqx-rule-element [type]="currentAction.actionType" [isSmall]="true" [element]="actionElement" [disabled]="true"></sqx-rule-element>
</div>
<div class="col text-end" *ngIf="currentAction && !rule">
@ -134,9 +134,9 @@
</sqx-form-alert>
<sqx-generic-action
[actionForm]="currentAction.form"
[trigger]="currentTrigger"
[triggerType]="currentTrigger?.type"
[actionForm]="currentAction"
[trigger]="currentTrigger?.form.value"
[triggerType]="currentTrigger?.triggerType"
[appName]="rulesState.appName">
</sqx-generic-action>
</ng-container>

60
frontend/src/app/features/rules/pages/rule/rule-page.component.ts

@ -12,8 +12,6 @@ import { debounceTime, Subscription } from 'rxjs';
import { ActionForm, ALL_TRIGGERS, MessageBus, ResourceOwner, RuleDto, RuleElementDto, RulesService, RulesState, SchemasState, TriggerForm, value$ } from '@app/shared';
import { RuleConfigured } from '../messages';
type ComponentState<T> = { type: string; values: any; form: T };
@Component({
selector: 'sqx-rule-page',
styleUrls: ['./rule-page.component.scss'],
@ -28,8 +26,8 @@ export class RulePageComponent extends ResourceOwner implements OnInit {
public rule?: RuleDto | null;
public currentTrigger?: ComponentState<TriggerForm>;
public currentAction?: ComponentState<ActionForm>;
public currentTrigger?: TriggerForm;
public currentAction?: ActionForm;
public isEnabled = false;
public isEditable = false;
@ -39,11 +37,11 @@ export class RulePageComponent extends ResourceOwner implements OnInit {
}
public get actionElement() {
return this.supportedActions![this.currentAction?.type || ''];
return this.supportedActions![this.currentAction?.actionType || ''];
}
public get triggerElement() {
return this.supportedTriggers[this.currentTrigger?.type || ''];
return this.supportedTriggers[this.currentTrigger?.triggerType || ''];
}
constructor(
@ -92,30 +90,32 @@ export class RulePageComponent extends ResourceOwner implements OnInit {
}
}
public selectAction(type: string, values = {}) {
if (this.currentAction?.type !== type && this.supportedActions) {
const form = new ActionForm(this.supportedActions[type], type);
public selectAction(type: string, values?: any) {
const definition = this.supportedActions[type];
this.currentAction = { form, type, values };
this.currentAction.form.setEnabled(this.isEditable);
if (this.currentAction?.actionType !== type && definition) {
this.currentAction = new ActionForm(definition, type);
this.currentAction.setEnabled(this.isEditable);
this.currentActionSubscription?.unsubscribe();
this.currentActionSubscription = this.subscribe(form.form);
this.currentActionSubscription = this.subscribe(this.currentAction.form);
}
this.currentAction!.form.load(values);
if (values) {
this.currentAction?.load(values);
}
}
public selectTrigger(type: string, values = {}) {
if (this.currentTrigger?.type !== type) {
const form = new TriggerForm(type);
this.currentTrigger = { form, type, values };
this.currentTrigger.form.setEnabled(this.isEditable);
public selectTrigger(type: string, values?: any) {
if (this.currentTrigger?.triggerType !== type) {
this.currentTrigger = new TriggerForm(type);
this.currentTrigger.setEnabled(this.isEditable);
this.currentTriggerSubscription?.unsubscribe();
this.currentTriggerSubscription = this.subscribe(form.form);
this.currentTriggerSubscription = this.subscribe(this.currentTrigger.form);
}
this.currentTrigger.form.load(values);
if (values) {
this.currentTrigger?.load(values || {});
}
}
private subscribe(form: AbstractControl) {
@ -139,13 +139,13 @@ export class RulePageComponent extends ResourceOwner implements OnInit {
return;
}
const action = this.currentAction.form.submit();
const action = this.currentAction.submit();
if (!action) {
return;
}
const trigger = this.currentTrigger.form.submit();
const trigger = this.currentTrigger.submit();
if (!trigger || !action) {
return;
@ -183,23 +183,23 @@ export class RulePageComponent extends ResourceOwner implements OnInit {
return;
}
if (!this.currentAction.form.form.valid || !this.currentTrigger.form.form.valid) {
if (!this.currentAction.form.valid || !this.currentTrigger.form.valid) {
return;
}
this.messageBus.emit(new RuleConfigured(
this.currentTrigger.form.getValue(),
this.currentAction.form.getValue()));
this.currentTrigger.getValue(),
this.currentAction.getValue()));
}
private submitCompleted() {
this.currentAction?.form.submitCompleted({ noReset: true });
this.currentTrigger?.form.submitCompleted({ noReset: true });
this.currentAction?.submitCompleted({ noReset: true });
this.currentTrigger?.submitCompleted({ noReset: true });
}
private submitFailed(error: any) {
this.currentAction?.form?.submitFailed(error);
this.currentTrigger?.form?.submitFailed(error);
this.currentAction?.submitFailed(error);
this.currentTrigger?.submitFailed(error);
}
public back() {

4
frontend/src/app/features/rules/shared/triggers/content-changed-trigger.component.ts

@ -75,13 +75,13 @@ export class ContentChangedTriggerComponent implements OnChanges {
}
public updateCondition(schema: SchemaDto, condition: string) {
this.triggerSchemas = this.triggerSchemas.map(s => (s.schema === schema ? { schema, condition } : s));
this.triggerSchemas.replaceBy('schema', { schema, condition });
this.updateValue();
}
public updateValue() {
const schemas = this.triggerSchemas.map(s => ({ schemaId: s.schema.id, condition: s.condition }));
const schemas = this.triggerSchemas.map(({ schema, condition }) => ({ schemaId: schema.id, condition }));
this.triggerForm.form.patchValue({ schemas });
}

3
frontend/src/app/shared/state/languages.state.ts

@ -189,8 +189,7 @@ export class LanguagesState extends State<Snapshot> {
.map(l => languages.find(x => x.iso2Code === l)).defined(),
fallbackLanguagesNew:
languages
.filter(l => language.iso2Code !== l.iso2Code && !language.fallback.includes(l.iso2Code))
.sortByString(x => x.englishName),
.filter(l => language.iso2Code !== l.iso2Code && !language.fallback.includes(l.iso2Code)).sortByString(x => x.englishName),
};
}
}

4
frontend/src/app/shared/state/rules.forms.ts

@ -11,7 +11,7 @@ import { RuleElementDto } from '../services/rules.service';
export class ActionForm extends Form<any, FormGroup> {
constructor(public readonly definition: RuleElementDto,
private readonly actionType: string,
public readonly actionType: string,
) {
super(ActionForm.builForm(definition));
}
@ -40,7 +40,7 @@ export class ActionForm extends Form<any, FormGroup> {
export class TriggerForm extends Form<any, FormGroup> {
constructor(
private readonly triggerType: string,
public readonly triggerType: string,
) {
super(TriggerForm.builForm(triggerType));
}

Loading…
Cancel
Save