Link activity selection with journal
This commit is contained in:
parent
ab72de9a4a
commit
e1a9a50bb9
|
|
@ -41,7 +41,7 @@ export namespace Components {
|
|||
interface ElsaDesignerTreeActivity {
|
||||
"displayContext": ActivityDesignDisplayContext;
|
||||
"icon": string;
|
||||
"selected": boolean;
|
||||
"isSelected": boolean;
|
||||
}
|
||||
interface ElsaDropdownButton {
|
||||
"icon"?: any;
|
||||
|
|
@ -177,6 +177,7 @@ export namespace Components {
|
|||
interface ElsaWorkflowInstanceJournal {
|
||||
"activityDescriptors": Array<ActivityDescriptor>;
|
||||
"hide": () => Promise<void>;
|
||||
"selectActivityRecord": (activityId?: string) => Promise<void>;
|
||||
"serverUrl": string;
|
||||
"show": () => Promise<void>;
|
||||
"workflowBlueprint": WorkflowBlueprint;
|
||||
|
|
@ -483,15 +484,19 @@ declare namespace LocalJSX {
|
|||
}
|
||||
interface ElsaDesignerTree {
|
||||
"model"?: WorkflowModel;
|
||||
"onActivityDeselected"?: (event: CustomEvent<ActivityModel>) => void;
|
||||
"onActivitySelected"?: (event: CustomEvent<ActivityModel>) => void;
|
||||
"onWorkflow-changed"?: (event: CustomEvent<WorkflowModel>) => void;
|
||||
"selectedActivityId"?: string;
|
||||
}
|
||||
interface ElsaDesignerTreeActivity {
|
||||
"displayContext"?: ActivityDesignDisplayContext;
|
||||
"icon"?: string;
|
||||
"isSelected"?: boolean;
|
||||
"onDeselected"?: (event: CustomEvent<ActivityModel>) => void;
|
||||
"onEdit-activity"?: (event: CustomEvent<ActivityModel>) => void;
|
||||
"onRemove-activity"?: (event: CustomEvent<ActivityModel>) => void;
|
||||
"selected"?: boolean;
|
||||
"onSelected"?: (event: CustomEvent<ActivityModel>) => void;
|
||||
}
|
||||
interface ElsaDropdownButton {
|
||||
"icon"?: any;
|
||||
|
|
|
|||
|
|
@ -14,9 +14,11 @@ export class ElsaDesignerTreeActivity {
|
|||
|
||||
@Prop() displayContext: ActivityDesignDisplayContext
|
||||
@Prop() icon: string
|
||||
@Prop() selected: boolean;
|
||||
@Prop({attribute:"selected"}) isSelected: boolean;
|
||||
@Event({eventName: 'remove-activity', bubbles: true}) removeActivityEmitter: EventEmitter<ActivityModel>;
|
||||
@Event({eventName: 'edit-activity', bubbles: true}) editActivityEmitter: EventEmitter<ActivityModel>;
|
||||
@Event() selected: EventEmitter<ActivityModel>;
|
||||
@Event() deselected: EventEmitter<ActivityModel>;
|
||||
@State() showMenu: boolean
|
||||
contextMenu: HTMLElement;
|
||||
el: HTMLElement;
|
||||
|
|
@ -41,16 +43,26 @@ export class ElsaDesignerTreeActivity {
|
|||
this.removeActivityEmitter.emit(this.displayContext.activityModel);
|
||||
}
|
||||
|
||||
onSelectActivity(e: Event) {
|
||||
this.isSelected = !this.isSelected;
|
||||
|
||||
if(this.selected)
|
||||
this.selected.emit(this.displayContext.activityModel);
|
||||
else
|
||||
this.deselected.emit(this.displayContext.activityModel);
|
||||
}
|
||||
|
||||
render() {
|
||||
const displayContext = this.displayContext;
|
||||
const activity = displayContext.activityModel;
|
||||
const activityId = activity.activityId;
|
||||
const displayName = activity.displayName && activity.displayName.length > 0 ? activity.displayName : activity.name && activity.name.length > 0 ? activity.name : activity.type
|
||||
const activityClass = this.selected ? 'border-blue-600' : 'border-white hover:border-blue-600';
|
||||
const activityClass = this.isSelected ? 'border-blue-600' : 'border-white hover:border-blue-600';
|
||||
|
||||
return (
|
||||
<Host id={`activity-${activityId}`}
|
||||
onDblClick={e => this.onEditActivityClick(e)}
|
||||
onClick={e => this.onSelectActivity(e)}
|
||||
class={`${activityClass} activity border-2 border-solid rounded bg-white text-left text-black text-lg select-none max-w-md shadow-sm relative`}>
|
||||
<div class="p-5">
|
||||
<div class="flex justify-between space-x-8">
|
||||
|
|
|
|||
|
|
@ -16,9 +16,11 @@ import state from "../../../../utils/store";
|
|||
})
|
||||
export class ElsaWorkflowDesigner {
|
||||
|
||||
@Prop() model: WorkflowModel = { activities: [], connections: [], persistenceBehavior: WorkflowPersistenceBehavior.WorkflowBurst };
|
||||
@Prop() model: WorkflowModel = {activities: [], connections: [], persistenceBehavior: WorkflowPersistenceBehavior.WorkflowBurst};
|
||||
@Prop() selectedActivityId?: string;
|
||||
@Event({eventName: 'workflow-changed', bubbles: true, composed: true, cancelable: true}) workflowChanged: EventEmitter<WorkflowModel>
|
||||
@Event() activitySelected: EventEmitter<ActivityModel>;
|
||||
@Event() activityDeselected: EventEmitter<ActivityModel>;
|
||||
@State() workflowModel: WorkflowModel
|
||||
el: HTMLElement
|
||||
canvasElement: HTMLElement;
|
||||
|
|
@ -32,7 +34,7 @@ export class ElsaWorkflowDesigner {
|
|||
}
|
||||
|
||||
@Method()
|
||||
async destroyJsPlumb(){
|
||||
async destroyJsPlumb() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
|
|
@ -60,8 +62,8 @@ export class ElsaWorkflowDesigner {
|
|||
componentWillLoad() {
|
||||
this.workflowModel = this.model;
|
||||
}
|
||||
|
||||
onActivityPicked = async (args) =>{
|
||||
|
||||
onActivityPicked = async (args) => {
|
||||
const activityDescriptor = (args as ActivityDescriptor);
|
||||
const connectFromRoot = !this.parentActivityOutcome || this.parentActivityOutcome == "";
|
||||
const sourceId = connectFromRoot ? null : this.parentActivityId;
|
||||
|
|
@ -70,7 +72,7 @@ export class ElsaWorkflowDesigner {
|
|||
|
||||
this.showActivityEditor(activityModel, false);
|
||||
};
|
||||
|
||||
|
||||
onUpdateActivity = args => {
|
||||
const activityModel = (args as ActivityModel);
|
||||
this.updateActivity(activityModel);
|
||||
|
|
@ -101,7 +103,7 @@ export class ElsaWorkflowDesigner {
|
|||
eventBus.emit(EventTypes.ActivityDesignDisplaying, this, displayContext);
|
||||
displayContexts[model.activityId] = displayContext;
|
||||
}
|
||||
|
||||
|
||||
this.activityDisplayContexts = displayContexts;
|
||||
}
|
||||
|
||||
|
|
@ -232,7 +234,7 @@ export class ElsaWorkflowDesigner {
|
|||
this.workflowChanged.emit(model);
|
||||
}
|
||||
|
||||
removeInvalidConnections(invalidConnections: Array<ConnectionModel>){
|
||||
removeInvalidConnections(invalidConnections: Array<ConnectionModel>) {
|
||||
if (invalidConnections.length > 0) {
|
||||
|
||||
const isValid = (connection: ConnectionModel): boolean => invalidConnections.findIndex(x => x.targetId == connection.targetId && x.sourceId == connection.sourceId && x.outcome == connection.outcome) < 0;
|
||||
|
|
@ -391,7 +393,7 @@ export class ElsaWorkflowDesigner {
|
|||
|
||||
workflowModel.connections = [...connections, newConnection];
|
||||
} else {
|
||||
|
||||
|
||||
// Create new connection.
|
||||
const newConnection: ConnectionModel = {
|
||||
sourceId: sourceActivityId,
|
||||
|
|
@ -405,6 +407,14 @@ export class ElsaWorkflowDesigner {
|
|||
this.updateWorkflowModel(workflowModel);
|
||||
}
|
||||
|
||||
private onActivitySelected(e: CustomEvent<ActivityModel>) {
|
||||
this.activitySelected.emit(e.detail);
|
||||
}
|
||||
|
||||
private onActivityDeselected(e: CustomEvent<ActivityModel>) {
|
||||
this.activityDeselected.emit(e.detail);
|
||||
}
|
||||
|
||||
render() {
|
||||
const renderedActivities = new Set<string>();
|
||||
|
||||
|
|
@ -442,7 +452,7 @@ export class ElsaWorkflowDesigner {
|
|||
|
||||
if (list.length === 0)
|
||||
return list;
|
||||
|
||||
|
||||
const sourceActivityConnection: ConnectionDefinitionMapped = connections.find(x => x.targetActivityId === list[0].activityId);
|
||||
|
||||
if (!sourceActivityConnection)
|
||||
|
|
@ -456,7 +466,7 @@ export class ElsaWorkflowDesigner {
|
|||
|
||||
const sourceActivityConnections: Array<ConnectionDefinitionMapped> = connections.filter(x => x.sourceActivityId === sourceActivityId);
|
||||
const sourceActivityDisplayContext = this.activityDisplayContexts[sourceActivity.activityId];
|
||||
|
||||
|
||||
if (sourceActivityDisplayContext.outcomes) {
|
||||
sourceActivity.outcomes = sourceActivityDisplayContext.outcomes;
|
||||
}
|
||||
|
|
@ -491,7 +501,7 @@ export class ElsaWorkflowDesigner {
|
|||
const children = getChildActivities(this.workflowModel, activityId);
|
||||
const displayContext = this.activityDisplayContexts[activityId];
|
||||
|
||||
if(renderedActivities.has(displayContext.activityModel.activityId))
|
||||
if (renderedActivities.has(displayContext.activityModel.activityId))
|
||||
return;
|
||||
|
||||
renderedActivities.add(displayContext.activityModel.activityId);
|
||||
|
|
@ -538,10 +548,12 @@ export class ElsaWorkflowDesigner {
|
|||
|
||||
renderActivity(displayContext: ActivityDesignDisplayContext) {
|
||||
const selected = this.selectedActivityId == displayContext.activityModel.activityId;
|
||||
return <elsa-designer-tree-activity displayContext={displayContext}
|
||||
return <elsa-designer-tree-activity displayContext={displayContext}
|
||||
draggable={true}
|
||||
selected={selected}
|
||||
isSelected={selected}
|
||||
onDragStart={e => this.onDragStartActivity(e, displayContext)}
|
||||
onSelected={e => this.onActivitySelected(e)}
|
||||
onDeselected={e => this.onActivityDeselected(e)}
|
||||
/>;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ export class ElsaWorkflowInstanceJournal {
|
|||
|
||||
@Method()
|
||||
async show() {
|
||||
if(this.isVisible)
|
||||
return;
|
||||
|
||||
this.isVisible = true;
|
||||
|
||||
enter(this.el);
|
||||
|
|
@ -56,9 +59,19 @@ export class ElsaWorkflowInstanceJournal {
|
|||
|
||||
@Method()
|
||||
async hide() {
|
||||
if(!this.isVisible)
|
||||
return;
|
||||
|
||||
leave(this.el).then(() => this.isVisible = false);
|
||||
}
|
||||
|
||||
@Method()
|
||||
async selectActivityRecord(activityId?: string) {
|
||||
const record = !!activityId ? this.records.items.find(x => x.activityId == activityId) : null;
|
||||
this.selectedRecordId = !!record ? record.id : null;
|
||||
await this.show();
|
||||
}
|
||||
|
||||
@Watch('workflowInstanceId')
|
||||
async workflowInstanceIdChangedHandler(newValue: string) {
|
||||
const workflowInstanceId = newValue;
|
||||
|
|
@ -68,7 +81,7 @@ export class ElsaWorkflowInstanceJournal {
|
|||
try {
|
||||
this.records = await client.workflowExecutionLogApi.get(workflowInstanceId);
|
||||
} catch {
|
||||
console.warn(`The specified workflow definition does not exist. Creating a new one.`);
|
||||
console.warn('The specified workflow instance does not exist.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ export class ElsaWorkflowInstanceViewerScreen {
|
|||
@State() selectedActivityId?: string;
|
||||
el: HTMLElement;
|
||||
designer: HTMLElsaDesignerTreeElement;
|
||||
journal: HTMLElsaWorkflowInstanceJournalElement;
|
||||
|
||||
@Method()
|
||||
async getServerUrl(): Promise<string> {
|
||||
|
|
@ -162,12 +163,25 @@ export class ElsaWorkflowInstanceViewerScreen {
|
|||
this.selectedActivityId = e.detail.activityId;
|
||||
}
|
||||
|
||||
onActivitySelected(e: CustomEvent<ActivityModel>) {
|
||||
this.selectedActivityId = e.detail.activityId;
|
||||
this.journal.selectActivityRecord(this.selectedActivityId);
|
||||
}
|
||||
|
||||
onActivityDeselected(e: CustomEvent<ActivityModel>) {
|
||||
if(this.selectedActivityId == e.detail.activityId)
|
||||
this.selectedActivityId = null;
|
||||
|
||||
this.journal.selectActivityRecord(this.selectedActivityId);
|
||||
}
|
||||
|
||||
render() {
|
||||
const descriptors: Array<ActivityDescriptor> = state.activityDescriptors;
|
||||
return (
|
||||
<Host class="flex flex-col w-full relative" ref={el => this.el = el}>
|
||||
{this.renderCanvas()}
|
||||
<elsa-workflow-instance-journal workflowInstanceId={this.workflowInstanceId}
|
||||
<elsa-workflow-instance-journal ref={el => this.journal = el}
|
||||
workflowInstanceId={this.workflowInstanceId}
|
||||
serverUrl={this.serverUrl}
|
||||
activityDescriptors={descriptors}
|
||||
workflowBlueprint={this.workflowBlueprint}
|
||||
|
|
@ -179,7 +193,12 @@ export class ElsaWorkflowInstanceViewerScreen {
|
|||
renderCanvas() {
|
||||
return (
|
||||
<div class="flex-1 flex">
|
||||
<elsa-designer-tree model={this.workflowModel} class="flex-1" ref={el => this.designer = el} selectedActivityId={this.selectedActivityId}/>
|
||||
<elsa-designer-tree model={this.workflowModel}
|
||||
class="flex-1" ref={el => this.designer = el}
|
||||
selectedActivityId={this.selectedActivityId}
|
||||
onActivitySelected={e => this.onActivitySelected(e)}
|
||||
onActivityDeselected={e => this.onActivityDeselected(e)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue