From 418d7edca9d1564384609de30df87c7a86f8081a Mon Sep 17 00:00:00 2001 From: axeleron007 Date: Mon, 27 Sep 2021 13:31:57 +0300 Subject: [PATCH] Json schema ad hoc validation added and code clean up --- .../Activities/HttpEndpoint/HttpEndpoint.cs | 8 +-- .../Design/ActivityInputUIHints.cs | 1 - .../elsa-workflows-studio/package-lock.json | 7 +- .../elsa-workflows-studio/package.json | 1 + .../elsa-workflows-studio/src/components.d.ts | 17 ----- .../elsa-script-property.tsx | 64 ++++++++++++++++++- .../elsa-url-property/elsa-url-property.tsx | 49 -------------- ...elsa-workflow-definition-editor-screen.tsx | 4 +- .../src/drivers/index.ts | 3 +- .../src/drivers/url-driver.tsx | 12 ---- .../src/plugins/default-drivers-plugin.ts | 3 +- 11 files changed, 73 insertions(+), 96 deletions(-) delete mode 100644 src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-url-property/elsa-url-property.tsx delete mode 100644 src/designer/elsa-workflows-studio/src/drivers/url-driver.tsx diff --git a/src/activities/Elsa.Activities.Http/Activities/HttpEndpoint/HttpEndpoint.cs b/src/activities/Elsa.Activities.Http/Activities/HttpEndpoint/HttpEndpoint.cs index 9c573e33b..51332cf03 100644 --- a/src/activities/Elsa.Activities.Http/Activities/HttpEndpoint/HttpEndpoint.cs +++ b/src/activities/Elsa.Activities.Http/Activities/HttpEndpoint/HttpEndpoint.cs @@ -62,13 +62,7 @@ namespace Elsa.Activities.Http Category = PropertyCategories.Advanced, UIHint = ActivityInputUIHints.CodeEditor, OptionsProvider = typeof(HttpEndpoint))] - public string? Schema { get; set; } - - [ActivityInput( - Category = PropertyCategories.Advanced, - DefaultValue = "https://extendsclass.com/json-schema-validator.html", - UIHint = ActivityInputUIHints.Url)] - public string? OnlineConverter { get; set; } + public string? Schema { get; set; } [ActivityInput( Hint = "Check to allow authenticated requests only", diff --git a/src/core/Elsa.Abstractions/Design/ActivityInputUIHints.cs b/src/core/Elsa.Abstractions/Design/ActivityInputUIHints.cs index 7c5871cfa..e554cba9f 100644 --- a/src/core/Elsa.Abstractions/Design/ActivityInputUIHints.cs +++ b/src/core/Elsa.Abstractions/Design/ActivityInputUIHints.cs @@ -10,7 +10,6 @@ namespace Elsa.Design public const string Dropdown = "dropdown"; public const string MultiText = "multi-text"; public const string CodeEditor = "code-editor"; - public const string Url = "url"; /// /// An editor that allows the user to write a blob of JSON. diff --git a/src/designer/elsa-workflows-studio/package-lock.json b/src/designer/elsa-workflows-studio/package-lock.json index 47bce63b9..f0a20813a 100644 --- a/src/designer/elsa-workflows-studio/package-lock.json +++ b/src/designer/elsa-workflows-studio/package-lock.json @@ -1,17 +1,17 @@ { "name": "@elsa-workflows/elsa-workflows-studio", "version": "2.2.4", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@elsa-workflows/elsa-workflows-studio", - "version": "2.2.0", + "version": "2.2.4", "license": "MIT", "dependencies": { "@fullhuman/postcss-purgecss": "^4.0.3", "@microsoft/signalr": "^5.0.9", - "@stencil/core": "^2.8.0", + "@stencil/core": "^2.8.1", "@stencil/postcss": "^2.0.0", "@stencil/router": "^1.0.1", "@stencil/state-tunnel": "^1.0.1", @@ -20,6 +20,7 @@ "@tailwindcss/forms": "^0.3.3", "@tailwindcss/jit": "^0.1.18", "@tailwindcss/typography": "^0.4.1", + "ajv": "^6.12.6", "autoprefixer": "10.2.6", "axios": "^0.21.1", "axios-middleware": "^0.3.1", diff --git a/src/designer/elsa-workflows-studio/package.json b/src/designer/elsa-workflows-studio/package.json index aa7c07fba..c32fc1360 100644 --- a/src/designer/elsa-workflows-studio/package.json +++ b/src/designer/elsa-workflows-studio/package.json @@ -44,6 +44,7 @@ "@tailwindcss/forms": "^0.3.3", "@tailwindcss/jit": "^0.1.18", "@tailwindcss/typography": "^0.4.1", + "ajv": "^6.12.6", "autoprefixer": "10.2.6", "axios": "^0.21.1", "axios-middleware": "^0.3.1", diff --git a/src/designer/elsa-workflows-studio/src/components.d.ts b/src/designer/elsa-workflows-studio/src/components.d.ts index 2bdbd4d4d..283d6e5e2 100644 --- a/src/designer/elsa-workflows-studio/src/components.d.ts +++ b/src/designer/elsa-workflows-studio/src/components.d.ts @@ -229,10 +229,6 @@ export namespace Components { "hide": () => Promise; "show": (options: ToastNotificationOptions) => Promise; } - interface ElsaUrlProperty { - "propertyDescriptor": ActivityPropertyDescriptor; - "propertyModel": ActivityDefinitionProperty; - } interface ElsaWebhookDefinitionEditorNotifications { } interface ElsaWebhookDefinitionEditorScreen { @@ -579,12 +575,6 @@ declare global { prototype: HTMLElsaToastNotificationElement; new (): HTMLElsaToastNotificationElement; }; - interface HTMLElsaUrlPropertyElement extends Components.ElsaUrlProperty, HTMLStencilElement { - } - var HTMLElsaUrlPropertyElement: { - prototype: HTMLElsaUrlPropertyElement; - new (): HTMLElsaUrlPropertyElement; - }; interface HTMLElsaWebhookDefinitionEditorNotificationsElement extends Components.ElsaWebhookDefinitionEditorNotifications, HTMLStencilElement { } var HTMLElsaWebhookDefinitionEditorNotificationsElement: { @@ -728,7 +718,6 @@ declare global { "elsa-tab-content": HTMLElsaTabContentElement; "elsa-tab-header": HTMLElsaTabHeaderElement; "elsa-toast-notification": HTMLElsaToastNotificationElement; - "elsa-url-property": HTMLElsaUrlPropertyElement; "elsa-webhook-definition-editor-notifications": HTMLElsaWebhookDefinitionEditorNotificationsElement; "elsa-webhook-definition-editor-screen": HTMLElsaWebhookDefinitionEditorScreenElement; "elsa-webhook-definitions-list-screen": HTMLElsaWebhookDefinitionsListScreenElement; @@ -963,10 +952,6 @@ declare namespace LocalJSX { } interface ElsaToastNotification { } - interface ElsaUrlProperty { - "propertyDescriptor"?: ActivityPropertyDescriptor; - "propertyModel"?: ActivityDefinitionProperty; - } interface ElsaWebhookDefinitionEditorNotifications { } interface ElsaWebhookDefinitionEditorScreen { @@ -1107,7 +1092,6 @@ declare namespace LocalJSX { "elsa-tab-content": ElsaTabContent; "elsa-tab-header": ElsaTabHeader; "elsa-toast-notification": ElsaToastNotification; - "elsa-url-property": ElsaUrlProperty; "elsa-webhook-definition-editor-notifications": ElsaWebhookDefinitionEditorNotifications; "elsa-webhook-definition-editor-screen": ElsaWebhookDefinitionEditorScreen; "elsa-webhook-definitions-list-screen": ElsaWebhookDefinitionsListScreen; @@ -1171,7 +1155,6 @@ declare module "@stencil/core" { "elsa-tab-content": LocalJSX.ElsaTabContent & JSXBase.HTMLAttributes; "elsa-tab-header": LocalJSX.ElsaTabHeader & JSXBase.HTMLAttributes; "elsa-toast-notification": LocalJSX.ElsaToastNotification & JSXBase.HTMLAttributes; - "elsa-url-property": LocalJSX.ElsaUrlProperty & JSXBase.HTMLAttributes; "elsa-webhook-definition-editor-notifications": LocalJSX.ElsaWebhookDefinitionEditorNotifications & JSXBase.HTMLAttributes; "elsa-webhook-definition-editor-screen": LocalJSX.ElsaWebhookDefinitionEditorScreen & JSXBase.HTMLAttributes; "elsa-webhook-definitions-list-screen": LocalJSX.ElsaWebhookDefinitionsListScreen & JSXBase.HTMLAttributes; diff --git a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-script-property/elsa-script-property.tsx b/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-script-property/elsa-script-property.tsx index e34977d1f..7c22a6dac 100644 --- a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-script-property/elsa-script-property.tsx +++ b/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-script-property/elsa-script-property.tsx @@ -3,6 +3,7 @@ import {ActivityDefinitionProperty, ActivityPropertyDescriptor} from "../../../. import {createElsaClient} from "../../../../services/elsa-client"; import Tunnel from '../../../../data/workflow-editor'; import {MonacoValueChangedArgs} from "../../../controls/elsa-monaco/elsa-monaco"; +import Ajv from "ajv" @Component({ tag: 'elsa-script-property', @@ -19,10 +20,12 @@ export class ElsaScriptProperty { @Prop({mutable: true}) serverUrl: string; @Prop({mutable: true}) workflowDefinitionId: string; @State() currentValue?: string + @State() isJsonSchemaValid?: boolean; monacoEditor: HTMLElsaMonacoElement; async componentWillLoad() { this.currentValue = this.propertyModel.expressions['Literal']; + this.validate(this.currentValue); } async componentDidLoad() { @@ -44,8 +47,47 @@ export class ElsaScriptProperty { } } - onMonacoValueChanged(e: MonacoValueChangedArgs) { + onConvertToJsonSchemaClick(e: Event) { + e.preventDefault(); + window.open('https://extendsclass.com/json-schema-validator.html'); + } + + onMonacoValueChanged(e: MonacoValueChangedArgs) { this.currentValue = e.value; + this.validate(e.value); + } + + validate(value: string) { + const propertyDescriptor = this.propertyDescriptor; + const propertyName = propertyDescriptor.name; + const fieldName = propertyName; + + if (fieldName === "Schema") + { + this.isJsonSchemaValid = true; + const ajv = new Ajv(); + let json: object; + try{ + json = JSON.parse(value) + } + catch (e){ + this.isJsonSchemaValid = false; + } + + if (json != undefined) + { + try { + const validate = ajv.compile(json); + const errors = validate.errors; + if (errors != null) + this.isJsonSchemaValid = false; + } + catch (e){ + const err = e; + this.isJsonSchemaValid = false; + } + } + } } render() { @@ -58,6 +100,7 @@ export class ElsaScriptProperty { const fieldLabel = propertyDescriptor.label || propertyName; const fieldHint = propertyDescriptor.hint; const value = this.currentValue; + const isSchema = fieldName === "Schema"; return
@@ -88,7 +131,26 @@ export class ElsaScriptProperty { ref={el => this.monacoEditor = el}/>
{fieldHint ?

{fieldHint}

: undefined} + {this.isJsonSchemaValid == undefined ? undefined : this.isJsonSchemaValid ? +

+ Json is valid +

+ : +

+ Json is invalid +

+ } + {isSchema ? + + : undefined + } } } diff --git a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-url-property/elsa-url-property.tsx b/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-url-property/elsa-url-property.tsx deleted file mode 100644 index 3556e9874..000000000 --- a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-url-property/elsa-url-property.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import {Component, h, Prop, State} from '@stencil/core'; -import {ActivityDefinitionProperty, ActivityPropertyDescriptor, SyntaxNames} from "../../../../models"; - -@Component({ - tag: 'elsa-url-property', - shadow: false, -}) -export class ElsaUrlProperty { - - @Prop() propertyDescriptor: ActivityPropertyDescriptor; - @Prop() propertyModel: ActivityDefinitionProperty; - @State() currentValue: string; - - componentWillLoad() { - const defaultSyntax = this.propertyDescriptor.defaultSyntax || SyntaxNames.Literal; - this.currentValue = this.propertyModel.expressions[defaultSyntax] || undefined; - } - - onUrlClick(e: MouseEvent, url: string) { - e.preventDefault(); - window.open(url, '_blank', 'noopener,noreferrer'); - } - - render() { - const propertyDescriptor = this.propertyDescriptor; - const propertyModel = this.propertyModel; - const propertyName = propertyDescriptor.name; - const fieldLabel = propertyDescriptor.label || propertyName; - let value = this.currentValue; - - if (value == undefined) { - const defaultValue = this.propertyDescriptor.defaultValue; - value = defaultValue ? defaultValue.toString() : undefined; - } - - return ( - - this.onUrlClick(e, value)} - class="elsa-relative elsa-inline-flex elsa-items-center elsa-px-4 elsa-py-2 elsa-border elsa-border-gray-300 elsa-text-sm elsa-leading-5 elsa-font-medium elsa-rounded-md elsa-text-gray-700 elsa-bg-white hover:elsa-text-gray-500 focus:elsa-outline-none focus:elsa-shadow-outline-blue focus:elsa-border-blue-300 active:elsa-bg-gray-100 active:elsa-text-gray-700 elsa-transition elsa-ease-in-out elsa-duration-150"> - {fieldLabel} - - - ) - } -} diff --git a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx index 2eda86a7f..07cac614b 100644 --- a/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx @@ -544,7 +544,7 @@ export class ElsaWorkflowDefinitionEditorScreen { `; -debugger + return (
{this.workflowDesignerMode == WorkflowDesignerMode.Test ? @@ -597,7 +597,7 @@ debugger const value = message.data["Body"]; const request: WorkflowTestUpdateHttpEndpoint = { activityId: message.activityId, - jsonSchema: JSON.stringify(convert(value), null, 4) + jsonSchema: JSON.stringify(convert(value), null, 1) }; await this.updateHttpEndpointJsonSchema(request); diff --git a/src/designer/elsa-workflows-studio/src/drivers/index.ts b/src/designer/elsa-workflows-studio/src/drivers/index.ts index 275541886..78de3ca12 100644 --- a/src/designer/elsa-workflows-studio/src/drivers/index.ts +++ b/src/designer/elsa-workflows-studio/src/drivers/index.ts @@ -8,5 +8,4 @@ export * from './multiline-driver'; export * from './null-property-driver'; export * from './radio-list-driver'; export * from './single-line-driver'; -export * from './switch-case-builder-driver'; -export * from './url-driver'; \ No newline at end of file +export * from './switch-case-builder-driver'; \ No newline at end of file diff --git a/src/designer/elsa-workflows-studio/src/drivers/url-driver.tsx b/src/designer/elsa-workflows-studio/src/drivers/url-driver.tsx deleted file mode 100644 index 5aad77b58..000000000 --- a/src/designer/elsa-workflows-studio/src/drivers/url-driver.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import {PropertyDisplayDriver} from "../services"; -import {ActivityModel, ActivityPropertyDescriptor} from "../models"; -import {h} from "@stencil/core"; -import {getOrCreateProperty} from "../utils/utils"; - -export class UrlDriver implements PropertyDisplayDriver { - - display(activity: ActivityModel, property: ActivityPropertyDescriptor) { - const prop = getOrCreateProperty(activity, property.name); - return ; - } -} diff --git a/src/designer/elsa-workflows-studio/src/plugins/default-drivers-plugin.ts b/src/designer/elsa-workflows-studio/src/plugins/default-drivers-plugin.ts index 4279ee907..54b8aa52b 100644 --- a/src/designer/elsa-workflows-studio/src/plugins/default-drivers-plugin.ts +++ b/src/designer/elsa-workflows-studio/src/plugins/default-drivers-plugin.ts @@ -1,5 +1,5 @@ import {propertyDisplayManager, ElsaPlugin, PropertyDisplayDriver} from "../services"; -import {JsonDriver, RadioListDriver, CheckboxDriver, CheckListDriver, CodeEditorDriver, DropdownDriver, MultilineDriver, MultiTextDriver, SingleLineDriver, SwitchCaseBuilderDriver, UrlDriver} from "../drivers"; +import {JsonDriver, RadioListDriver, CheckboxDriver, CheckListDriver, CodeEditorDriver, DropdownDriver, MultilineDriver, MultiTextDriver, SingleLineDriver, SwitchCaseBuilderDriver} from "../drivers"; import {ElsaStudio} from "../models"; export class DefaultDriversPlugin implements ElsaPlugin { @@ -14,7 +14,6 @@ export class DefaultDriversPlugin implements ElsaPlugin { this.addDriver('multi-text', () => new MultiTextDriver()); this.addDriver('code-editor', () => new CodeEditorDriver()); this.addDriver('switch-case-builder', () => new SwitchCaseBuilderDriver()); - this.addDriver('url', () => new UrlDriver()); } addDriver(controlType: string, c: (elsaStudio: ElsaStudio) => T) {