Add dropdown control
This commit is contained in:
parent
9c6c141516
commit
3b7e5aff57
|
|
@ -19,7 +19,7 @@ namespace Elsa.Activities.Entity
|
|||
public string? EntityName { get; set; }
|
||||
|
||||
[ActivityProperty(
|
||||
UIHint = ActivityPropertyUIHints.DropdownList,
|
||||
UIHint = ActivityPropertyUIHints.Dropdown,
|
||||
Hint = "The Entity Changed Action to observe. Matches any action if no value is specified.",
|
||||
Options = new[] { "Added", "Updated", "Deleted" }
|
||||
)]
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace Elsa.Activities.Http
|
|||
/// The HTTP method to use.
|
||||
/// </summary>
|
||||
[ActivityProperty(
|
||||
UIHint = ActivityPropertyUIHints.DropdownList,
|
||||
UIHint = ActivityPropertyUIHints.Dropdown,
|
||||
Hint = "The HTTP method to use when making the request.",
|
||||
Options = new[] { "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD" }
|
||||
)]
|
||||
|
|
@ -63,7 +63,7 @@ namespace Elsa.Activities.Http
|
|||
/// The Content Type header to send along with the request body.
|
||||
/// </summary>
|
||||
[ActivityProperty(
|
||||
UIHint = ActivityPropertyUIHints.DropdownList,
|
||||
UIHint = ActivityPropertyUIHints.Dropdown,
|
||||
Hint = "The content type to send with the request.",
|
||||
Options = new[] { "text/plain", "text/html", "application/json", "application/xml" }
|
||||
)]
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Elsa.Activities.Http
|
|||
{
|
||||
[Action(
|
||||
Category = "HTTP",
|
||||
DisplayName = "Write HTTP Response",
|
||||
DisplayName = "HTTP Response",
|
||||
Description = "Write an HTTP response.",
|
||||
Outcomes = new[] { OutcomeNames.Done }
|
||||
)]
|
||||
|
|
@ -34,7 +34,7 @@ namespace Elsa.Activities.Http
|
|||
/// The HTTP status code to return.
|
||||
/// </summary>
|
||||
[ActivityProperty(
|
||||
UIHint = ActivityPropertyUIHints.DropdownList,
|
||||
UIHint = ActivityPropertyUIHints.Dropdown,
|
||||
Hint = "The HTTP status code to write.",
|
||||
Options = new[] { HttpStatusCode.OK, HttpStatusCode.Created, HttpStatusCode.Accepted, HttpStatusCode.NoContent, HttpStatusCode.Redirect, HttpStatusCode.BadRequest, HttpStatusCode.NotFound, HttpStatusCode.Conflict }
|
||||
)]
|
||||
|
|
@ -50,7 +50,7 @@ namespace Elsa.Activities.Http
|
|||
/// The Content-Type header to send along with the response.
|
||||
/// </summary>
|
||||
[ActivityProperty(
|
||||
UIHint = ActivityPropertyUIHints.DropdownList,
|
||||
UIHint = ActivityPropertyUIHints.Dropdown,
|
||||
Hint = "The HTTP content type header to write.",
|
||||
Options = new[]{ "text/plain", "text/html", "application/json", "application/xml" }
|
||||
)]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace Elsa.Design
|
|||
public const string Checkbox = "checkbox";
|
||||
public const string CheckList = "check-list";
|
||||
public const string RadioList = "radio-list";
|
||||
public const string DropdownList = "dropdown-list";
|
||||
public const string Dropdown = "dropdown";
|
||||
|
||||
/// <summary>
|
||||
/// A list that allows the user to enter zero or more values.
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace Elsa.Activities.ControlFlow
|
|||
}
|
||||
|
||||
[ActivityProperty(
|
||||
UIHint = ActivityPropertyUIHints.DropdownList,
|
||||
UIHint = ActivityPropertyUIHints.Dropdown,
|
||||
Hint = "WaitAll: wait for all incoming activities to have executed. WaitAny: continue execution as soon as any of the incoming activity has executed.",
|
||||
Options = new[] { "WaitAll", "WaitAny" }
|
||||
)]
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ namespace Elsa.Metadata
|
|||
return ActivityPropertyUIHints.SingleLine;
|
||||
|
||||
if (typeof(IEnumerable).IsAssignableFrom(type))
|
||||
return ActivityPropertyUIHints.DropdownList;
|
||||
return ActivityPropertyUIHints.Dropdown;
|
||||
|
||||
return ActivityPropertyUIHints.SingleLine;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ export namespace Components {
|
|||
"activityModel": ActivityModel;
|
||||
"icon": string;
|
||||
}
|
||||
interface ElsaDropdownProperty {
|
||||
"propertyDescriptor": ActivityPropertyDescriptor;
|
||||
"propertyModel": ActivityDefinitionProperty;
|
||||
}
|
||||
interface ElsaModalDialog {
|
||||
"hide": (animate: boolean) => Promise<void>;
|
||||
"show": (animate: boolean) => Promise<void>;
|
||||
|
|
@ -95,6 +99,12 @@ declare global {
|
|||
prototype: HTMLElsaDesignerTreeActivityElement;
|
||||
new (): HTMLElsaDesignerTreeActivityElement;
|
||||
};
|
||||
interface HTMLElsaDropdownPropertyElement extends Components.ElsaDropdownProperty, HTMLStencilElement {
|
||||
}
|
||||
var HTMLElsaDropdownPropertyElement: {
|
||||
prototype: HTMLElsaDropdownPropertyElement;
|
||||
new (): HTMLElsaDropdownPropertyElement;
|
||||
};
|
||||
interface HTMLElsaModalDialogElement extends Components.ElsaModalDialog, HTMLStencilElement {
|
||||
}
|
||||
var HTMLElsaModalDialogElement: {
|
||||
|
|
@ -138,6 +148,7 @@ declare global {
|
|||
"elsa-checkbox-property": HTMLElsaCheckboxPropertyElement;
|
||||
"elsa-designer-tree": HTMLElsaDesignerTreeElement;
|
||||
"elsa-designer-tree-activity": HTMLElsaDesignerTreeActivityElement;
|
||||
"elsa-dropdown-property": HTMLElsaDropdownPropertyElement;
|
||||
"elsa-modal-dialog": HTMLElsaModalDialogElement;
|
||||
"elsa-monaco": HTMLElsaMonacoElement;
|
||||
"elsa-text-property": HTMLElsaTextPropertyElement;
|
||||
|
|
@ -169,6 +180,10 @@ declare namespace LocalJSX {
|
|||
"onEdit-activity"?: (event: CustomEvent<ActivityModel>) => void;
|
||||
"onRemove-activity"?: (event: CustomEvent<ActivityModel>) => void;
|
||||
}
|
||||
interface ElsaDropdownProperty {
|
||||
"propertyDescriptor"?: ActivityPropertyDescriptor;
|
||||
"propertyModel"?: ActivityDefinitionProperty;
|
||||
}
|
||||
interface ElsaModalDialog {
|
||||
}
|
||||
interface ElsaMonaco {
|
||||
|
|
@ -203,6 +218,7 @@ declare namespace LocalJSX {
|
|||
"elsa-checkbox-property": ElsaCheckboxProperty;
|
||||
"elsa-designer-tree": ElsaDesignerTree;
|
||||
"elsa-designer-tree-activity": ElsaDesignerTreeActivity;
|
||||
"elsa-dropdown-property": ElsaDropdownProperty;
|
||||
"elsa-modal-dialog": ElsaModalDialog;
|
||||
"elsa-monaco": ElsaMonaco;
|
||||
"elsa-text-property": ElsaTextProperty;
|
||||
|
|
@ -221,6 +237,7 @@ declare module "@stencil/core" {
|
|||
"elsa-checkbox-property": LocalJSX.ElsaCheckboxProperty & JSXBase.HTMLAttributes<HTMLElsaCheckboxPropertyElement>;
|
||||
"elsa-designer-tree": LocalJSX.ElsaDesignerTree & JSXBase.HTMLAttributes<HTMLElsaDesignerTreeElement>;
|
||||
"elsa-designer-tree-activity": LocalJSX.ElsaDesignerTreeActivity & JSXBase.HTMLAttributes<HTMLElsaDesignerTreeActivityElement>;
|
||||
"elsa-dropdown-property": LocalJSX.ElsaDropdownProperty & JSXBase.HTMLAttributes<HTMLElsaDropdownPropertyElement>;
|
||||
"elsa-modal-dialog": LocalJSX.ElsaModalDialog & JSXBase.HTMLAttributes<HTMLElsaModalDialogElement>;
|
||||
"elsa-monaco": LocalJSX.ElsaMonaco & JSXBase.HTMLAttributes<HTMLElsaMonacoElement>;
|
||||
"elsa-text-property": LocalJSX.ElsaTextProperty & JSXBase.HTMLAttributes<HTMLElsaTextPropertyElement>;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export class ElsaCheckListProperty {
|
|||
<div class="flex items-center h-5">
|
||||
<input id={inputId} type="checkbox" checked={isSelected} value={option} onChange={e => this.onCheckChanged(e)} class="focus:ring-blue-500 h-4 w-4 text-blue-600 border-gray-300 rounded"/>
|
||||
</div>
|
||||
<div class="ml-3 text-sm">
|
||||
<div class="ml-3 mt-1 text-sm">
|
||||
<label htmlFor={inputId} class="font-medium text-gray-700">{option}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import {Component, h, Prop, State} from '@stencil/core';
|
||||
import {ActivityDefinitionProperty, ActivityPropertyDescriptor} from "../../../../models";
|
||||
|
||||
@Component({
|
||||
tag: 'elsa-dropdown-property',
|
||||
styleUrl: 'elsa-dropdown-property.css',
|
||||
shadow: false,
|
||||
})
|
||||
export class ElsaDropdownProperty {
|
||||
|
||||
@Prop() propertyDescriptor: ActivityPropertyDescriptor;
|
||||
@Prop() propertyModel: ActivityDefinitionProperty;
|
||||
@State() currentValue?: string;
|
||||
|
||||
async componentWillLoad() {
|
||||
this.currentValue = this.propertyModel.expression || '';
|
||||
}
|
||||
|
||||
onChanged(e: Event) {
|
||||
const select = (e.target as HTMLSelectElement);
|
||||
this.currentValue = select.value;
|
||||
}
|
||||
|
||||
render() {
|
||||
const propertyDescriptor = this.propertyDescriptor;
|
||||
const propertyName = propertyDescriptor.name;
|
||||
const fieldId = propertyName;
|
||||
const fieldName = propertyName;
|
||||
const fieldLabel = propertyDescriptor.label || propertyName;
|
||||
const fieldHint = propertyDescriptor.hint;
|
||||
const options = propertyDescriptor.options as Array<any>;
|
||||
const value = this.currentValue;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<label htmlFor={fieldId} class="block text-sm font-medium text-gray-700">
|
||||
{fieldLabel}
|
||||
</label>
|
||||
|
||||
<select id={fieldId} name={fieldName} class="mt-1 block focus:ring-blue-500 focus:border-blue-500 w-full shadow-sm sm:max-w-xs sm:text-sm border-gray-300 rounded-md">
|
||||
{options.map((option, index) => <option value={option} selected={option === value}>{option}</option>)}
|
||||
</select>
|
||||
|
||||
{fieldHint ? <p class="mt-2 text-sm text-gray-500">{fieldHint}</p> : undefined}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -73,55 +73,51 @@ export class ElsaTextProperty {
|
|||
const property = this.propertyModel;
|
||||
const value = this.currentValue;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<label htmlFor={fieldId} class="block text-sm font-medium text-gray-700">
|
||||
{fieldLabel}
|
||||
</label>
|
||||
<div class="mb-2">
|
||||
<div class="sm:hidden">
|
||||
<label htmlFor="tabs" class="sr-only">Select a tab</label>
|
||||
<select id="tabs" name="tabs" onChange={e => {
|
||||
this.onSyntaxListChange(e)
|
||||
}} class="block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm rounded-md">
|
||||
{syntaxes.map(syntax => {
|
||||
const isSelected = syntax == selectedSyntax;
|
||||
return (
|
||||
<option selected={isSelected}>{syntax}</option>
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
<div class="hidden sm:block">
|
||||
<nav class="flex flex-row-reverse" aria-label="Tabs">
|
||||
{syntaxes.map(syntax => {
|
||||
const isSelected = syntax == selectedSyntax;
|
||||
const className = isSelected ? 'bg-blue-100 text-blue-700' : 'text-gray-500 hover:text-gray-700';
|
||||
return <div>
|
||||
|
||||
return (
|
||||
<a href="#" onClick={e => {
|
||||
this.onSyntaxSelect(e, syntax)
|
||||
}} data-syntax={syntax} class={`${className} px-3 py-2 font-medium text-sm rounded-md`}>
|
||||
<div class="flex">
|
||||
<div class="">
|
||||
<label htmlFor={fieldId} class="block text-sm font-medium text-gray-700">
|
||||
{fieldLabel}
|
||||
</label>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="">
|
||||
<div class="sm:hidden">
|
||||
<label htmlFor="tabs" class="sr-only">Select a tab</label>
|
||||
<select id="tabs" name="tabs" onChange={e => this.onSyntaxListChange(e)} class="block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm rounded-md">
|
||||
{syntaxes.map(syntax => {
|
||||
return <option selected={syntax == selectedSyntax}>{syntax}</option>;
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
<div class="hidden sm:block">
|
||||
<nav class="flex flex-row-reverse" aria-label="Tabs">
|
||||
{syntaxes.map(syntax => {
|
||||
const isSelected = syntax == selectedSyntax;
|
||||
const className = isSelected ? 'bg-blue-100 text-blue-700' : 'text-gray-500 hover:text-gray-700';
|
||||
|
||||
return <a href="#" onClick={e => this.onSyntaxSelect(e, syntax)} data-syntax={syntax} class={`${className} px-3 py-2 font-medium text-sm rounded-md`}>
|
||||
{syntax}
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
</a>;
|
||||
})}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<elsa-monaco value={value}
|
||||
language={monacoLanguage}
|
||||
editor-height={this.editorHeight}
|
||||
single-line={this.singleLineMode}
|
||||
onValueChanged={e => this.onMonacoValueChanged(e.detail)}
|
||||
ref={el => this.monacoEditor = el}/>
|
||||
</div>
|
||||
{fieldHint ? <p class="mt-2 text-sm text-gray-500">{fieldHint}</p> : undefined}
|
||||
<input type="hidden" name={fieldName} value={value}/>
|
||||
<input type="hidden" name={syntaxFieldName} value={selectedSyntax}/>
|
||||
</div>
|
||||
)
|
||||
<div class="mt-1">
|
||||
<elsa-monaco value={value}
|
||||
language={monacoLanguage}
|
||||
editor-height={this.editorHeight}
|
||||
single-line={this.singleLineMode}
|
||||
onValueChanged={e => this.onMonacoValueChanged(e.detail)}
|
||||
ref={el => this.monacoEditor = el}/>
|
||||
</div>
|
||||
{fieldHint ? <p class="mt-2 text-sm text-gray-500">{fieldHint}</p> : undefined}
|
||||
<input type="hidden" name={fieldName} value={value}/>
|
||||
<input type="hidden" name={syntaxFieldName} value={selectedSyntax}/>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
import {PropertyDisplayDriver} from "../services/property-display-driver";
|
||||
import {ActivityModel, ActivityPropertyDescriptor} from "../models";
|
||||
import {h} from "@stencil/core";
|
||||
import {getProperty, setActivityModelProperty} from "../utils/utils";
|
||||
|
||||
export class DropdownDriver implements PropertyDisplayDriver {
|
||||
|
||||
display(activity: ActivityModel, property: ActivityPropertyDescriptor) {
|
||||
const key = `${activity.activityId}:${property.name}`;
|
||||
const prop = getProperty(activity.properties, property.name);
|
||||
|
||||
return (
|
||||
<div class="sm:col-span-6">
|
||||
<elsa-dropdown-property propertyDescriptor={property} propertyModel={prop}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
update(activity: ActivityModel, property: ActivityPropertyDescriptor, form: FormData) {
|
||||
const value = form.get(property.name) as string;
|
||||
setActivityModelProperty(activity, property.name, value, 'Literal');
|
||||
}
|
||||
}
|
||||
|
|
@ -3,3 +3,4 @@ export * from './single-line-driver';
|
|||
export * from './multiline-driver';
|
||||
export * from './check-list-driver';
|
||||
export * from './checkbox-driver';
|
||||
export * from './dropdown-driver';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import {ActivityModel, ActivityPropertyDescriptor} from "../models/";
|
||||
import {PropertyDisplayDriver} from "./property-display-driver";
|
||||
import {CheckBoxDriver, CheckListDriver, MultilineDriver, NullPropertyDriver, SingleLineDriver} from "../property-display-drivers";
|
||||
import {CheckBoxDriver, CheckListDriver, DropdownDriver, MultilineDriver, NullPropertyDriver, SingleLineDriver} from "../property-display-drivers";
|
||||
import {Map} from '../utils/utils';
|
||||
|
||||
export type PropertyDisplayDriverMap = Map<() => PropertyDisplayDriver>;
|
||||
|
|
@ -14,7 +14,8 @@ export class PropertyDisplayManager {
|
|||
'single-line': () => new SingleLineDriver(),
|
||||
'multi-line': () => new MultilineDriver(),
|
||||
'check-list': () => new CheckListDriver(),
|
||||
'checkbox': () => new CheckBoxDriver()
|
||||
'checkbox': () => new CheckBoxDriver(),
|
||||
'dropdown': () => new DropdownDriver()
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue