MultiText enhancement when Options are provided.

This commit is contained in:
tomy2105 2021-04-28 11:15:48 +02:00 committed by Sipke Schoorstra
parent 27e0e76884
commit bbe3aa22fd
4 changed files with 159 additions and 6 deletions

View file

@ -0,0 +1,17 @@
:host {
display: block;
}
.tag-input:focus {
outline: none !important;
box-shadow: none !important;
}
.pr-8 {
padding-right: 2rem !important;
}
.bg-green-350 {
--tw-bg-opacity: 1;
background-color: rgba(52,191,113,var(--tw-bg-opacity));
}

View file

@ -0,0 +1,112 @@
import { Component, h, Prop, Event, EventEmitter, State, Watch } from '@stencil/core';
import { MultiTextDefinition } from '../../../models/domain';
@Component({
tag: 'elsa-input-tags-dropdown',
styleUrl: 'elsa-input-tags-dropdown.css',
shadow: false,
})
export class ElsaInputTagsDropdown {
@Prop() fieldName?: string;
@Prop() fieldId?: string;
@Prop() placeHolder?: string = 'Add tag';
@Prop() values?: Array<string | MultiTextDefinition> = [];
@Prop() dropdownValues?: Array<MultiTextDefinition> = [];
@Event({ bubbles: true }) valueChanged: EventEmitter<Array<string | MultiTextDefinition>>;
@State() currentValues?: Array<MultiTextDefinition> = [];
@State() dropdownTags?: Array<MultiTextDefinition> = [];
@Watch('values')
valuesChangedHandler(newValue: Array<string | MultiTextDefinition>) {
let values: Array<MultiTextDefinition> = [];
newValue.forEach(value => {
this.dropdownValues.forEach(tag => {
if (value === tag.value) {
values.push(tag);
}
})
})
this.currentValues = values || [];
}
componentWillLoad() {
this.dropdownTags = this.dropdownValues;
let values: Array<MultiTextDefinition> = [];
this.values.forEach(value => {
this.dropdownValues.forEach(tag => {
if (value === tag.value) {
values.push(tag);
}
})
})
this.currentValues = values;
const tagsToRemove: Array<string> = this.currentValues.map(tag => tag.value);
this.dropdownTags = this.dropdownTags.filter(tag => !tagsToRemove.includes(tag.value));
}
async onTagSelected(e: any) {
e.preventDefault();
const input = e.target as HTMLSelectElement;
const currentTag: MultiTextDefinition = {
text: input.options[input.selectedIndex].text.trim(),
value: input.value
}
if (currentTag.value.length == 0)
return;
const values: Array<MultiTextDefinition> = [...this.currentValues];
values.push(currentTag);
this.currentValues = values.distinct();
input.value = "Add";
this.dropdownTags = this.dropdownTags.filter(tag => tag.value !== currentTag.value);
await this.valueChanged.emit(values);
}
async onDeleteTagClick(e: any, currentTag: MultiTextDefinition) {
e.preventDefault();
this.currentValues = this.currentValues.filter(tag => tag.value !== currentTag.value);
this.dropdownTags = [...this.dropdownTags, currentTag].sort((tag1, tag2) => tag1.value.localeCompare(tag2.value));
await this.valueChanged.emit(this.currentValues);
}
render() {
let values: Array<MultiTextDefinition> = this.currentValues || [];
if (!Array.isArray(values))
values = [];
const valuesJson = JSON.stringify(values.map(tag => tag.value));
return (
<div class="py-2 px-3 bg-white shadow-sm border border-gray-300 rounded-md">
{values.map(tag =>
(
<a href="#" onClick={e => this.onDeleteTagClick(e, tag)} class="inline-block text-xs bg-blue-400 text-white py-2 px-3 mr-1 mb-1 rounded">
<input type="hidden" value={tag.value} />
<span>{tag.text}</span>
<span class="text-white hover:text-white ml-1">&times;</span>
</a>
))}
<select id={this.fieldId} class="inline-block text-xs bg-green-350 text-white py-2 px-3 mr-1 mb-1 pr-8 rounded" onChange={(e) => this.onTagSelected(e)}>
<option value="Add" disabled selected>{this.placeHolder}</option>
{this.dropdownTags.map(tag =>
(
<option value={tag.value}>
<span>{tag.text}</span>
</option>
)
)}
</select>
<input type="hidden" name={this.fieldName} value={valuesJson} />
</div>
)
}
}

View file

@ -1,5 +1,5 @@
import {Component, h, Prop, State} from '@stencil/core';
import {ActivityDefinitionProperty, ActivityPropertyDescriptor, SyntaxNames} from "../../../../models";
import {ActivityDefinitionProperty, ActivityPropertyDescriptor, SyntaxNames, MultiTextDefinition} from "../../../../models";
import {parseJson} from "../../../../utils/utils";
@Component({
@ -11,14 +11,20 @@ export class ElsaMultiTextProperty {
@Prop() propertyDescriptor: ActivityPropertyDescriptor;
@Prop() propertyModel: ActivityDefinitionProperty;
@State() currentValue?: string
@State() currentValue?: string;
async componentWillLoad() {
this.currentValue = this.propertyModel.expressions[SyntaxNames.Json] || '[]';
}
onValueChanged(newValue: Array<string>){
this.currentValue = JSON.stringify(newValue);
onValueChanged(newValue: Array<string | MultiTextDefinition>) {
const newValues = newValue.map(dropdown => {
if (typeof dropdown === 'string') return dropdown;
return dropdown.value;
})
this.currentValue = JSON.stringify(newValues);
this.propertyModel.expressions[SyntaxNames.Json] = this.currentValue;
}
@ -26,6 +32,13 @@ export class ElsaMultiTextProperty {
this.currentValue = e.detail;
}
createKeyValueOptions(options: Array<MultiTextDefinition>) {
if (options === null)
return options;
return options.map(option => typeof option === 'string' ? { text: option, value: option } : option);
}
render() {
const propertyDescriptor = this.propertyDescriptor;
const propertyModel = this.propertyModel;
@ -33,14 +46,20 @@ export class ElsaMultiTextProperty {
const fieldId = propertyName;
const fieldName = propertyName;
const values = parseJson(this.currentValue);
const valueType = propertyDescriptor.options !== null ? 'dropdown' : 'multi-text';
const propertyOptions = this.createKeyValueOptions(propertyDescriptor.options);
const elsaInputTags = valueType === 'multi-text' ?
<elsa-input-tags values={values} fieldId={fieldId} fieldName={fieldName} onValueChanged={e => this.onValueChanged(e.detail)} /> :
<elsa-input-tags-dropdown dropdownValues={propertyOptions} values={values} fieldId={fieldId} fieldName={fieldName} onValueChanged={e => this.onValueChanged(e.detail)} />;
return (
<elsa-property-editor propertyDescriptor={propertyDescriptor}
propertyModel={propertyModel}
onDefaultSyntaxValueChanged={e => this.onDefaultSyntaxValueChanged(e)}
editor-height="2em"
single-line={true}>
<elsa-input-tags values={values} fieldId={fieldId} fieldName={fieldName} onValueChanged={e => this.onValueChanged(e.detail)}/>
{elsaInputTags}
</elsa-property-editor>
)
}

View file

@ -168,6 +168,11 @@ export interface ConnectionDefinitionMapped {
outcome: string;
}
export interface MultiTextDefinition {
text: string;
value: string;
}
export interface ActivityDefinitionProperty {
name: string;
syntax?: string;