diff --git a/projects/workflows-creator/src/lib/builder/builder.component.html b/projects/workflows-creator/src/lib/builder/builder.component.html index 4fc1553..c580a97 100644 --- a/projects/workflows-creator/src/lib/builder/builder.component.html +++ b/projects/workflows-creator/src/lib/builder/builder.component.html @@ -11,7 +11,7 @@ (add)="openPopup(types.GROUP)" (remove)="onGroupRemove(i)" (eventAdded)="onEventAdded($event)" - (eventRemoved)="onEventRemoved()" + (nodeRemoved)="onNodeRemoved()" (actionAdded)="onActionAdded($event)" (itemChanged)="onItemChanged($event)" > @@ -29,6 +29,7 @@ [templateMap]="templateMap" [allColumns]="allColumns" (eventAdded)="onEventAdded($event)" + (nodeRemoved)="onNodeRemoved()" (actionAdded)="onActionAdded($event)" (itemChanged)="onItemChanged($event)" > diff --git a/projects/workflows-creator/src/lib/builder/builder.component.scss b/projects/workflows-creator/src/lib/builder/builder.component.scss index b5e1b4d..495d2d9 100644 --- a/projects/workflows-creator/src/lib/builder/builder.component.scss +++ b/projects/workflows-creator/src/lib/builder/builder.component.scss @@ -25,7 +25,7 @@ } } .container { - min-width: 46%; + min-width: 52%; max-width: max-content; color: rgb(50, 51, 56); margin: auto; diff --git a/projects/workflows-creator/src/lib/builder/builder.component.ts b/projects/workflows-creator/src/lib/builder/builder.component.ts index d346069..d779b16 100644 --- a/projects/workflows-creator/src/lib/builder/builder.component.ts +++ b/projects/workflows-creator/src/lib/builder/builder.component.ts @@ -20,7 +20,16 @@ import { } from '../classes'; import {AbstractBaseGroup} from '../classes/nodes'; import {BuilderService, ElementService, NodeService} from '../classes/services'; -import {EventTypes, LocalizedStringKeys, NodeTypes, ValueTypes} from '../enum'; +import { + ActionTypes, + ConditionTypes, + EventTypes, + LocalizedStringKeys, + NUMBER, + NodeTypes, + NotificationRecipientTypesEnum, + ValueTypes, +} from '../enum'; import {InvalidEntityError} from '../errors/base.error'; import { ActionAddition, @@ -38,6 +47,11 @@ import { WorkflowNode, } from '../types'; import {LocalizationProviderService} from '../services/localization-provider.service'; +import { + ReadColumnValue, + TriggerWhenColumnChanges, +} from '../services/bpmn/elements/tasks'; +import {GatewayElement} from '../services/bpmn/elements/gateways'; @Component({ selector: 'workflow-builder', @@ -78,7 +92,7 @@ export class BuilderComponent implements OnInit, OnChanges { stateChange = new EventEmitter>(); @Output() - diagramChange = new EventEmitter(); + diagramChange = new EventEmitter(); @Output() eventAdded = new EventEmitter>(); @@ -217,7 +231,7 @@ export class BuilderComponent implements OnInit, OnChanges { this.updateDiagram(); this.updateState(event.node, event.newNode.inputs); this.elseBlockHidden = - !this.eventGroups[0]?.children?.length && + this.eventGroups[0]?.children?.length === 1 && (event.node.getIdentifier() === EventTypes.OnIntervalEvent || event.node.getIdentifier() === EventTypes.OnAddItemEvent); } @@ -226,16 +240,9 @@ export class BuilderComponent implements OnInit, OnChanges { * The function is called when an event is removed from the workflow. * Hides the else block when it is not needed. */ - onEventRemoved() { - const events = this.eventGroups[0].children; - - this.elseBlockHidden = - events.length === 1 && - (events[0].node.getIdentifier() === EventTypes.OnIntervalEvent || - events[0].node.getIdentifier() === EventTypes.OnAddItemEvent || - (events[0].node.getIdentifier() === EventTypes.OnChangeEvent && - (events[0].node.state.get('value') === ValueTypes.AnyValue || - events[0].node.state.get('valueType') === ValueTypes.AnyValue))); + onNodeRemoved() { + this.updateDiagram(); + if (this.eventGroups[0]?.children?.length) this.hideElseBlockIfRequired(); } /** @@ -264,19 +271,32 @@ export class BuilderComponent implements OnInit, OnChanges { item: item.element.node, }); this.updateState(item.element.node, item.element.inputs); - // TODO: to be refactored - // to hide else block when anything is selected in ValueInput or ValueTypeInput - this.elseBlockHidden = - this.eventGroups[0].children?.length === 1 && - this.eventGroups[0].children[0].node.getIdentifier() === - EventTypes.OnChangeEvent && - (this.eventGroups[0].children[0].node.state.get('value') === - ValueTypes.AnyValue || - this.eventGroups[0].children[0].node.state.get('valueType') === - ValueTypes.AnyValue); + this.hideElseBlockIfRequired(); this.updateDiagram(); } + /** + * This function checks if the else block should be hidden based on the type and number of events in + * the event group. + */ + hideElseBlockIfRequired() { + const events = this.eventGroups[0].children; + let value = events[0].node.state.get('value'); + if (typeof value === 'object') { + value = value.value; + } + if (events.length !== 1) { + this.elseBlockHidden = false; + } else { + this.elseBlockHidden = + events[0].node.getIdentifier() === EventTypes.OnIntervalEvent || + events[0].node.getIdentifier() === EventTypes.OnAddItemEvent || + (events[0].node.getIdentifier() === EventTypes.OnChangeEvent && + (value === ValueTypes.AnyValue || + events[0].node.state.get('valueType') === ValueTypes.AnyValue)); + } + } + /** * "If the type is a group, then get the groups, otherwise throw an error." * @@ -346,6 +366,31 @@ export class BuilderComponent implements OnInit, OnChanges { value: AllowedValues | AllowedValuesMap, select = false, ) { + if ( + (input.getIdentifier() === 'ValueTypeInput' || + input.getIdentifier() === 'ValueInput') && + element.node.getIdentifier() === 'OnChangeEvent' + ) { + if ( + ((value as AllowedValuesMap)?.value as AllowedValuesMap)?.value === + ValueTypes.AnyValue || + (value as AllowedValuesMap)?.value === ValueTypes.AnyValue + ) { + /** + * Remove node on changes event + */ + element.node.elements.splice(-NUMBER.TWO, NUMBER.TWO); + // element.inputs[1].prefix = ''; + //this.enableActionIcon = false; + } else { + element.node.elements = [ + TriggerWhenColumnChanges.identifier, + ReadColumnValue.identifier, + GatewayElement.identifier, + ]; + } + } + if (select && isSelectInput(input)) { element.node.state.change( `${input.inputKey}Name`, @@ -429,8 +474,58 @@ export class BuilderComponent implements OnInit, OnChanges { * It builds a new diagram, emits the new diagram, and then tells Angular to update the view */ async updateDiagram() { + const nodes = [ + ...this.eventGroups[0].children, + ...this.actionGroups[0].children, + ...this.elseActionGroups[0].children, + ]; + let isValid = + !!this.eventGroups[0].children.length && + (!!this.actionGroups[0].children.length || + !!this.elseActionGroups[0].children.length); + if (isValid) { + for (const node of nodes) { + switch (node.node.getIdentifier()) { + case EventTypes.OnChangeEvent: + case EventTypes.OnValueEvent: + case ActionTypes.ChangeColumnValueAction: + const columnExists = !!node.node.state.get('column'); + const valueExists = + node.node.state.get('condition') === ConditionTypes.PastToday + ? true + : !!node.node.state.get('value'); + const valueTypeIsSufficient = [ + ValueTypes.AnyValue, + ValueTypes.Today, + ValueTypes.PastToday, + ].includes(node.node.state.get('valueType')); + isValid = columnExists && (valueExists || valueTypeIsSufficient); + break; + case EventTypes.OnIntervalEvent: + const intervalExists = !!node.node.state.get('interval'); + const intervalValueExists = !!node.node.state.get('value'); + isValid = intervalValueExists && intervalExists; + break; + case ActionTypes.SendEmailAction: + const email = !!node.node.state.get('email'); + const emailTo = !!node.node.state.get('emailTo'); + const specificRecipientsRequired = [ + NotificationRecipientTypesEnum.NotifySpecificColumn, + NotificationRecipientTypesEnum.NotifySpecificPeople, + ].includes(node.node.state.get('emailTo')); + const recipients = !!node.node.state.get('specificRecepient'); + isValid = specificRecipientsRequired + ? email && emailTo && recipients + : email && emailTo; + break; + } + if (!isValid) { + break; // exit the loop since we found an invalid input + } + } + } this.diagram = await this.build(); - this.diagramChange.emit(this.diagram); + this.diagramChange.emit({diagram: this.diagram, isValid: isValid}); this.cdr.detectChanges(); } diff --git a/projects/workflows-creator/src/lib/builder/group/group.component.html b/projects/workflows-creator/src/lib/builder/group/group.component.html index 46758f9..3c24b04 100644 --- a/projects/workflows-creator/src/lib/builder/group/group.component.html +++ b/projects/workflows-creator/src/lib/builder/group/group.component.html @@ -144,7 +144,8 @@ emailInput: emailInput, appendEmailBody: appendEmailBody, setFocusKey: setFocusKey, - hide: hidePopper() + hide: hidePopper(), + setFocusOutPos: setFocusOutPos } " > @@ -284,6 +285,7 @@ let-appendEmailBody="appendEmailBody" let-setFocusKey="setFocusKey" let-hide="hide" + let-setFocusOutPos="setFocusOutPos" > diff --git a/projects/workflows-creator/src/lib/builder/group/group.component.scss b/projects/workflows-creator/src/lib/builder/group/group.component.scss index 42f2acc..f113dfb 100644 --- a/projects/workflows-creator/src/lib/builder/group/group.component.scss +++ b/projects/workflows-creator/src/lib/builder/group/group.component.scss @@ -71,7 +71,7 @@ .value-text { display: inline-block; overflow: hidden; - max-width: 45%; + max-width: 15rem; text-decoration: inherit; text-overflow: ellipsis; vertical-align: top; diff --git a/projects/workflows-creator/src/lib/builder/group/group.component.ts b/projects/workflows-creator/src/lib/builder/group/group.component.ts index b9e5cdb..fe28b9f 100644 --- a/projects/workflows-creator/src/lib/builder/group/group.component.ts +++ b/projects/workflows-creator/src/lib/builder/group/group.component.ts @@ -86,7 +86,7 @@ export class GroupComponent implements OnInit, AfterViewInit { eventAdded = new EventEmitter(); @Output() - eventRemoved = new EventEmitter(); + nodeRemoved = new EventEmitter(); @Output() actionAdded = new EventEmitter(); @@ -103,6 +103,7 @@ export class GroupComponent implements OnInit, AfterViewInit { subject: '', body: '', focusKey: '', + caretPos: 0, }; dropdownSettings: IDropdownSettings = { singleSelection: false, @@ -134,6 +135,9 @@ export class GroupComponent implements OnInit, AfterViewInit { typeSubjectPlaceholder = ''; typeEmailPlaceholder = ''; + doThisLbl = ''; + whenThisHappensLbl = ''; + setLbl = ''; localizedStringKeys = LocalizedStringKeys; @@ -208,6 +212,14 @@ export class GroupComponent implements OnInit, AfterViewInit { this.templateMap?.[InputTypes.Interval] || this.listTemplate, [InputTypes.Email]: this.templateMap?.[InputTypes.Email] || this.emailTemplate, + [InputTypes.OptionList]: + this.templateMap?.[InputTypes.OptionList] || this.listTemplate, + [InputTypes.Stepper]: + this.templateMap?.[InputTypes.Stepper] || this.listTemplate, + [InputTypes.IntervalDate]: + this.templateMap?.[InputTypes.IntervalDate] || this.listTemplate, + [InputTypes.IntervalTime]: + this.templateMap?.[InputTypes.IntervalTime] || this.listTemplate, }; } @@ -221,6 +233,13 @@ export class GroupComponent implements OnInit, AfterViewInit { if (allowedInputs.includes(input.getIdentifier())) { const value = input.getModelValue(nodeWithInput.node.state); if (nodeWithInput.node.state.get('email')) { + (value as AllowedValuesMap).body = ( + (value as AllowedValuesMap).body as string + ).replace(/\\"/g, '"'); + (value as AllowedValuesMap).subject = ( + (value as AllowedValuesMap).subject as string + ).replace(/\\"/g, '"'); + this.emailInput = value; } else { switch (nodeWithInput.node.state.get('valueInputType')) { @@ -261,11 +280,21 @@ export class GroupComponent implements OnInit, AfterViewInit { */ appendEmailBody(item: Select, emailInput: EmailInput) { if (emailInput.focusKey === 'subject') { - emailInput.subject += ` ${item.value}`; + emailInput.subject = [ + emailInput.subject.slice(0, emailInput.caretPos), + `${item.value}`, + emailInput.subject.slice(emailInput.caretPos), + ].join(''); } if (emailInput.focusKey === 'body') { - emailInput.body += ` ${item.value}`; + emailInput.body = [ + emailInput.body.slice(0, emailInput.caretPos), + `${item.value}`, + emailInput.body.slice(emailInput.caretPos), + ].join(''); } + + emailInput.caretPos += `${item.value}`.length; } /** @@ -278,6 +307,14 @@ export class GroupComponent implements OnInit, AfterViewInit { emailInput.focusKey = key; } + /** + * @emailInput this is the object that contains the email input + * @caretPosition pos caret position + */ + setFocusOutPos(emailInput: EmailInput, caretPosition: number) { + emailInput.caretPos = caretPosition; + } + /** * If the type is an action, set the node list to the actions, otherwise if the type is an event, set * the node list to the trigger events if there is only one event group and no children, otherwise @@ -322,20 +359,20 @@ export class GroupComponent implements OnInit, AfterViewInit { inputs: this.nodes.mapInputs(node), }; if (node.type === NodeTypes.EVENT) { - this.eventAdded.emit({ - node: node, - newNode: newNode, - }); if (newNode.node.getIdentifier() === 'OnIntervalEvent') { newNode.node.state.change('valueInputType', 'number'); } this.group.children.push(newNode as EventWithInput); + this.eventAdded.emit({ + node: node, + newNode: newNode, + }); } else if (node.type === NodeTypes.ACTION) { + this.group.children.push(newNode as ActionWithInput); this.actionAdded.emit({ node: node, newNode: newNode, }); - this.group.children.push(newNode as ActionWithInput); } else { throw new InvalidEntityError('Node'); } @@ -347,7 +384,7 @@ export class GroupComponent implements OnInit, AfterViewInit { */ onNodeRemove(index: number) { this.group.children.splice(index, 1); - this.eventRemoved.emit(); + this.nodeRemoved.emit(); } /** @@ -369,13 +406,24 @@ export class GroupComponent implements OnInit, AfterViewInit { element, input, input.setValue(element.node.state, value), - input.typeFunction(element.node.state) === InputTypes.List, + input.typeFunction(element.node.state) === InputTypes.List || + input.typeFunction(element.node.state) === InputTypes.OptionList, ); + this.clearValues(); } popper.hide(); }; } + private clearValues() { + this.emailInput = { + subject: '', + body: '', + focusKey: '', + caretPos: 0, + }; + } + /** * It hides the previous popper and shows the current popper. * @param {MouseEvent} event - MouseEvent - The event that triggered the popper to show. @@ -470,32 +518,24 @@ export class GroupComponent implements OnInit, AfterViewInit { } } if (select && isSelectInput(input)) { - if ( - element.node.state.get('columnName') === 'Priority' && - input.inputKey !== 'condition' - ) { - element.node.state.change( - `${input.inputKey}Name`, - value as AllowedValuesMap, - ); - this.itemChanged.emit({ - field: input.getIdentifier(), - value: value as AllowedValuesMap, - element: element, - }); - value = value as AllowedValuesMap; - } else { - element.node.state.change( - `${input.inputKey}Name`, - (value as AllowedValuesMap)[input.listNameField], - ); - this.itemChanged.emit({ - field: input.getIdentifier(), - value: (value as AllowedValuesMap)[input.listValueField], - element: element, - }); - value = (value as AllowedValuesMap)[input.listValueField]; - } + element.node.state.change( + `${input.inputKey}Name`, + (value as AllowedValuesMap)[input.listNameField], + ); + value = + input.inputKey === 'value' + ? value + : (value as AllowedValuesMap)[input.listValueField]; + element.node.state.change(input.inputKey, value); + this.handleSubsequentInputs(element, input); + this.itemChanged.emit({ + field: input.getIdentifier(), + value: + input.inputKey === 'value' + ? (value as AllowedValuesMap)[input.listValueField] + : value, + element: element, + }); } element.node.state.change(input.inputKey, value); this.handleSubsequentInputs(element, input); @@ -517,6 +557,9 @@ export class GroupComponent implements OnInit, AfterViewInit { element: NodeWithInput, input: WorkflowPrompt, ) { + if (input.inputKey === 'email') { + return; + } const currentIndex = element.inputs.findIndex( i => i.getIdentifier() === input.getIdentifier(), ); diff --git a/projects/workflows-creator/src/lib/builder/node/node.component.scss b/projects/workflows-creator/src/lib/builder/node/node.component.scss index 4d0acaf..e5435d5 100644 --- a/projects/workflows-creator/src/lib/builder/node/node.component.scss +++ b/projects/workflows-creator/src/lib/builder/node/node.component.scss @@ -6,6 +6,7 @@ position: relative; .workflow-content { flex-grow: 1; + height: 3rem; } .action-icons { cursor: pointer; diff --git a/projects/workflows-creator/src/lib/classes/nodes/abstract-prompt.class.ts b/projects/workflows-creator/src/lib/classes/nodes/abstract-prompt.class.ts index 67afaec..30dda6e 100644 --- a/projects/workflows-creator/src/lib/classes/nodes/abstract-prompt.class.ts +++ b/projects/workflows-creator/src/lib/classes/nodes/abstract-prompt.class.ts @@ -54,6 +54,7 @@ export abstract class WorkflowPrompt { value: AllowedValues | AllowedValuesMap, ) { switch (this.typeFunction(state)) { + case InputTypes.OptionList: case InputTypes.List: return value; case InputTypes.People: { @@ -94,12 +95,19 @@ export abstract class WorkflowPrompt { const dateTime = `${this.onDateSelect(date)} ${hours}:${min}`; return moment(dateTime.toString(), 'DD-MM-YYYY hh:mm').format(); case InputTypes.Email: + (value as AllowedValuesMap).body = ( + (value as AllowedValuesMap).body as string + ).replace(/"/g, '\\"'); + (value as AllowedValuesMap).subject = ( + (value as AllowedValuesMap).subject as string + ).replace(/"/g, '\\"'); (value as AllowedValuesMap).displayValue = 'email'; return value; case InputTypes.Number: case InputTypes.Text: case InputTypes.Boolean: case InputTypes.Percentage: + case InputTypes.Stepper: default: if (value) { return (value as HTMLInputElement).value; @@ -140,6 +148,7 @@ export abstract class WorkflowPrompt { */ getValueName(state: State) { switch (this.typeFunction(state)) { + case InputTypes.OptionList: case InputTypes.List: if (typeof state.get(`${this.inputKey}Name`) === 'object') { return state.get(`${this.inputKey}Name`)?.displayValue; @@ -161,10 +170,14 @@ export abstract class WorkflowPrompt { .utc(state.get(this.inputKey), 'YYYY-MM-DD hh:mm') .format('MMM DD, YYYY hh:mm A') : ''; + case InputTypes.IntervalDate: + case InputTypes.IntervalTime: + return state.get(this.inputKey)?.value; case InputTypes.Number: case InputTypes.Text: case InputTypes.Boolean: case InputTypes.Percentage: + case InputTypes.Stepper: default: return state.get(this.inputKey); } @@ -178,6 +191,7 @@ export abstract class WorkflowPrompt { */ setValueName(state: State) { switch (this.typeFunction(state)) { + case InputTypes.OptionList: case InputTypes.List: if ( typeof state.get(this.inputKey) === 'object' && @@ -200,6 +214,7 @@ export abstract class WorkflowPrompt { case InputTypes.Text: case InputTypes.Boolean: case InputTypes.Percentage: + case InputTypes.Stepper: default: return state.get(this.inputKey); } diff --git a/projects/workflows-creator/src/lib/const.ts b/projects/workflows-creator/src/lib/const.ts index 65c943d..092f4ce 100644 --- a/projects/workflows-creator/src/lib/const.ts +++ b/projects/workflows-creator/src/lib/const.ts @@ -14,14 +14,14 @@ xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_1aj5pzu" targetNamespace="http://bpmn.io/schema/bpmn" -exporter="Camunda Modeler" exporterVersion="4.12.0" +exporter="Camunda Modeler" exporterVersion="5.21.0" modeler:executionPlatform="Camunda Platform" -modeler:executionPlatformVersion="7.15.0"> +modeler:executionPlatformVersion="7.21.0"> `; -export const JSON_SCRIPT_START = `var json = S(\"{}\");\n`; -export const JSON_SCRIPT_END = `\n json`; +export const JSON_SCRIPT_START = `var json = {};\n`; +export const JSON_SCRIPT_END = `\n JSON.stringify(json)`; export const BASE_XML = new InjectionToken('diagram.bpmn.base'); export const MODDLE = new InjectionToken( diff --git a/projects/workflows-creator/src/lib/enum.ts b/projects/workflows-creator/src/lib/enum.ts index 9914cfb..0e9d3da 100644 --- a/projects/workflows-creator/src/lib/enum.ts +++ b/projects/workflows-creator/src/lib/enum.ts @@ -20,6 +20,11 @@ export enum InputTypes { People = 'people', Percentage = 'percentage', Text = 'text', + OptionList = 'optionList', + Item = 'Item', + Stepper = 'Stepper', + IntervalDate = 'IntervalDate', + IntervalTime = 'IntervalTime', } /* Defining the types of conditions that can be used in the application. */ @@ -79,6 +84,11 @@ export enum EventTypes { OnValueEvent = 'OnValueEvent', } +export enum ActionTypes { + ChangeColumnValueAction = 'ChangeColumnValueAction', + SendEmailAction = 'SendEmailAction', +} + export enum StartElementTypes { BasicStartElement = 'StartElement', StartOnIntervalElement = 'StartOnIntervalElement', @@ -101,3 +111,12 @@ export enum LocalizedStringKeys { SelectColumnTooltip = 'selectColumnTooltip', SetLbl = 'setLbl', } + +export enum IntervalType { + Day = 'day', + Days = 'days', + Weeks = 'weeks', + Months = 'months', + Week = 'week', + Month = 'month', +} diff --git a/projects/workflows-creator/src/lib/services/bpmn/builder.service.ts b/projects/workflows-creator/src/lib/services/bpmn/builder.service.ts index 3b9f009..388da48 100644 --- a/projects/workflows-creator/src/lib/services/bpmn/builder.service.ts +++ b/projects/workflows-creator/src/lib/services/bpmn/builder.service.ts @@ -347,7 +347,10 @@ export class BpmnBuilderService extends BuilderService< const [id, key] = property['name'].split('_'); if (state[id]) { try { - state[id][key] = JSON.parse(property['value']); + state[id][key] = + typeof JSON.parse(property['value']) === 'object' + ? JSON.parse(property['value']) + : property['value']; } catch (error) { state[id][key] = property['value']; } diff --git a/projects/workflows-creator/src/lib/services/bpmn/elements/gateways/gateway.element.ts b/projects/workflows-creator/src/lib/services/bpmn/elements/gateways/gateway.element.ts index 6c178e5..74b653f 100644 --- a/projects/workflows-creator/src/lib/services/bpmn/elements/gateways/gateway.element.ts +++ b/projects/workflows-creator/src/lib/services/bpmn/elements/gateways/gateway.element.ts @@ -21,7 +21,7 @@ export class GatewayElement extends BpmnElement { ) { super(); } - tag = 'bpmn:ExclusiveGateway'; + tag = 'bpmn:InclusiveGateway'; name = 'gateway'; properties = {}; statement: string | undefined; diff --git a/projects/workflows-creator/src/lib/services/bpmn/elements/process/process.element.ts b/projects/workflows-creator/src/lib/services/bpmn/elements/process/process.element.ts index 059f7ba..0c30ab4 100644 --- a/projects/workflows-creator/src/lib/services/bpmn/elements/process/process.element.ts +++ b/projects/workflows-creator/src/lib/services/bpmn/elements/process/process.element.ts @@ -30,6 +30,7 @@ export class ProcessElement extends BpmnElement { static identifier = 'ProcessElement'; attributes = { isExecutable: true, + historyTimeToLive: 'P3650D', }; getIdentifier(): string { diff --git a/projects/workflows-creator/src/lib/services/bpmn/elements/tasks/change-column-value.task.ts b/projects/workflows-creator/src/lib/services/bpmn/elements/tasks/change-column-value.task.ts index ce89120..26d9262 100644 --- a/projects/workflows-creator/src/lib/services/bpmn/elements/tasks/change-column-value.task.ts +++ b/projects/workflows-creator/src/lib/services/bpmn/elements/tasks/change-column-value.task.ts @@ -8,6 +8,7 @@ import {CREATE_TASK_STRATEGY} from '../../strategies/create'; import {LINK_BASIC_STRATEGY} from '../../strategies/link'; import {ServiceTaskElement} from './service-task.task'; import {ENV_TOKEN} from '../../../../token'; +import {InputTypes} from '../../../../enum'; @Injectable() export class ChangeColumnValue extends ServiceTaskElement { @@ -41,12 +42,25 @@ export class ChangeColumnValue extends ServiceTaskElement { }, changedValue: { formatter: (state: State) => { - if (typeof state.get('value') === 'object') { - return `'${JSON.stringify(state.get('value'))}'`; + switch (state.get('valueInputType')) { + case InputTypes.People: + return `'${JSON.stringify(state.get('value'))}'`; + case InputTypes.OptionList: + case InputTypes.List: + if (!state.get('value')) return ''; + return `'${JSON.stringify({ + displayValue: state.get('value').text?.split('"').join(''), + value: state.get('value').value, + iconClass: state.get('value').iconClass, + color: state.get('value').color, + bgColor: state.get('value').bgColor, + })}'`; + default: + return `'{"displayValue": "${ + state.get('valueName')?.split('"').join('') ?? + state.get('value') + }", "value": "${state.get('value')}"}'`; } - return `'{"displayValue": "${ - state.get('valueName') ?? state.get('value') - }", "value": "${state.get('value')}"}'`; }, }, }, diff --git a/projects/workflows-creator/src/lib/services/bpmn/elements/tasks/read-column.task.ts b/projects/workflows-creator/src/lib/services/bpmn/elements/tasks/read-column.task.ts index 5d7d7fd..64c116c 100644 --- a/projects/workflows-creator/src/lib/services/bpmn/elements/tasks/read-column.task.ts +++ b/projects/workflows-creator/src/lib/services/bpmn/elements/tasks/read-column.task.ts @@ -32,6 +32,9 @@ export class ReadColumnValue extends ServiceTaskElement { taskIds: { from: 'taskIds', }, + metaData: { + state: 'metaData', + }, groupColumnId: { state: 'column', }, diff --git a/projects/workflows-creator/src/lib/services/bpmn/elements/tasks/send-email.task.ts b/projects/workflows-creator/src/lib/services/bpmn/elements/tasks/send-email.task.ts index fb309e8..f52ef29 100644 --- a/projects/workflows-creator/src/lib/services/bpmn/elements/tasks/send-email.task.ts +++ b/projects/workflows-creator/src/lib/services/bpmn/elements/tasks/send-email.task.ts @@ -54,7 +54,8 @@ export class SendEmail extends ServiceTaskElement { }, }, }; - outputs: string; + + outputs = 'outputVariable'; static identifier = 'SendEmail'; getIdentifier(): string { diff --git a/projects/workflows-creator/src/lib/services/bpmn/strategies/create/basic-interval-create.strategy.ts b/projects/workflows-creator/src/lib/services/bpmn/strategies/create/basic-interval-create.strategy.ts index 8813cf2..61da4f7 100644 --- a/projects/workflows-creator/src/lib/services/bpmn/strategies/create/basic-interval-create.strategy.ts +++ b/projects/workflows-creator/src/lib/services/bpmn/strategies/create/basic-interval-create.strategy.ts @@ -7,7 +7,17 @@ import { ModdleElement, RecordOfAnyType, } from '../../../../types'; -import {WorkflowElement} from '../../../../classes'; +import {State, WorkflowElement} from '../../../../classes'; + +enum WeekDaysEnum { + sunday = 1, + monday = 2, + tuesday = 3, + wednesday = 4, + thursday = 5, + friday = 6, + saturday = 7, +} @Injectable() export class CreateBasicIntervalStrategy @@ -38,9 +48,7 @@ export class CreateBasicIntervalStrategy const state = workflowNode.state; const timeCycle = this.moddle.create('bpmn:FormalExpression', { 'xsi:type': 'bpmn:tFormalExpression', - body: `R/P${state.get('timescale')}${state.get('value')}${state.get( - 'interval', - )}`, + body: this.intervalBodyPrepare(state), }); timerEventDefinition['timeCycle'] = timeCycle; @@ -53,6 +61,53 @@ export class CreateBasicIntervalStrategy }); } + private intervalBodyPrepare(state: State) { + if ( + state.get('interval') === 'M' && + state.get('toInterval') && + state.get('TimeInterval') + ) { + const val = + state.get('value') == 1 + ? '*' + : `${state.get('toInterval').month}/${state.get('value')}`; + const timeZoneDate = new Date(); + timeZoneDate.setHours(state.get('TimeInterval').hour); + timeZoneDate.setMinutes(state.get('TimeInterval').min); + return `0 timeZoneDate(${timeZoneDate})timeZoneDateEnd ${ + state.get('toInterval').date + } ${val} ?`; + } else if ( + state.get('interval') === 'W' && + state.get('toInterval') && + state.get('TimeInterval') + ) { + const val = state.get('value') == 1 ? '' : `/${state.get('value')}`; + let weekDays = state + .get('toInterval') + ?.ids?.map( + (day: string) => WeekDaysEnum[day as keyof typeof WeekDaysEnum], + ) + .join(','); + const timeZoneDate = new Date(); + timeZoneDate.setHours(state.get('TimeInterval').hour); + timeZoneDate.setMinutes(state.get('TimeInterval').min); + return `0 timeZoneDate(${timeZoneDate})timeZoneDateEnd ? * ${weekDays}${val}`; + } else if (state.get('interval') === 'D' && state.get('TimeInterval')) { + const today = new Date(); + today.setHours(state.get('TimeInterval').hour); + today.setMinutes(state.get('TimeInterval').min); + let isoString = ''; + if (today.getTime() < new Date().getTime()) { + today.setDate(today.getDate() + 1); + } + isoString = today.toISOString(); + return `R/${isoString}/P${state.get('value')}${state.get('interval')}`; + } else { + return '0 0 0 ? * *'; + } + } + /** * It takes an object of attributes and a node, and returns the same object of attributes, but with * any attribute that is a state reference replaced with the value of that state diff --git a/projects/workflows-creator/src/lib/services/bpmn/strategies/create/task-create.strategy.ts b/projects/workflows-creator/src/lib/services/bpmn/strategies/create/task-create.strategy.ts index 72562df..b18d0f4 100644 --- a/projects/workflows-creator/src/lib/services/bpmn/strategies/create/task-create.strategy.ts +++ b/projects/workflows-creator/src/lib/services/bpmn/strategies/create/task-create.strategy.ts @@ -142,38 +142,53 @@ export class CreateTaskStrategy implements CreateStrategy { let read = ''; if (froms.length > 0) { if (prevIds.length) { - read = `var readObj = ${prevIds - .map(id => `JSON.parse(execution.getVariable('${id}'))`) - .join(' || ')} || {};`; + read = `${prevIds + .map( + (id, index) => + `var readObj${index} = JSON.parse(execution.getVariable('${id}')) || {};`, + ) + .join('\n')} + `; } } - const getVariables = froms - .map( - p => - `var ${(p as FromParam).from}Local = readObj.${ - (p as FromParam).from - };`, - ) - .join('\n'); + const getVariables = froms.map( + p => + ` + var ${(p as FromParam).from}Local; + ${prevIds + .map( + (_: any, index: number) => ` + if(readObj${index}.${ + (p as FromParam).from + } && readObj${index}.${(froms[0] as FromParam).from}.length){ + ${(froms[0] as FromParam).from}Local = readObj${index}.${ + (froms[0] as FromParam).from + }; + } + `, + ) + .join('\n')} + `, + ); const setVariabels = Object.keys(params).reduce( (p: string, key: string) => { const tmp = params[key]; if (isFormattedParam(tmp)) { - return `${p}\njson.prop("${key}", ${tmp.formatter(state)});`; + return `${p}\njson["${key}"] = ${tmp.formatter(state)};`; } else if (isFromParam(tmp)) { - return `${p}\njson.prop("${key}", ${tmp.from}Local);`; + return `${p}\njson["${key}"] = ${tmp.from}Local;`; } else if (isStateParam(tmp)) { if ( tmp.state === 'recipients' && Array.isArray(state.get(tmp.state)) ) { const metaValue = this.transposeArrayToString(state.get(tmp.state)); - return `${p}\njson.prop("${key}", [${metaValue ?? ''}]);`; + return `${p}\njson["${key}"] = [${metaValue ?? ''}];`; } - return `${p}\njson.prop("${key}", "${state.get(tmp.state) ?? ''}");`; + return `${p}\njson["${key}"] = "${state.get(tmp.state) ?? ''}";`; } else { - return `${p}\njson.prop("${key}", "${tmp.value}");`; + return `${p}\njson["${key}"] = "${tmp.value}";`; } }, '', @@ -181,9 +196,9 @@ export class CreateTaskStrategy implements CreateStrategy { return [ read, getVariables, - `var json = S("{}");`, + `var json = {};`, setVariabels, - 'json', + 'JSON.stringify(json)', ].join('\n'); } diff --git a/projects/workflows-creator/src/lib/services/bpmn/strategies/link/gateway-link.strategy.ts b/projects/workflows-creator/src/lib/services/bpmn/strategies/link/gateway-link.strategy.ts index 5021d09..d936798 100644 --- a/projects/workflows-creator/src/lib/services/bpmn/strategies/link/gateway-link.strategy.ts +++ b/projects/workflows-creator/src/lib/services/bpmn/strategies/link/gateway-link.strategy.ts @@ -193,12 +193,13 @@ export class GatewayLinkStrategy implements LinkStrategy { ) { const lastNodeWithOutput = this.getLastNodeWithOutput(node); const read = `var readObj = JSON.parse(execution.getVariable('${lastNodeWithOutput.element.id}'));`; - const declarations = `var ids = [];var json = S("{}");`; + const declarations = `var ids = [];var json = {};`; const column = node.workflowNode.state.get('columnName'); const condition = this.getCondition(node); const loop = this.createLoopScript(node, condition, isElse); const setters = ` - json.prop("taskIds", ids); + json["taskIds"] = ids; + json = JSON.stringify(json); execution.setVariable('${flowId}',json); if(ids.length > 0){true;}else {false;} `; @@ -224,10 +225,30 @@ export class GatewayLinkStrategy implements LinkStrategy { ) { const column: string = node.workflowNode.state.get('columnName'); const conditionType = node.workflowNode.state.get('condition'); - const value = node.workflowNode.state.get('value'); + const valueType = node.workflowNode.state.get('valueType'); + const valueInputType = node.workflowNode.state.get('valueInputType'); - if (!conditionType && value) { - switch (value) { + if ( + valueInputType === InputTypes.Date && + (valueType === ValueTypes.Custom || + conditionType === ConditionTypes.Equal) + ) { + return ` + for (var key in readObj) { + var taskValuePair = readObj[key]; + if (taskValuePair && (taskValuePair.value || taskValuePair.value==='')) { + var readDateValue = taskValuePair.value.split('T')[0]; + var customDate = "${condition}"; + + if (${isElse ? '!' : ''}(readDateValue === customDate)) { + ids.push(taskValuePair.id); + } + } + } + `; + } + if (!conditionType && valueType && valueInputType === InputTypes.Date) { + switch (valueType) { case ValueTypes.PastToday: return ` for(var key in readObj){ @@ -252,6 +273,20 @@ export class GatewayLinkStrategy implements LinkStrategy { } } `; + case ValueTypes.Custom: + return ` + for (var key in readObj) { + var taskValuePair = readObj[key]; + if (taskValuePair && taskValuePair.value) { + var readDateValue = taskValuePair.value.split('T')[0]; + var customDate = "${condition}"; + + if (${isElse ? '!' : ''}(readDateValue === customDate)) { + ids.push(taskValuePair.id); + } + } + } + `; } } @@ -302,6 +337,28 @@ export class GatewayLinkStrategy implements LinkStrategy { } }`; } + if (column === InputTypes.Item) { + return `var selectedVals = ${condition}; + var selCol = selectedVals.split(','); + for(var key in readObj){ + var taskValuePair = readObj[key]; + if(taskValuePair && taskValuePair.value && taskValuePair.value.length){ + var hasItem = false; + var usCol = taskValuePair.value; + + for(var selKey in selCol){ + for(var myKey in usCol){ + if(usCol[myKey].value == selCol[selKey] && !hasItem){ + hasItem = true; + } + } + } + if(${conditionExpression}(hasItem)){ + ids.push(taskValuePair.id); + } + } + }`; + } switch (conditionType) { case ConditionTypes.PastToday: return ` @@ -322,9 +379,13 @@ export class GatewayLinkStrategy implements LinkStrategy { var taskValuePair = readObj[key]; if(taskValuePair && taskValuePair.value){ var readDateValue = new Date(taskValuePair.value); + var today = new Date(); + readDateValue.setHours(0,0,0,0); + today.setHours(0,0,0,0); + readDateValue.setDate(readDateValue.getDate()${condition}); if(${ isElse ? '!' : '' - }(readDateValue > new Date() && readDateValue.setDate(readDateValue.getDate()${condition}) < new Date())){ + }(readDateValue.valueOf() === today.valueOf())){ ids.push(taskValuePair.id); } } @@ -369,12 +430,21 @@ export class GatewayLinkStrategy implements LinkStrategy { private getCondition(node: BpmnStatementNode) { let value = node.workflowNode.state.get('value'); const valueType = node.workflowNode.state.get('valueInputType'); - if (valueType === InputTypes.Text || valueType === InputTypes.List) { - value = `'${value}'`; - } - if (value && valueType === InputTypes.People) { - return `'${value.ids}'`; - } + if (value) + switch (valueType) { + case InputTypes.Stepper: + case InputTypes.Text: + value = `'${value}'`; + break; + case InputTypes.OptionList: + case InputTypes.List: + value = `'${value.value}'`; + break; + case InputTypes.People: + return `'${value.ids}'`; + case InputTypes.Date: + return `${value.split('T')[0]}`; + } const condition = node.workflowNode.state.get('condition'); const pair = this.conditions.find(item => item.condition === condition); if (!pair) { diff --git a/projects/workflows-creator/src/lib/services/bpmn/strategies/link/or-gateway-link.strategy.ts b/projects/workflows-creator/src/lib/services/bpmn/strategies/link/or-gateway-link.strategy.ts index 9b4c948..2ed9de6 100644 --- a/projects/workflows-creator/src/lib/services/bpmn/strategies/link/or-gateway-link.strategy.ts +++ b/projects/workflows-creator/src/lib/services/bpmn/strategies/link/or-gateway-link.strategy.ts @@ -112,12 +112,13 @@ export class OrGatewayLinkStrategy implements LinkStrategy { ) { const lastNodeWithOutput = this.getLastNodeWithOutput(node); const read = `var readObj = JSON.parse(execution.getVariable('${lastNodeWithOutput.element.id}'));`; - const declarations = `var ids = [];var json = S("{}");`; + const declarations = `var ids = [];var json = {};`; const column = node.workflowNode.state.get('columnName'); const condition = this.getCondition(node); const loop = this.createLoopScript(node, condition, isElse); const setters = ` - json.prop("taskIds", ids); + json["taskIds"] = ids; + json.stringify(json); execution.setVariable('${flowId}',json); if(ids.length > 0){true;}else {false;} `; @@ -161,9 +162,13 @@ export class OrGatewayLinkStrategy implements LinkStrategy { var taskValuePair = readObj[key]; if(taskValuePair && taskValuePair.value){ var readDateValue = new Date(taskValuePair.value); + var today = new Date(); + readDateValue.setHours(0,0,0,0); + today.setHours(0,0,0,0); + readDateValue.setDate(readDateValue.getDate()${condition}); if(${ isElse ? '!' : '' - }(readDateValue > new Date() && readDateValue.setDate(readDateValue.getDate()${condition}) < new Date())){ + }(readDateValue.valueOf() === today.valueOf())){ ids.push(taskValuePair.id); } } diff --git a/projects/workflows-creator/src/lib/services/statement/events/oninterval.event.ts b/projects/workflows-creator/src/lib/services/statement/events/oninterval.event.ts index 60b3434..26fa0f1 100644 --- a/projects/workflows-creator/src/lib/services/statement/events/oninterval.event.ts +++ b/projects/workflows-creator/src/lib/services/statement/events/oninterval.event.ts @@ -2,8 +2,9 @@ import {LocalizedStringKeys, StartElementTypes} from '../../../enum'; import {RecordOfAnyType} from '../../../types'; import {BpmnEvent} from '../../../types/bpmn.types'; import {TriggerOnInterval} from '../../bpmn/elements/tasks/trigger-on-interval.task'; +import {TimeIntervalInput, ToIntervalInput} from '../inputs'; import {IntervalInput} from '../inputs/interval.input'; -import {ValueInput} from '../inputs/value.input'; +import {StepperInput} from '../inputs/stepper.input'; export class OnIntervalEvent extends BpmnEvent { groupType: string; @@ -14,7 +15,12 @@ export class OnIntervalEvent extends BpmnEvent { name = 'On Interval'; statement = 'Every '; properties = {}; - prompts = [ValueInput.identifier, IntervalInput.identifier]; + prompts = [ + StepperInput.identifier, + IntervalInput.identifier, + ToIntervalInput.identifier, + TimeIntervalInput.identifier, + ]; static identifier = 'OnIntervalEvent'; constructor( localizedStringMap: RecordOfAnyType, diff --git a/projects/workflows-creator/src/lib/services/statement/events/onvalue.event.ts b/projects/workflows-creator/src/lib/services/statement/events/onvalue.event.ts index a8c4c41..f792117 100644 --- a/projects/workflows-creator/src/lib/services/statement/events/onvalue.event.ts +++ b/projects/workflows-creator/src/lib/services/statement/events/onvalue.event.ts @@ -3,8 +3,8 @@ import {RecordOfAnyType} from '../../../types'; import {BpmnEvent} from '../../../types/bpmn.types'; import {GatewayElement} from '../../bpmn/elements/gateways/gateway.element'; import {ReadColumnValue} from '../../bpmn/elements/tasks/read-column.task'; -import {ColumnInput} from '../inputs/column.input'; import {ConditionInput} from '../inputs/condition.input'; +import {CriteriaInput} from '../inputs/criteria.input'; import {ValueInput} from '../inputs/value.input'; export class OnValueEvent extends BpmnEvent { @@ -16,7 +16,7 @@ export class OnValueEvent extends BpmnEvent { statement = 'check if '; properties = {}; prompts = [ - ColumnInput.identifier, + CriteriaInput.identifier, ConditionInput.identifier, ValueInput.identifier, ]; diff --git a/projects/workflows-creator/src/lib/services/statement/inputs/criteria.input.ts b/projects/workflows-creator/src/lib/services/statement/inputs/criteria.input.ts new file mode 100644 index 0000000..8817e01 --- /dev/null +++ b/projects/workflows-creator/src/lib/services/statement/inputs/criteria.input.ts @@ -0,0 +1,20 @@ +import {State, WorkflowPrompt} from '../../../classes'; +import {InputTypes} from '../../../enum'; +import {RecordOfAnyType} from '../../../types'; + +export class CriteriaInput extends WorkflowPrompt { + prefix = ''; + suffix = ''; + typeFunction = () => InputTypes.OptionList; + inputKey = 'column'; + listNameField = 'text'; + listValueField = 'value'; + placeholder = 'Criteria'; + options = (state: State) => + state.get('columns'); + static identifier = 'CriteriaInput'; + + getIdentifier(): string { + return CriteriaInput.identifier; + } +} diff --git a/projects/workflows-creator/src/lib/services/statement/inputs/index.ts b/projects/workflows-creator/src/lib/services/statement/inputs/index.ts index ea94d81..9207aaa 100644 --- a/projects/workflows-creator/src/lib/services/statement/inputs/index.ts +++ b/projects/workflows-creator/src/lib/services/statement/inputs/index.ts @@ -7,3 +7,7 @@ export * from './value.input'; export * from './interval.input'; export * from './triggercolumn.input'; export * from './valuetype.input'; +export * from './criteria.input'; +export * from './stepper.input'; +export * from './tointerval.input'; +export * from './timeinterval.input'; diff --git a/projects/workflows-creator/src/lib/services/statement/inputs/interval.input.ts b/projects/workflows-creator/src/lib/services/statement/inputs/interval.input.ts index dbae337..e51f618 100644 --- a/projects/workflows-creator/src/lib/services/statement/inputs/interval.input.ts +++ b/projects/workflows-creator/src/lib/services/statement/inputs/interval.input.ts @@ -3,8 +3,8 @@ import {InputTypes} from '../../../enum'; import {RecordOfAnyType} from '../../../types'; export class IntervalInput extends WorkflowPrompt { - prefix = ''; - suffix = ''; + prefix: string | {state: string} = {state: 'valuePrefix'}; + suffix: string | {state: string} = {state: 'intervalValueSuffix'}; typeFunction = () => InputTypes.List; inputKey = 'interval'; listNameField = 'text'; diff --git a/projects/workflows-creator/src/lib/services/statement/inputs/stepper.input.ts b/projects/workflows-creator/src/lib/services/statement/inputs/stepper.input.ts new file mode 100644 index 0000000..06433e9 --- /dev/null +++ b/projects/workflows-creator/src/lib/services/statement/inputs/stepper.input.ts @@ -0,0 +1,21 @@ +import {State, WorkflowPrompt} from '../../../classes'; +import {InputTypes} from '../../../enum'; +import {RecordOfAnyType} from '../../../types'; + +export class StepperInput extends WorkflowPrompt { + prefix = ''; + suffix = ''; + typeFunction = () => InputTypes.Stepper; + inputKey = 'value'; + listNameField = 'text'; + listValueField = 'value'; + placeholder = 'n'; + customPlaceholder: string | {state: string} = {state: 'stepperPlaceholder'}; + options = (state: State) => + state.get('stepperCount') as []; + static identifier = 'StepperInput'; + + getIdentifier(): string { + return StepperInput.identifier; + } +} diff --git a/projects/workflows-creator/src/lib/services/statement/inputs/timeinterval.input.ts b/projects/workflows-creator/src/lib/services/statement/inputs/timeinterval.input.ts new file mode 100644 index 0000000..b25aa25 --- /dev/null +++ b/projects/workflows-creator/src/lib/services/statement/inputs/timeinterval.input.ts @@ -0,0 +1,30 @@ +import {State, WorkflowPrompt} from '../../../classes'; +import {InputTypes, IntervalType} from '../../../enum'; +import {BpmnNode, RecordOfAnyType} from '../../../types'; +export class TimeIntervalInput extends WorkflowPrompt { + prefix: string | {state: string} = {state: 'timeIntervalSuffix'}; + suffix = ''; + typeFunction = () => InputTypes.IntervalTime; + inputKey = 'TimeInterval'; + listNameField = 'text'; + listValueField = 'value'; + placeholder = 'hh:mm'; + customPlaceholder: string | {state: string} = {state: 'timeStatePlaceholder'}; + isHidden = (node: BpmnNode) => { + return ![ + IntervalType.Weeks, + IntervalType.Months, + IntervalType.Week, + IntervalType.Month, + IntervalType.Days, + IntervalType.Day, + ].includes(node.state.get('intervalType')); + }; + options = (state: State) => + state.get('timevalues'); + static identifier = 'TimeIntervalInput'; + + getIdentifier(): string { + return TimeIntervalInput.identifier; + } +} diff --git a/projects/workflows-creator/src/lib/services/statement/inputs/tointerval.input.ts b/projects/workflows-creator/src/lib/services/statement/inputs/tointerval.input.ts new file mode 100644 index 0000000..fcf6c88 --- /dev/null +++ b/projects/workflows-creator/src/lib/services/statement/inputs/tointerval.input.ts @@ -0,0 +1,30 @@ +import {State, WorkflowPrompt} from '../../../classes'; +import {InputTypes, IntervalType} from '../../../enum'; +import {BpmnNode, RecordOfAnyType} from '../../../types'; + +export class ToIntervalInput extends WorkflowPrompt { + prefix = ''; + suffix = ''; + typeFunction = (state: State) => + state.get('valueInputTypes') as InputTypes; + inputKey = 'toInterval'; + listNameField = 'text'; + listValueField = 'value'; + placeholder = 'weekday'; + customPlaceholder: string | {state: string} = {state: 'dateStatePlaceholder'}; + isHidden = (node: BpmnNode) => { + return ![ + IntervalType.Weeks, + IntervalType.Months, + IntervalType.Week, + IntervalType.Month, + ].includes(node.state.get('intervalType')); + }; + options = (state: State) => + state.get('intervalOption'); + static identifier = 'ToIntervalInput'; + + getIdentifier(): string { + return ToIntervalInput.identifier; + } +} diff --git a/projects/workflows-creator/src/lib/services/statement/inputs/value.input.ts b/projects/workflows-creator/src/lib/services/statement/inputs/value.input.ts index 293db18..b1cb912 100644 --- a/projects/workflows-creator/src/lib/services/statement/inputs/value.input.ts +++ b/projects/workflows-creator/src/lib/services/statement/inputs/value.input.ts @@ -9,7 +9,7 @@ import { import {BpmnNode, RecordOfAnyType} from '../../../types'; export class ValueInput extends WorkflowListPrompt { - prefix: string | {state: string} = ''; + prefix: string | {state: string} = {state: 'valuePrefix'}; suffix: string | {state: string} = {state: 'valueSuffix'}; inputKey = 'value'; listNameField = 'text'; @@ -32,6 +32,7 @@ export class ValueInput extends WorkflowListPrompt { InputTypes.Number, InputTypes.People, InputTypes.Percentage, + InputTypes.Date, ].includes(node.state.get('valueInputType')) && node.state.get('valueType') !== ValueTypes.Custom) ); diff --git a/projects/workflows-creator/src/lib/services/statement/inputs/valuetype.input.ts b/projects/workflows-creator/src/lib/services/statement/inputs/valuetype.input.ts index 58ad5fc..ac19a9b 100644 --- a/projects/workflows-creator/src/lib/services/statement/inputs/valuetype.input.ts +++ b/projects/workflows-creator/src/lib/services/statement/inputs/valuetype.input.ts @@ -20,6 +20,7 @@ export class ValueTypeInput extends WorkflowListPrompt { InputTypes.Number, InputTypes.People, InputTypes.Percentage, + InputTypes.Date, ].includes(node.state.get('valueInputType')); }; diff --git a/projects/workflows-creator/src/lib/types/base.types.ts b/projects/workflows-creator/src/lib/types/base.types.ts index 91916cf..d38576f 100644 --- a/projects/workflows-creator/src/lib/types/base.types.ts +++ b/projects/workflows-creator/src/lib/types/base.types.ts @@ -172,6 +172,7 @@ export type EmailInput = { subject: string; body: string; focusKey: string; + caretPos: number; }; /** diff --git a/projects/workflows-creator/src/lib/workflow-builder.module.ts b/projects/workflows-creator/src/lib/workflow-builder.module.ts index 2501d7d..f730147 100644 --- a/projects/workflows-creator/src/lib/workflow-builder.module.ts +++ b/projects/workflows-creator/src/lib/workflow-builder.module.ts @@ -89,6 +89,12 @@ import {TriggerColumnInput} from './services/statement/inputs/triggercolumn.inpu import {ValueTypeInput} from './services/statement/inputs/valuetype.input'; import {TooltipRenderComponent} from './builder/tooltip-render/tooltip-render.component'; import {LocalizationPipe} from './pipes/localization.pipe'; +import { + CriteriaInput, + StepperInput, + TimeIntervalInput, + ToIntervalInput, +} from './services'; @NgModule({ declarations: [ BuilderComponent, @@ -143,7 +149,11 @@ import {LocalizationPipe} from './pipes/localization.pipe'; {provide: BPMN_ELEMENTS, useClass: ChangeColumnValue, multi: true}, {provide: BPMN_ELEMENTS, useClass: ProcessPropertiesElement, multi: true}, {provide: BPMN_INPUTS, useClass: ColumnInput, multi: true}, + {provide: BPMN_INPUTS, useClass: CriteriaInput, multi: true}, + {provide: BPMN_INPUTS, useClass: StepperInput, multi: true}, + {provide: BPMN_INPUTS, useClass: TimeIntervalInput, multi: true}, {provide: BPMN_INPUTS, useClass: TriggerColumnInput, multi: true}, + {provide: BPMN_INPUTS, useClass: ToIntervalInput, multi: true}, {provide: BPMN_INPUTS, useClass: IntervalInput, multi: true}, {provide: BPMN_INPUTS, useClass: ConditionInput, multi: true}, {provide: BPMN_INPUTS, useClass: EmailDataInput, multi: true},