The Webhooks functionality implementation

All functionality for the Webhooks is implemented like: list, create, edit, delete
This commit is contained in:
axeleron007 2021-06-02 14:14:24 +03:00
parent 389080c5f4
commit e5d497c539
33 changed files with 137 additions and 311 deletions

View file

@ -0,0 +1,45 @@
using System.Threading;
using System.Threading.Tasks;
using Elsa.Persistence.Specifications;
using Elsa.Webhooks.Abstractions.Models;
using Elsa.Webhooks.Abstractions.Persistence;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
namespace Elsa.Activities.Webhooks.Endpoints.WebhookDefinitions
{
[ApiController]
[ApiVersion("1")]
[Route("v{apiVersion:apiVersion}/webhook-definitions/{id}")]
[Produces("application/json")]
public class Delete : ControllerBase
{
private readonly IWebhookDefinitionStore _webhookDefinitionStore;
public Delete(IWebhookDefinitionStore webhookDefinitionStore)
{
_webhookDefinitionStore = webhookDefinitionStore;
}
[HttpDelete]
[ProducesResponseType(StatusCodes.Status202Accepted)]
[SwaggerOperation(
Summary = "Deletes a webhook definition.",
Description = "Deletes a webhook definition.",
OperationId = "WebhookDefinitions.Delete",
Tags = new[] { "WebhookDefinitions" })
]
public async Task<IActionResult> Handle(string id, CancellationToken cancellationToken)
{
var webhookDefinition = !string.IsNullOrWhiteSpace(id) ? await _webhookDefinitionStore.FindAsync(new EntityIdSpecification<WebhookDefinition>(id), cancellationToken) : default;
if (webhookDefinition != null)
{
await _webhookDefinitionStore.DeleteAsync(webhookDefinition, cancellationToken);
}
return Accepted();
}
}
}

View file

@ -16,7 +16,7 @@ namespace Elsa.Activities.Webhooks.Endpoints.WebhookDefinitions
{
[ApiController]
[ApiVersion("1")]
[Route("v{apiVersion:apiVersion}/webhook-definitions/{webhookDefinitionId}")]
[Route("v{apiVersion:apiVersion}/webhook-definitions/{webhookId}")]
[Produces(MediaTypeNames.Application.Json)]
public class Get : Controller
{
@ -30,8 +30,8 @@ namespace Elsa.Activities.Webhooks.Endpoints.WebhookDefinitions
}
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(WorkflowDefinition))]
[SwaggerResponseExample(StatusCodes.Status200OK, typeof(WorkflowDefinitionExample))]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(WebhookDefinition))]
[SwaggerResponseExample(StatusCodes.Status200OK, typeof(WebhookDefinitionExample))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[SwaggerOperation(
Summary = "Returns a single webhook definition.",
@ -39,9 +39,9 @@ namespace Elsa.Activities.Webhooks.Endpoints.WebhookDefinitions
OperationId = "WebhookDefinitions.GetByDefinition",
Tags = new[] { "WebhookDefinitions" })
]
public async Task<IActionResult> Handle(string webhookDefinitionId, CancellationToken cancellationToken = default)
public async Task<IActionResult> Handle(string webhookId, CancellationToken cancellationToken = default)
{
var webhookDefinition = await _webhookDefinitionStore.FindAsync(new EntityIdSpecification<WebhookDefinition>(webhookDefinitionId), cancellationToken);
var webhookDefinition = await _webhookDefinitionStore.FindAsync(new EntityIdSpecification<WebhookDefinition>(webhookId), cancellationToken);
return webhookDefinition == null ? (IActionResult) NotFound() : Json(webhookDefinition, _serializerSettingsProvider.GetSettings());
}
}

View file

@ -2,8 +2,7 @@ namespace Elsa.Activities.Webhooks.Endpoints.WebhookDefinitions
{
public sealed record SaveRequest
{
//public string? Id { get; init; }
public string? WebhookDefinitionId { get; init; }
public string? Id { get; init; }
public string? Path { get; init; }
public string? Name { get; init; }
public string? Description { get; init; }

View file

@ -36,15 +36,15 @@ namespace Elsa.Activities.Webhooks.Endpoints.WebhookDefinitions
]
public async Task<ActionResult<WebhookDefinition>> Handle([FromBody] SaveRequest request, [FromRoute] ApiVersion apiVersion, CancellationToken cancellationToken)
{
var webhookDefinitionId = request.WebhookDefinitionId;
var webhookDefinition = !string.IsNullOrWhiteSpace(webhookDefinitionId) ? await _webhookDefinitionStore.FindAsync(new EntityIdSpecification<WebhookDefinition>(webhookDefinitionId), cancellationToken) : default;
var webhookId = request.Id;
var webhookDefinition = !string.IsNullOrWhiteSpace(webhookId) ? await _webhookDefinitionStore.FindAsync(new EntityIdSpecification<WebhookDefinition>(webhookId), cancellationToken) : default;
if (webhookDefinition == null)
{
webhookDefinition = new WebhookDefinition();
if (!string.IsNullOrWhiteSpace(webhookDefinitionId))
webhookDefinition.DefinitionId = webhookDefinitionId;
if (!string.IsNullOrWhiteSpace(webhookId))
webhookDefinition.Id = webhookId;
}
webhookDefinition.Name = request.Name?.Trim();
@ -55,7 +55,7 @@ namespace Elsa.Activities.Webhooks.Endpoints.WebhookDefinitions
await _webhookDefinitionStore.SaveAsync(webhookDefinition, cancellationToken);
return CreatedAtAction("Handle", "Get", new { definitionId = webhookDefinition.DefinitionId, apiVersion = apiVersion.ToString() }, webhookDefinition);
return CreatedAtAction("Handle", "Get", new { id = webhookDefinition.Id, apiVersion = apiVersion.ToString() }, webhookDefinition);
}
}
}

View file

@ -66,9 +66,6 @@ namespace Elsa.Activities.Webhooks.Persistence.Decorators
{
if (string.IsNullOrWhiteSpace(webhookDefinition.Id))
webhookDefinition.Id = _idGenerator.Generate();
if (string.IsNullOrWhiteSpace(webhookDefinition.DefinitionId))
webhookDefinition.DefinitionId = _idGenerator.Generate();
return webhookDefinition;
}

View file

@ -5,7 +5,6 @@ namespace Elsa.Webhooks.Abstractions.Models
public class WebhookDefinition : IEntity, ITenantScope
{
public string Id { get; set; } = default!;
public string DefinitionId { get; set; } = default!;
public string? TenantId { get; set; }
public string Name { get; set; } = default!;
public string Path { get; set; } = default!;

View file

@ -8,8 +8,6 @@ namespace Elsa.Webhooks.Client.Models
{
[DataMember(Order = 1)] public string Id { get; set; } = default!;
[DataMember(Order = 2)] public string DefinitionId { get; set; } = default!;
[DataMember(Order = 3)] public string? TenantId { get; set; }
[DataMember(Order = 4)] public string Name { get; set; } = default!;

View file

@ -6,8 +6,6 @@ namespace Elsa.Webhooks.Client.Models
{
[DataMember(Order = 1)] public string Id { get; set; } = default!;
[DataMember(Order = 2)] public string DefinitionId { get; set; } = default!;
[DataMember(Order = 3)] public string? TenantId { get; set; }
[DataMember(Order = 4)] public string Name { get; set; } = default!;

View file

@ -8,7 +8,6 @@ namespace Elsa.Webhooks.Persistence.EntityFramework.Core.Configuration
{
public void Configure(EntityTypeBuilder<WebhookDefinition> builder)
{
builder.HasIndex(x => new { x.DefinitionId}).HasDatabaseName($"IX_{nameof(WebhookDefinition)}_{nameof(WebhookDefinition.DefinitionId)}").IsUnique();
builder.HasIndex(x => x.TenantId).HasDatabaseName($"IX_{nameof(WebhookDefinition)}_{nameof(WebhookDefinition.TenantId)}");
builder.HasIndex(x => x.Path).HasDatabaseName($"IX_{nameof(WebhookDefinition)}_{nameof(WebhookDefinition.Path)}");
builder.HasIndex(x => x.Name).HasDatabaseName($"IX_{nameof(WebhookDefinition)}_{nameof(WebhookDefinition.Name)}");

View file

@ -1,15 +1,12 @@
using System;
using System.Linq.Expressions;
using AutoMapper;
using Elsa.Persistence.EntityFramework.Core.Services;
using Elsa.Persistence.EntityFramework.Core.Stores;
using Elsa.Persistence.Specifications;
using Elsa.Serialization;
using Elsa.Webhooks.Abstractions.Models;
using Elsa.Webhooks.Abstractions.Persistence;
using Elsa.Webhooks.Persistence.EntityFramework.Core.Services;
//using Elsa.Webhooks.Persistence.EntityFramework.Core.Services;
using AutoMapper;
namespace Elsa.Webhooks.Persistence.EntityFramework.Core.Stores
{
@ -23,41 +20,5 @@ namespace Elsa.Webhooks.Persistence.EntityFramework.Core.Stores
}
protected override Expression<Func<WebhookDefinition, bool>> MapSpecification(ISpecification<WebhookDefinition> specification) => AutoMapSpecification(specification);
//protected override void OnSaving(WebhookContext dbContext, WebhookDefinition entity)
//{
// //var data = new
// //{
// // entity.Activities,
// // entity.Connections,
// // entity.Variables,
// // entity.ContextOptions,
// // entity.CustomAttributes
// //};
// //var json = _contentSerializer.Serialize(data);
// //dbContext.Entry(entity).Property("Data").CurrentValue = json;
//}
//protected override void OnLoading(WebhookContext dbContext, WebhookDefinition entity)
//{
// //var data = new
// //{
// // entity.Activities,
// // entity.Connections,
// // entity.Variables,
// // entity.ContextOptions,
// // entity.CustomAttributes
// //};
// //var json = (string)dbContext.Entry(entity).Property("Data").CurrentValue;
// //data = JsonConvert.DeserializeAnonymousType(json, data, DefaultContentSerializer.CreateDefaultJsonSerializationSettings());
// //entity.Activities = data.Activities;
// //entity.Connections = data.Connections;
// //entity.Variables = data.Variables;
// //entity.ContextOptions = data.ContextOptions;
// //entity.CustomAttributes = data.CustomAttributes;
//}
}
}

View file

@ -1,4 +1,4 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Elsa.Webhooks.Persistence.EntityFramework.MySql.Migrations
{
@ -15,8 +15,6 @@ namespace Elsa.Webhooks.Persistence.EntityFramework.MySql.Migrations
{
Id = table.Column<string>(type: "varchar(255)", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
DefinitionId = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
TenantId = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Name = table.Column<string>(type: "longtext", nullable: false)

View file

@ -21,10 +21,6 @@ namespace Elsa.Webhooks.Persistence.EntityFramework.MySql.Migrations
b.Property<string>("Id")
.HasColumnType("varchar(255)");
b.Property<string>("DefinitionId")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Description")
.HasColumnType("longtext");

View file

@ -1,4 +1,4 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Elsa.Webhooks.Persistence.EntityFramework.PostgreSql.Migrations
{
@ -11,7 +11,6 @@ namespace Elsa.Webhooks.Persistence.EntityFramework.PostgreSql.Migrations
columns: table => new
{
Id = table.Column<string>(type: "text", nullable: false),
DefinitionId = table.Column<string>(type: "text", nullable: false),
TenantId = table.Column<string>(type: "text", nullable: true),
Name = table.Column<string>(type: "text", nullable: false),
Path = table.Column<string>(type: "text", nullable: false),

View file

@ -1,4 +1,4 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Elsa.Webhooks.Persistence.EntityFramework.SqlServer.Migrations
{
@ -11,7 +11,6 @@ namespace Elsa.Webhooks.Persistence.EntityFramework.SqlServer.Migrations
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
DefinitionId = table.Column<string>(type: "nvarchar(max)", nullable: false),
TenantId = table.Column<string>(type: "nvarchar(max)", nullable: true),
Name = table.Column<string>(type: "nvarchar(max)", nullable: false),
Path = table.Column<string>(type: "nvarchar(max)", nullable: false),

View file

@ -1,4 +1,4 @@
// <auto-generated />
// <auto-generated />
using Elsa.Webhooks.Persistence.EntityFramework.Core;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@ -15,7 +15,7 @@ namespace Elsa.Webhooks.Persistence.EntityFramework.SqlServer.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "5.0.6")
.HasAnnotation("ProductVersion", "5.0.6")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Elsa.Webhooks.Abstractions.Models.WebhookDefinition", b =>

View file

@ -1,4 +1,4 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Elsa.Webhooks.Persistence.EntityFramework.Sqlite.Migrations
{
@ -11,7 +11,6 @@ namespace Elsa.Webhooks.Persistence.EntityFramework.Sqlite.Migrations
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
DefinitionId = table.Column<string>(type: "TEXT", nullable: false),
TenantId = table.Column<string>(type: "TEXT", nullable: true),
Name = table.Column<string>(type: "TEXT", nullable: false),
Path = table.Column<string>(type: "TEXT", nullable: false),

View file

@ -27,12 +27,11 @@ namespace Elsa.Webhooks.Persistence.MongoDb.Services
{
var builder = Builders<WebhookDefinition>.IndexKeys;
var tenantKeysDefinition = builder.Ascending(x => x.TenantId);
var definitionIdKeysDefinition = builder.Ascending(x => x.DefinitionId);
var nameKeysDefinition = builder.Ascending(x => x.Name);
var webhookDefinitionIdDefinition = builder.Ascending(x => x.DefinitionId);
var webhookIdDefinition = builder.Ascending(x => x.Id);
var collection = _mongoContext.WebhookDefinitions;
await CreateIndexesAsync(_mongoContext.WebhookDefinitions, cancellationToken, tenantKeysDefinition, definitionIdKeysDefinition, nameKeysDefinition);
await collection.Indexes.CreateOneAsync(new CreateIndexModel<WebhookDefinition>(webhookDefinitionIdDefinition, new CreateIndexOptions { Unique = true }), cancellationToken: cancellationToken);
await CreateIndexesAsync(_mongoContext.WebhookDefinitions, cancellationToken, tenantKeysDefinition, webhookIdDefinition, nameKeysDefinition);
await collection.Indexes.CreateOneAsync(new CreateIndexModel<WebhookDefinition>(webhookIdDefinition, new CreateIndexOptions { Unique = true }), cancellationToken: cancellationToken);
}
private async Task CreateIndexesAsync<T>(IMongoCollection<T> collection, CancellationToken cancellationToken, params IndexKeysDefinition<T>[] definitions)

View file

@ -4,7 +4,7 @@ namespace Elsa.Webhooks.Persistence.YesSql.Documents
{
public class WebhookDefinitionDocument : YesSqlDocument
{
public string DefinitionId { get; set; } = default!;
public string Id { get; set; } = default!;
public string? TenantId { get; set; }
public string? Name { get; set; }
public string? Path { get; set; }

View file

@ -6,7 +6,7 @@ namespace Elsa.Webhooks.Persistence.YesSql.Indexes
{
public class WebhookDefinitionIndex : MapIndex
{
public string DefinitionId { get; set; } = default!;
public string Id { get; set; } = default!;
public string? TenantId { get; set; }
public bool IsEnabled { get; set; }
}
@ -21,7 +21,7 @@ namespace Elsa.Webhooks.Persistence.YesSql.Indexes
.Map(
webhookDefinition => new WebhookDefinitionIndex
{
DefinitionId = webhookDefinition.DefinitionId,
Id = webhookDefinition.Id,
TenantId = webhookDefinition.TenantId,
IsEnabled = webhookDefinition.IsEnabled
}

View file

@ -11,8 +11,8 @@ namespace Elsa.Webhooks.Persistence.YesSql
{
SchemaBuilder.CreateMapIndexTable<WebhookDefinitionIndex>(
table => table
.Column<string>(nameof(WebhookDefinitionIndex.Id))
.Column<string?>(nameof(WebhookDefinitionIndex.TenantId))
.Column<string>(nameof(WebhookDefinitionIndex.DefinitionId))
.Column<bool>(nameof(WebhookDefinitionIndex.IsEnabled)),
CollectionNames.WebhookDefinitions);

View file

@ -23,14 +23,13 @@ namespace Elsa.Webhooks.Persistence.YesSql.Stores
{
}
protected override async Task<WebhookDefinitionDocument?> FindDocumentAsync(ISession session, WebhookDefinition entity, CancellationToken cancellationToken) => await Query<WebhookDefinitionIndex>(session, x => x.DefinitionId == entity.Id).FirstOrDefaultAsync();
protected override async Task<WebhookDefinitionDocument?> FindDocumentAsync(ISession session, WebhookDefinition entity, CancellationToken cancellationToken) => await Query<WebhookDefinitionIndex>(session, x => x.Id == entity.Id).FirstOrDefaultAsync();
protected override IQuery<WebhookDefinitionDocument> MapSpecification(ISession session, ISpecification<WebhookDefinition> specification)
{
return specification switch
{
EntityIdSpecification<WebhookDefinition> s => Query<WebhookDefinitionIndex>(session, x => x.DefinitionId == s.Id),
//VersionOptionsSpecification s => Query<WebhookDefinitionIndex>(session),
EntityIdSpecification<WebhookDefinition> s => Query<WebhookDefinitionIndex>(session, x => x.Id == s.Id),
_ => AutoMapSpecification<WebhookDefinitionIndex>(session, specification)
};
}

View file

@ -195,19 +195,15 @@ export namespace Components {
}
interface ElsaWebhookDefinitionEditorScreen {
"getServerUrl": () => Promise<string>;
"getWebhookDefinitionId": () => Promise<string>;
"getWebhookId": () => Promise<string>;
"monacoLibPath": string;
"serverUrl": string;
"webhookDefinitionId": string;
"webhookId": string;
}
interface ElsaWebhookDefinitionsListScreen {
"history"?: RouterHistory;
"serverUrl": string;
}
interface ElsaWebhookSaveButton {
"saving": boolean;
"webhookDefinition": WebhookDefinition;
}
interface ElsaWorkflowBlueprintViewerScreen {
"getServerUrl": () => Promise<string>;
"serverUrl": string;
@ -476,12 +472,6 @@ declare global {
prototype: HTMLElsaWebhookDefinitionsListScreenElement;
new (): HTMLElsaWebhookDefinitionsListScreenElement;
};
interface HTMLElsaWebhookSaveButtonElement extends Components.ElsaWebhookSaveButton, HTMLStencilElement {
}
var HTMLElsaWebhookSaveButtonElement: {
prototype: HTMLElsaWebhookSaveButtonElement;
new (): HTMLElsaWebhookSaveButtonElement;
};
interface HTMLElsaWorkflowBlueprintViewerScreenElement extends Components.ElsaWorkflowBlueprintViewerScreen, HTMLStencilElement {
}
var HTMLElsaWorkflowBlueprintViewerScreenElement: {
@ -579,7 +569,6 @@ declare global {
"elsa-webhook-definition-editor-notifications": HTMLElsaWebhookDefinitionEditorNotificationsElement;
"elsa-webhook-definition-editor-screen": HTMLElsaWebhookDefinitionEditorScreenElement;
"elsa-webhook-definitions-list-screen": HTMLElsaWebhookDefinitionsListScreenElement;
"elsa-webhook-save-button": HTMLElsaWebhookSaveButtonElement;
"elsa-workflow-blueprint-viewer-screen": HTMLElsaWorkflowBlueprintViewerScreenElement;
"elsa-workflow-definition-editor-notifications": HTMLElsaWorkflowDefinitionEditorNotificationsElement;
"elsa-workflow-definition-editor-screen": HTMLElsaWorkflowDefinitionEditorScreenElement;
@ -776,17 +765,12 @@ declare namespace LocalJSX {
"monacoLibPath"?: string;
"onWebhookSaved"?: (event: CustomEvent<WebhookDefinition>) => void;
"serverUrl"?: string;
"webhookDefinitionId"?: string;
"webhookId"?: string;
}
interface ElsaWebhookDefinitionsListScreen {
"history"?: RouterHistory;
"serverUrl"?: string;
}
interface ElsaWebhookSaveButton {
"onSaveClicked"?: (event: CustomEvent<any>) => void;
"saving"?: boolean;
"webhookDefinition"?: WebhookDefinition;
}
interface ElsaWorkflowBlueprintViewerScreen {
"serverUrl"?: string;
"workflowDefinitionId"?: string;
@ -871,7 +855,6 @@ declare namespace LocalJSX {
"elsa-webhook-definition-editor-notifications": ElsaWebhookDefinitionEditorNotifications;
"elsa-webhook-definition-editor-screen": ElsaWebhookDefinitionEditorScreen;
"elsa-webhook-definitions-list-screen": ElsaWebhookDefinitionsListScreen;
"elsa-webhook-save-button": ElsaWebhookSaveButton;
"elsa-workflow-blueprint-viewer-screen": ElsaWorkflowBlueprintViewerScreen;
"elsa-workflow-definition-editor-notifications": ElsaWorkflowDefinitionEditorNotifications;
"elsa-workflow-definition-editor-screen": ElsaWorkflowDefinitionEditorScreen;
@ -924,7 +907,6 @@ declare module "@stencil/core" {
"elsa-webhook-definition-editor-notifications": LocalJSX.ElsaWebhookDefinitionEditorNotifications & JSXBase.HTMLAttributes<HTMLElsaWebhookDefinitionEditorNotificationsElement>;
"elsa-webhook-definition-editor-screen": LocalJSX.ElsaWebhookDefinitionEditorScreen & JSXBase.HTMLAttributes<HTMLElsaWebhookDefinitionEditorScreenElement>;
"elsa-webhook-definitions-list-screen": LocalJSX.ElsaWebhookDefinitionsListScreen & JSXBase.HTMLAttributes<HTMLElsaWebhookDefinitionsListScreenElement>;
"elsa-webhook-save-button": LocalJSX.ElsaWebhookSaveButton & JSXBase.HTMLAttributes<HTMLElsaWebhookSaveButtonElement>;
"elsa-workflow-blueprint-viewer-screen": LocalJSX.ElsaWorkflowBlueprintViewerScreen & JSXBase.HTMLAttributes<HTMLElsaWorkflowBlueprintViewerScreenElement>;
"elsa-workflow-definition-editor-notifications": LocalJSX.ElsaWorkflowDefinitionEditorNotifications & JSXBase.HTMLAttributes<HTMLElsaWorkflowDefinitionEditorNotificationsElement>;
"elsa-workflow-definition-editor-screen": LocalJSX.ElsaWorkflowDefinitionEditorScreen & JSXBase.HTMLAttributes<HTMLElsaWorkflowDefinitionEditorScreenElement>;

View file

@ -6,11 +6,12 @@ import {createElsaClient, SaveWebhookDefinitionRequest} from "../../../../servic
import {pluginManager} from '../../../../services/plugin-manager';
import state from '../../../../utils/store';
import Tunnel, {WebhookEditorState} from '../../../../data/webhook-editor';
//import {ActivityContextMenuState, WorkflowDesignerMode} from "../../../designers/tree/elsa-designer-tree/models";
import {MonacoValueChangedArgs} from "../../../controls/elsa-monaco/elsa-monaco";
import {MarkerSeverity} from "monaco-editor";
import {checkBox, FormContext, selectField, SelectOption, textArea, textInput} from "../../../../utils/forms";
//import {registerClickOutside} from "stencil-click-outside";
interface VariableDefinition {
name?: string;
value?: string
}
@Component({
tag: 'elsa-webhook-definition-editor-screen',
@ -23,14 +24,15 @@ export class ElsaWebhookDefinitionEditorScreen {
}
@Event() webhookSaved: EventEmitter<WebhookDefinition>;
@Prop({attribute: 'webhook-definition-id', reflect: true}) webhookDefinitionId: string;
@Prop({attribute: 'webhook-definition-id', reflect: true}) webhookId: string;
@Prop({attribute: 'server-url', reflect: true}) serverUrl: string;
@Prop({attribute: 'monaco-lib-path', reflect: true}) monacoLibPath: string;
//@Prop() webhookDefinitionInternal: WebhookDefinition;
@State() webhookDefinition: WebhookDefinition;
@State() webhookModel: WebhookModel;
@State() saving: boolean;
@State() saved: boolean;
@State() networkError: string;
monacoEditor: HTMLElsaMonacoElement;
formContext: FormContext;
el: HTMLElement;
@ -40,20 +42,26 @@ export class ElsaWebhookDefinitionEditorScreen {
}
@Method()
async getWebhookDefinitionId(): Promise<string> {
return this.webhookDefinition.definitionId;
async getWebhookId(): Promise<string> {
return this.webhookDefinition.id;
}
@Watch('webhookDefinitionId')
async webhookDefinitionIdChangedHandler(newValue: string) {
const webhookDefinitionId = newValue;
let webhookDefinition: WebhookDefinition = ElsaWebhookDefinitionEditorScreen.createWebhookDefinition();
webhookDefinition.definitionId = webhookDefinitionId;
const client = createElsaClient(this.serverUrl);
@Watch('webhookDefinition')
handleWebhookDefinitionChanged(newValue: WebhookDefinition) {
this.webhookDefinition = {...newValue};
this.formContext = new FormContext(this.webhookDefinition, newValue => this.webhookDefinition = newValue);
}
if (webhookDefinitionId && webhookDefinitionId.length > 0) {
@Watch('webhookId')
async webhookIdChangedHandler(newValue: string) {
const webhookId = newValue;
let webhookDefinition: WebhookDefinition = ElsaWebhookDefinitionEditorScreen.createWebhookDefinition();
webhookDefinition.id = webhookId;
const client = createElsaClient(this.serverUrl);
debugger
if (webhookId && webhookId.length > 0) {
try {
webhookDefinition = await client.webhookDefinitionsApi.getByDefinition(webhookDefinitionId);
webhookDefinition = await client.webhookDefinitionsApi.getByWebhookId(webhookId);
} catch {
console.warn(`The specified webhook definition does not exist. Creating a new one.`)
}
@ -62,21 +70,10 @@ export class ElsaWebhookDefinitionEditorScreen {
this.updateWebhookDefinition(webhookDefinition);
}
//@Watch('webhookDefinition')
//handleWebhookDefinitionChanged(newValue: WebhookDefinition) {
// this.webhookDefinition = {...newValue};
//this.formContext = new FormContext(this.webhookDefinition, newValue => this.webhookDefinition = newValue);
//}
@Watch("serverUrl")
async serverUrlChangedHandler(newValue: string) {
}
@Watch("monacoLibPath")
async monacoLibPathChangedHandler(newValue: string) {
state.monacoLibPath = newValue;
}
//@Listen('webhook-changed')
//async webhookChangedHandler(event: CustomEvent<WebhookModel>) {
//const webhookModel = event.detail;
@ -85,26 +82,20 @@ export class ElsaWebhookDefinitionEditorScreen {
async componentWillLoad() {
await this.serverUrlChangedHandler(this.serverUrl);
await this.webhookDefinitionIdChangedHandler(this.webhookDefinitionId);
await this.monacoLibPathChangedHandler(this.monacoLibPath);
await this.webhookIdChangedHandler(this.webhookId);
await this.handleWebhookDefinitionChanged(this.webhookDefinition);
}
updateWebhookDefinition(value: WebhookDefinition) {
this.webhookDefinition = value;
//this.webhookModel = this.mapWorkflowModel(value);
}
async saveWebhook() {
async saveWebhook(webhookModel?: WebhookModel) {
if (!this.serverUrl || this.serverUrl.length == 0)
return;
webhookModel = webhookModel || this.webhookModel;
const client = createElsaClient(this.serverUrl);
let webhookDefinition = this.webhookDefinition;
const request: SaveWebhookDefinitionRequest = {
webhookDefinitionId: webhookDefinition.definitionId || this.webhookDefinitionId,
webhookId: webhookDefinition.id || this.webhookId,
name: webhookDefinition.name,
path: webhookDefinition.path,
description: webhookDefinition.description,
@ -112,58 +103,37 @@ export class ElsaWebhookDefinitionEditorScreen {
isEnabled: webhookDefinition.isEnabled,
};
//this.saving = !publish;
//this.publishing = publish;
try {
webhookDefinition = await client.webhookDefinitionsApi.save(request);
this.webhookDefinition = webhookDefinition;
this.saving = false;
setTimeout(() => this.saved = false, 500);
this.webhookSaved.emit(webhookDefinition);
} catch (e) {
console.error(e);
this.saving = false;
this.saved = false;
}
catch (e) {
console.error(e);
this.networkError = e.message;
setTimeout(() => this.networkError = null, 10000);
}
}
async onSaveClicked(e: Event) {
e.preventDefault();
`debugger`
await this.saveWebhook();
updateWebhookDefinition(value: WebhookDefinition) {
this.webhookDefinition = value;
}
onMonacoValueChanged(e: MonacoValueChangedArgs) {
// Don't try and parse JSON if it contains errors.
const errorCount = e.markers.filter(x => x.severity == MarkerSeverity.Error).length;
if (errorCount > 0)
return;
const newValue = e.value;
let data = this.webhookDefinition.variables ? this.webhookDefinition.variables.data || {} : {};
try {
data = newValue.indexOf('{') >= 0 ? JSON.parse(newValue) : {};
} catch (e) {
} finally {
this.webhookDefinition = {...this.webhookDefinition, variables: {data: data}};
}
}
async onSaveClicked(e: Event) {
e.preventDefault();
await this.saveWebhook();
}
render() {
const tunnelState: WebhookEditorState = {
serverUrl: this.serverUrl,
webhookDefinitionId: this.webhookDefinition.definitionId
webhookId: this.webhookDefinition.id
};
return (
<Host class="elsa-flex elsa-flex-col elsa-w-full" ref={el => this.el = el}>
<form onSubmit={e => this.onSaveClicked(e)}>
<div class="elsa-px-8 mb-8">
<div class="elsa-border-b elsa-border-gray-200">
@ -232,9 +202,7 @@ export class ElsaWebhookDefinitionEditorScreen {
private static createWebhookDefinition(): WebhookDefinition {
return {
definitionId: null,
//version: 1,
//activities: [],
id: null,
};
}
}

View file

@ -1,62 +0,0 @@
import {Component, Host, h, Prop, State, Event, EventEmitter, Watch} from '@stencil/core';
import {enter, leave, toggle} from 'el-transition'
import {registerClickOutside} from "stencil-click-outside";
import {WebhookDefinition} from "../../../../models/webhook";
import {createElsaClient} from "../../../../services/elsa-client";
import Tunnel from '../../../../data/workflow-editor';
@Component({
tag: 'elsa-webhook-save-button',
shadow: false,
})
export class ElsaWebhookSaveButton {
@Prop() webhookDefinition: WebhookDefinition;
@Prop() saving: boolean;
@Event({bubbles: true}) saveClicked: EventEmitter;
//menu: HTMLElement;
onSaveClick() {
this.saveClicked.emit();
//leave(this.menu);
}
render() {
return (
<span class="elsa-relative elsa-z-0 elsa-inline-flex elsa-shadow-sm elsa-rounded-md">
{this.saving ? this.renderSavingButton() : this.renderSaveButton()}
<span class="-elsa-ml-px elsa-relative elsa-block">
</span>
</span>
);
}
renderSaveButton() {
return (
<button type="button"
onClick={() => this.onSaveClick()}
class="elsa-relative elsa-inline-flex elsa-items-center elsa-px-4 elsa-py-2 elsa-rounded-l-md elsa-border elsa-border-gray-300 elsa-bg-white elsa-text-sm elsa-font-medium elsa-text-gray-700 hover:elsa-bg-gray-50 focus:elsa-z-10 focus:elsa-outline-none focus:elsa-ring-1 focus:elsa-ring-blue-500 focus:elsa-border-blue-500">
Save
</button>);
}
renderSavingButton() {
return (
<button type="button"
disabled={true}
class="elsa-relative elsa-inline-flex elsa-items-center elsa-px-4 elsa-py-2 elsa-rounded-l-md elsa-border elsa-border-gray-300 elsa-bg-white elsa-text-sm elsa-font-medium elsa-text-gray-700 hover:elsa-bg-gray-50 focus:elsa-z-10 focus:elsa-outline-none focus:elsa-ring-1 focus:elsa-ring-blue-500 focus:elsa-border-blue-500">
<svg class="elsa-animate-spin -elsa-ml-1 elsa-mr-3 elsa-h-5 elsa-w-5 elsa-text-blue-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="elsa-opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
<path class="elsa-opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"/>
</svg>
Saving
</button>);
}
}
Tunnel.injectProps(ElsaWebhookSaveButton, ['serverUrl']);

View file

@ -1,38 +0,0 @@
# elsa-webhook-save-button
<!-- Auto Generated Below -->
## Properties
| Property | Attribute | Description | Type | Default |
| ------------------- | --------- | ----------- | ------------------- | ----------- |
| `saving` | `saving` | | `boolean` | `undefined` |
| `webhookDefinition` | -- | | `WebhookDefinition` | `undefined` |
## Events
| Event | Description | Type |
| ------------- | ----------- | ------------------ |
| `saveClicked` | | `CustomEvent<any>` |
## Dependencies
### Depends on
- context-consumer
### Graph
```mermaid
graph TD;
elsa-webhook-save-button --> context-consumer
style elsa-webhook-save-button fill:#f9f,stroke:#333,stroke-width:4px
```
----------------------------------------------
*Built with [StencilJS](https://stenciljs.com/)*

View file

@ -27,7 +27,7 @@ export class ElsaWebhookDefinitionsListScreen {
return;
const elsaClient = this.createClient();
await elsaClient.webhookDefinitionsApi.delete(webhookDefinition.definitionId);
await elsaClient.webhookDefinitionsApi.delete(webhookDefinition.id);
await this.loadWebhookDefinitions();
}
@ -43,12 +43,11 @@ export class ElsaWebhookDefinitionsListScreen {
}
render() {
const webhookDefinitions = this.webhookDefinitions.items;
const groupings = collection.groupBy(webhookDefinitions, 'definitionId');
const webhookDefinitions = this.webhookDefinitions;
const list = collection.orderBy(webhookDefinitions, 'name');
return (
<div>
{this.webhookDefinitions.items.length}
<div class="elsa-align-middle elsa-inline-block elsa-min-w-full elsa-border-b elsa-border-gray-200">
<table class="elsa-min-w-full">
<thead>
@ -64,9 +63,9 @@ export class ElsaWebhookDefinitionsListScreen {
</tr>
</thead>
<tbody class="elsa-bg-white elsa-divide-y elsa-divide-gray-100">
{collection.map(groupings, group => {
const names = collection.orderBy(group, 'name', 'desc');
const webhookDefinition: WebhookDefinitionSummary = names[0];
{collection.map(list, item => {
const webhookDefinition: WebhookDefinitionSummary = item;
let webhookDisplayName = webhookDefinition.name;
if (!webhookDisplayName || webhookDisplayName.trim().length == 0)
@ -75,7 +74,8 @@ export class ElsaWebhookDefinitionsListScreen {
if (!webhookDisplayName || webhookDisplayName.trim().length == 0)
webhookDisplayName = 'Untitled';
const editUrl = `/webhook-definitions/${webhookDefinition.definitionId}`;
debugger
const editUrl = `/webhook-definitions/${webhookDefinition.id}`;
const editIcon = (
<svg class="elsa-h-5 elsa-w-5 elsa-text-gray-500" width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">

View file

@ -31,7 +31,7 @@ export class ElsaWorkflowDefinitionSettingsModal {
this.formContext = new FormContext(this.workflowDefinitionInternal, newValue => this.workflowDefinitionInternal = newValue);
}
componentWillLoad() {
componentWillLoad() {
this.handleWorkflowDefinitionChanged(this.workflowDefinition);
}

View file

@ -44,7 +44,7 @@ export class ElsaWorkflowDefinitionsListScreen {
render() {
const workflowDefinitions = this.workflowDefinitions.items;
const groupings = collection.groupBy(workflowDefinitions, 'definitionId');
const groupings = collection.groupBy(workflowDefinitions, 'id');
return (
<div>

View file

@ -2,13 +2,13 @@ import {createProviderConsumer} from "@stencil/state-tunnel";
import {h} from "@stencil/core";
export interface WebhookEditorState {
webhookDefinitionId: string;
webhookId: string;
serverUrl: string;
}
export default createProviderConsumer<WebhookEditorState>(
{
webhookDefinitionId: null,
webhookId: null,
serverUrl: null
},
(subscribe, child) => (<context-consumer subscribe={subscribe} renderer={child}/>)

View file

@ -2,27 +2,20 @@ import {Map} from '../../utils/utils';
export interface WebhookDefinition {
id?: string;
definitionId?: string;
tenantId?: string;
name?: string;
path?: string;
description?: string;
payloadTypeName?: string;
isEnabled?: boolean;
variables?: Variables;
}
export interface WebhookDefinitionSummary {
id?: string;
definitionId?: string;
tenantId?: string;
name?: string;
path?: string;
description?: string;
payloadTypeName?: string;
isEnabled?: boolean;
}
export interface Variables {
data: Map<any>;
}
}

View file

@ -1,5 +1,4 @@
export const EventTypes = {
//ShowWorkflowSettings: 'show-workflow-settings',
UpdateWebhook: 'update-webhook',
WebhookModelChanged: 'webhook-model-changed',
WebhookSaved: 'webhook-saved',

View file

@ -1,2 +1,2 @@
export interface WebhookModel {
}
}

View file

@ -23,12 +23,11 @@ export const createElsaClient = function (serverUrl: string): ElsaClient {
const httpClient = axios.create(config);
return {
activitiesApi: {
activitiesApi: {
list: async () => {
const response = await httpClient.get<Array<ActivityDescriptor>>('v1/activities');
debugger;
return response.data;
}
}
},
workflowDefinitionsApi: {
list: async (page?: number, pageSize?: number, versionOptions?: VersionOptions) => {
@ -83,16 +82,16 @@ export const createElsaClient = function (serverUrl: string): ElsaClient {
const response = await httpClient.get<PagedList<WebhookDefinitionSummary>>(`v1/webhook-definitions`);
return response.data;
},
getByDefinition: async (definitionId: string) => {
const response = await httpClient.get<WebhookDefinition>(`v1/webhook-definitions/${definitionId}`);
getByWebhookId: async (webhookId: string) => {
const response = await httpClient.get<WebhookDefinition>(`v1/webhook-definitions/${webhookId}`);
return response.data;
},
save: async request => {
const response = await httpClient.post<WebhookDefinition>('v1/webhook-definitions', request);
return response.data;
},
delete: async definitionId => {
await httpClient.delete(`v1/webhook-definitions/${definitionId}`);
delete: async webhookId => {
await httpClient.delete(`v1/webhook-definitions/${webhookId}`);
},
},
workflowRegistryApi: {
@ -226,11 +225,11 @@ export interface WebhookDefinitionsApi {
list(page?: number, pageSize?: number): Promise<PagedList<WebhookDefinitionSummary>>;
getByDefinition(definitionId: string): Promise<WebhookDefinition>;
getByWebhookId(webhookId: string): Promise<WebhookDefinition>;
save(request: SaveWebhookDefinitionRequest): Promise<WebhookDefinition>;
delete(definitionId: string): Promise<void>;
delete(webhookId: string): Promise<void>;
}
export interface WorkflowRegistryApi {
@ -296,7 +295,7 @@ export interface SaveWorkflowDefinitionRequest {
}
export interface SaveWebhookDefinitionRequest {
webhookDefinitionId?: string;
webhookId?: string;
name?: string;
path?: string;
description?: string;