Implement record selection

This commit is contained in:
Sipke Schoorstra 2021-04-21 17:28:56 +02:00
parent ffafe42948
commit f20fdbf437
5 changed files with 57 additions and 11 deletions

View file

@ -5,7 +5,7 @@
* It contains typing information for all components that exist in this project.
*/
import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
import { ActivityDefinitionProperty, ActivityDescriptor, ActivityDesignDisplayContext, ActivityModel, ActivityPropertyDescriptor, VersionOptions, WorkflowBlueprint, WorkflowDefinition, WorkflowModel } from "./models";
import { ActivityDefinitionProperty, ActivityDescriptor, ActivityDesignDisplayContext, ActivityModel, ActivityPropertyDescriptor, VersionOptions, WorkflowBlueprint, WorkflowDefinition, WorkflowExecutionLogRecord, WorkflowModel } from "./models";
import { MatchResults, RouterHistory } from "@stencil/router";
import { MenuItem } from "./components/controls/elsa-context-menu/models";
import { DropdownButtonItem, DropdownButtonOrigin } from "./components/controls/elsa-dropdown-button/models";
@ -36,10 +36,12 @@ export namespace Components {
interface ElsaDesignerTree {
"destroyJsPlumb": () => Promise<void>;
"model": WorkflowModel;
"selectedActivityId"?: string;
}
interface ElsaDesignerTreeActivity {
"displayContext": ActivityDesignDisplayContext;
"icon": string;
"selected": boolean;
}
interface ElsaDropdownButton {
"icon"?: any;
@ -482,12 +484,14 @@ declare namespace LocalJSX {
interface ElsaDesignerTree {
"model"?: WorkflowModel;
"onWorkflow-changed"?: (event: CustomEvent<WorkflowModel>) => void;
"selectedActivityId"?: string;
}
interface ElsaDesignerTreeActivity {
"displayContext"?: ActivityDesignDisplayContext;
"icon"?: string;
"onEdit-activity"?: (event: CustomEvent<ActivityModel>) => void;
"onRemove-activity"?: (event: CustomEvent<ActivityModel>) => void;
"selected"?: boolean;
}
interface ElsaDropdownButton {
"icon"?: any;
@ -619,6 +623,7 @@ declare namespace LocalJSX {
}
interface ElsaWorkflowInstanceJournal {
"activityDescriptors"?: Array<ActivityDescriptor>;
"onRecordSelected"?: (event: CustomEvent<WorkflowExecutionLogRecord>) => void;
"serverUrl"?: string;
"workflowBlueprint"?: WorkflowBlueprint;
"workflowInstanceId"?: string;

View file

@ -14,6 +14,7 @@ export class ElsaDesignerTreeActivity {
@Prop() displayContext: ActivityDesignDisplayContext
@Prop() icon: string
@Prop() selected: boolean;
@Event({eventName: 'remove-activity', bubbles: true}) removeActivityEmitter: EventEmitter<ActivityModel>;
@Event({eventName: 'edit-activity', bubbles: true}) editActivityEmitter: EventEmitter<ActivityModel>;
@State() showMenu: boolean
@ -45,11 +46,12 @@ export class ElsaDesignerTreeActivity {
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';
return (
<Host id={`activity-${activityId}`}
onDblClick={e => this.onEditActivityClick(e)}
class="activity border-2 border-solid border-white rounded bg-white text-left text-black text-lg hover:border-blue-600 select-none max-w-md shadow-sm relative">
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">
<div class="flex-shrink-0">

View file

@ -17,6 +17,7 @@ import state from "../../../../utils/store";
export class ElsaWorkflowDesigner {
@Prop() model: WorkflowModel = { activities: [], connections: [], persistenceBehavior: WorkflowPersistenceBehavior.WorkflowBurst };
@Prop() selectedActivityId?: string;
@Event({eventName: 'workflow-changed', bubbles: true, composed: true, cancelable: true}) workflowChanged: EventEmitter<WorkflowModel>
@State() workflowModel: WorkflowModel
el: HTMLElement
@ -536,7 +537,10 @@ export class ElsaWorkflowDesigner {
}
renderActivity(displayContext: ActivityDesignDisplayContext) {
return <elsa-designer-tree-activity displayContext={displayContext} draggable={true}
const selected = this.selectedActivityId == displayContext.activityModel.activityId;
return <elsa-designer-tree-activity displayContext={displayContext}
draggable={true}
selected={selected}
onDragStart={e => this.onDragStartActivity(e, displayContext)}
/>;
}

View file

@ -1,4 +1,4 @@
import {Component, h, Host, Method, Prop, State, Watch} from '@stencil/core';
import {Component, EventEmitter, h, Host, Method, Prop, State, Watch, Event} from '@stencil/core';
import moment from 'moment';
import {enter, leave, toggle} from 'el-transition'
import {registerClickOutside} from "stencil-click-outside";
@ -19,8 +19,10 @@ export class ElsaWorkflowInstanceJournal {
@Prop() serverUrl: string;
@Prop() activityDescriptors: Array<ActivityDescriptor> = [];
@Prop() workflowBlueprint: WorkflowBlueprint;
@Event() recordSelected: EventEmitter<WorkflowExecutionLogRecord>;
@State() isVisible: boolean = true;
@State() records: PagedList<WorkflowExecutionLogRecord> = {items: [], totalCount: 0};
@State() selectedRecordId?: string;
el: HTMLElement;
@ -54,6 +56,18 @@ export class ElsaWorkflowInstanceJournal {
await this.workflowInstanceIdChangedHandler(this.workflowInstanceId);
}
getEventColor(eventName: string) {
const map = {
'Executing': 'blue',
'Executed': 'green',
'Faulted': 'rose',
'Warning': 'yellow',
'Information': 'blue',
};
return map[eventName] || 'gray';
}
onCloseClick() {
this.hide();
}
@ -62,12 +76,18 @@ export class ElsaWorkflowInstanceJournal {
this.show();
}
onRecordClick(record: WorkflowExecutionLogRecord) {
this.selectedRecordId = record.id;
this.recordSelected.emit(record);
}
render() {
const records = this.records;
const items = records.items;
const activityDescriptors = this.activityDescriptors;
const workflowBlueprint = this.workflowBlueprint;
const activityBlueprints: Array<ActivityBlueprint> = workflowBlueprint.activities || [];
const selectedRecordId = this.selectedRecordId;
const renderRecord = (record: WorkflowExecutionLogRecord, index: number) => {
const isLastItem = index == items.length - 1;
@ -80,6 +100,9 @@ export class ElsaWorkflowInstanceJournal {
const activityDescriptor = activityDescriptors.find(x => x.type === activityType);
const activityBlueprint = activityBlueprints.find(x => x.id === record.activityId) || {name: null, displayName: null};
const activityName = activityBlueprint.displayName || activityBlueprint.name || activityDescriptor.displayName || activityDescriptor.type;
const eventName = record.eventName;
const eventColor = this.getEventColor(eventName);
const recordClass = record.id === selectedRecordId ? 'border-blue-600' : 'hover:bg-gray-100 border-transparent';
const deltaTimeText = !!deltaTime ? deltaTime.asHours() > 1
? `${deltaTime.asHours()} h`
@ -92,7 +115,7 @@ export class ElsaWorkflowInstanceJournal {
return (
<li>
<div class="hover:bg-gray-100 cursor-pointer p-4 rounded">
<div onClick={() => this.onRecordClick(record)} class={`${recordClass} border-2 cursor-pointer p-4 rounded`}>
<div class="relative pb-10">
{isLastItem ? undefined : <div class="flex absolute top-8 left-4 -ml-px h-full w-0.5 bg-gray-200">
<div class="flex flex-1 items-center relative -left-5">
@ -112,9 +135,12 @@ export class ElsaWorkflowInstanceJournal {
</h3>
</div>
<div>
<span class="relative inline-flex items-center rounded-full border border-gray-300 px-3 py-0.5 text-sm">
<span class="font-medium text-gray-900">{record.eventName}</span>
</span>
<span class="relative inline-flex items-center rounded-full border border-gray-300 px-3 py-0.5 text-sm">
<span class="absolute flex-shrink-0 flex items-center justify-center">
<span class={`h-1.5 w-1.5 rounded-full bg-${eventColor}-500`} aria-hidden="true"/>
</span>
<span class="ml-3.5 font-medium text-gray-900">{eventName}</span>
</span>
</div>
<div class="text-right text-sm whitespace-nowrap text-gray-500">
<span>{currentTimestamp.format('DD-MM-YYYY HH:mm:ss')}</span>

View file

@ -7,7 +7,7 @@ import {
ActivityModel, Connection,
ConnectionModel,
EventTypes, SyntaxNames,
WorkflowBlueprint,
WorkflowBlueprint, WorkflowExecutionLogRecord,
WorkflowInstance,
WorkflowModel,
WorkflowPersistenceBehavior,
@ -32,6 +32,7 @@ export class ElsaWorkflowInstanceViewerScreen {
@State() workflowInstance: WorkflowInstance;
@State() workflowBlueprint: WorkflowBlueprint;
@State() workflowModel: WorkflowModel;
@State() selectedActivityId?: string;
el: HTMLElement;
designer: HTMLElsaDesignerTreeElement;
@ -157,12 +158,20 @@ export class ElsaWorkflowInstanceViewerScreen {
eventBus.emit(EventTypes.ShowWorkflowSettings);
}
onRecordSelected(e: CustomEvent<WorkflowExecutionLogRecord>) {
this.selectedActivityId = e.detail.activityId;
}
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} serverUrl={this.serverUrl} activityDescriptors={descriptors} workflowBlueprint={this.workflowBlueprint}/>
<elsa-workflow-instance-journal workflowInstanceId={this.workflowInstanceId}
serverUrl={this.serverUrl}
activityDescriptors={descriptors}
workflowBlueprint={this.workflowBlueprint}
onRecordSelected={e => this.onRecordSelected(e)}/>
</Host>
);
}
@ -170,7 +179,7 @@ export class ElsaWorkflowInstanceViewerScreen {
renderCanvas() {
return (
<div class="flex-1 flex">
<elsa-designer-tree model={this.workflowModel} class="flex-1" ref={el => this.designer = el}/>
<elsa-designer-tree model={this.workflowModel} class="flex-1" ref={el => this.designer = el} selectedActivityId={this.selectedActivityId}/>
</div>
);
}