diff --git a/src/Squidex.Domain.Apps.Write/Webhooks/WebhookDomainObject.cs b/src/Squidex.Domain.Apps.Write/Webhooks/WebhookDomainObject.cs index 139643a6c..c3484699d 100644 --- a/src/Squidex.Domain.Apps.Write/Webhooks/WebhookDomainObject.cs +++ b/src/Squidex.Domain.Apps.Write/Webhooks/WebhookDomainObject.cs @@ -74,7 +74,7 @@ namespace Squidex.Domain.Apps.Write.Webhooks private void VerifyCreatedAndNotDeleted() { - if (isDeleted || isCreated) + if (isDeleted || !isCreated) { throw new DomainException("Webhook has already been deleted or not created yet."); } diff --git a/src/Squidex/Controllers/Api/Webhooks/Models/WebhookCreatedDto.cs b/src/Squidex/Controllers/Api/Webhooks/Models/WebhookCreatedDto.cs new file mode 100644 index 000000000..7b04c9f0e --- /dev/null +++ b/src/Squidex/Controllers/Api/Webhooks/Models/WebhookCreatedDto.cs @@ -0,0 +1,32 @@ +// ========================================================================== +// WebhookCreatedDto.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using System; +using System.ComponentModel.DataAnnotations; + +namespace Squidex.Controllers.Api.Webhooks.Models +{ + public class WebhookCreatedDto + { + /// + /// The id of the webhook. + /// + public Guid Id { get; set; } + + /// + /// The shared secret that is used to calculate the signature. + /// + [Required] + public string SharedSecret { get; set; } + + /// + /// The version of the schema. + /// + public long Version { get; set; } + } +} diff --git a/src/Squidex/app/features/webhooks/pages/webhook.component.html b/src/Squidex/app/features/webhooks/pages/webhook.component.html new file mode 100644 index 000000000..a5005e98b --- /dev/null +++ b/src/Squidex/app/features/webhooks/pages/webhook.component.html @@ -0,0 +1,143 @@ +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + +
Url: + + + +
Secret: + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Schema + C + + U + + D + + P + + U +
+ {{schema.schema.name}} + + + + + + + + + + + + +
+ +
+
+ +
+ + +
+
+ +
+
+
+ + {{webhook.totalSucceeded}} + +
+
+ + {{webhook.totalFailed}} + +
+
+ + {{webhook.totalTimedout}} + +
+
+ + {{webhook.averageRequestTimeMs}} ms + +
+
+
+
\ No newline at end of file diff --git a/src/Squidex/app/features/webhooks/pages/webhook.component.scss b/src/Squidex/app/features/webhooks/pages/webhook.component.scss new file mode 100644 index 000000000..61873b1a2 --- /dev/null +++ b/src/Squidex/app/features/webhooks/pages/webhook.component.scss @@ -0,0 +1,13 @@ +@import '_vars'; +@import '_mixins'; + +.schemas-control { + width: 18rem; +} + +.webhook-section { + border-top: 1px solid $color-border; + margin-left: -1.25rem; + margin-right: -1.25rem; + padding: 1rem 1.25rem 0; +} \ No newline at end of file diff --git a/src/Squidex/app/features/webhooks/pages/webhook.component.ts b/src/Squidex/app/features/webhooks/pages/webhook.component.ts new file mode 100644 index 000000000..01b4d3631 --- /dev/null +++ b/src/Squidex/app/features/webhooks/pages/webhook.component.ts @@ -0,0 +1,129 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { FormBuilder, Validators } from '@angular/forms'; + +import { + ImmutableArray, + SchemaDto, + UpdateWebhookDto, + WebhookDto +} from 'shared'; + +interface WebhookSchemaForm { + schema: SchemaDto; + sendCreate: boolean; + sendUpdate: boolean; + sendDelete: boolean; + sendPublish: boolean; + sendUnpublish: boolean; +} + +@Component({ + selector: 'sqx-webhook', + styleUrls: ['./webhook.component.scss'], + templateUrl: './webhook.component.html' +}) +export class WebhookComponent implements OnInit { + @Output() + public deleting = new EventEmitter(); + + @Output() + public updating = new EventEmitter(); + + @Input() + public allSchemas: SchemaDto[]; + + @Input() + public webhook: WebhookDto; + + public schemas: ImmutableArray; + + public schemasToAdd: ImmutableArray; + + public webhookFormSubmitted = false; + public webhookForm = + this.formBuilder.group({ + url: ['', + [ + Validators.required + ]] + }); + + public addSchemaForm = + this.formBuilder.group({ + schema: [null] + }); + + public get hasUrl() { + return this.webhookForm.controls['url'].value && this.webhookForm.controls['url'].value.length > 0; + } + + public get hasSchema() { + return this.addSchemaForm.controls['schema'].value; + } + + constructor( + private readonly formBuilder: FormBuilder + ) { + } + + public ngOnInit() { + this.webhookForm.controls['url'].setValue(this.webhook.url); + + this.schemasToAdd = + ImmutableArray.of( + this.allSchemas.filter(schema => + !this.webhook.schemas.find(w => w.schemaId === schema.id))) + .sortByStringAsc(x => x.name); + + this.schemas = + ImmutableArray.of( + this.webhook.schemas.map(webhookSchema => { + const schema = this.allSchemas.find(s => s.id === webhookSchema.schemaId); + + if (schema) { + return { + schema: schema, + sendCreate: webhookSchema.sendCreate, + sendUpdate: webhookSchema.sendUpdate, + sendDelete: webhookSchema.sendDelete, + sendPublish: webhookSchema.sendPublish, + sendUnpublish: webhookSchema.sendUnpublish + }; + } else { + return null; + } + }).filter(w => !!w)).sortByStringAsc(x => x.schema.name); + + this.addSchemaForm.controls['schema'].setValue(this.schemasToAdd.find(x => true)); + } + + public removeSchema(webhookSchema: WebhookSchemaForm) { + this.schemasToAdd = this.schemasToAdd.push(webhookSchema.schema).sortByStringAsc(x => x.name); + this.schemas = this.schemas.remove(webhookSchema); + + this.addSchemaForm.controls['schema'].setValue(this.schemasToAdd.find(x => true)); + } + + public addSchema() { + const schema: SchemaDto = this.addSchemaForm.controls['schema'].value; + + this.schemasToAdd = this.schemasToAdd.remove(schema).sortByStringAsc(x => x.name); + this.schemas = this.schemas.push({ + schema: schema, + sendCreate: false, + sendUpdate: false, + sendDelete: false, + sendPublish: false, + sendUnpublish: false + }).sortByStringAsc(x => x.schema.name); + + this.addSchemaForm.controls['schema'].setValue(this.schemasToAdd.find(x => true)); + } +}