Json schema ad hoc validation added and code clean up

This commit is contained in:
axeleron007 2021-09-27 13:31:57 +03:00
parent 2c0ffb5b90
commit 418d7edca9
11 changed files with 73 additions and 96 deletions

View file

@ -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",

View file

@ -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";
/// <summary>
/// An editor that allows the user to write a blob of JSON.

View file

@ -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",

View file

@ -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",

View file

@ -229,10 +229,6 @@ export namespace Components {
"hide": () => Promise<void>;
"show": (options: ToastNotificationOptions) => Promise<void>;
}
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<HTMLElsaTabContentElement>;
"elsa-tab-header": LocalJSX.ElsaTabHeader & JSXBase.HTMLAttributes<HTMLElsaTabHeaderElement>;
"elsa-toast-notification": LocalJSX.ElsaToastNotification & JSXBase.HTMLAttributes<HTMLElsaToastNotificationElement>;
"elsa-url-property": LocalJSX.ElsaUrlProperty & JSXBase.HTMLAttributes<HTMLElsaUrlPropertyElement>;
"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>;

View file

@ -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 <div>
@ -88,7 +131,26 @@ export class ElsaScriptProperty {
ref={el => this.monacoEditor = el}/>
</div>
{fieldHint ? <p class="elsa-mt-2 elsa-text-sm elsa-text-gray-500">{fieldHint}</p> : undefined}
{this.isJsonSchemaValid == undefined ? undefined : this.isJsonSchemaValid ?
<p class="elsa-mt-1 elsa-text-sm elsa-text-green-500">
Json is valid
</p>
:
<p class="elsa-mt-1 elsa-text-sm elsa-text-red-500">
Json is invalid
</p>
}
<input type="hidden" name={fieldName} value={value}/>
{isSchema ?
<div class="elsa-mt-1">
<a href="#"
onClick={e => this.onConvertToJsonSchemaClick(e)}
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">
Convert to Json Schema
</a>
</div>
: undefined
}
</div>
}
}

View file

@ -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 (
<elsa-property-editor propertyDescriptor={propertyDescriptor}
propertyModel={propertyModel}
single-line={true}
showLabel={false}>
<a href="#"
onClick={e => 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}
</a>
</elsa-property-editor>
)
}
}

View file

@ -544,7 +544,7 @@ export class ElsaWorkflowDefinitionEditorScreen {
</svg>
</button>
</div>`;
debugger
return (
<div class="elsa-flex-1 elsa-flex elsa-relative" >
{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);

View file

@ -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';
export * from './switch-case-builder-driver';

View file

@ -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 <elsa-url-property propertyDescriptor={property} propertyModel={prop}/>;
}
}

View file

@ -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<T extends PropertyDisplayDriver>(controlType: string, c: (elsaStudio: ElsaStudio) => T) {