From 47c4e5900f4eef94f6d52b142212adfccf4c0327 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sat, 25 Jun 2022 21:07:02 +0200 Subject: [PATCH] Incremental work on journal UI --- .../default-activity-template.tsx | 2 +- .../variables-editor/variables-editor.tsx | 2 +- .../workflow-definition-editor.tsx | 10 +- .../workflow-instance-viewer/models.ts | 2 + .../workflow-journal.scss | 9 ++ .../workflow-journal.tsx | 145 +++++++++++++----- .../src/components/icons/activities/delay.tsx | 5 +- .../src/components/icons/activities/event.tsx | 5 +- .../components/icons/activities/flowchart.tsx | 5 +- .../components/icons/activities/foreach.tsx | 5 +- .../icons/activities/http-endpoint.tsx | 5 +- .../src/components/icons/activities/if.tsx | 5 +- .../src/components/icons/activities/index.tsx | 1 + .../src/components/icons/activities/models.ts | 27 ++++ .../components/icons/activities/read-line.tsx | 5 +- .../icons/activities/run-javascript.tsx | 5 +- .../src/components/icons/activities/timer.tsx | 5 +- .../icons/activities/write-line.tsx | 5 +- .../workflow-definition-browser.tsx | 2 +- .../workflow-instance-browser.tsx | 2 +- .../global/{tailwind.css => tailwind.scss} | 42 ++--- .../src/plugins/sequence/sequence-plugin.tsx | 7 +- .../src/plugins/switch/switch-plugin.tsx | 7 +- .../src/services/activity-icon-registry.tsx | 22 +-- .../src/services/activity-walker.ts | 19 +++ .../elsa-workflows-designer/stencil.config.ts | 2 +- 26 files changed, 244 insertions(+), 107 deletions(-) create mode 100644 src/designer/elsa-workflows-designer/src/components/designer/workflow-instance-viewer/workflow-journal.scss create mode 100644 src/designer/elsa-workflows-designer/src/components/icons/activities/models.ts rename src/designer/elsa-workflows-designer/src/global/{tailwind.css => tailwind.scss} (83%) diff --git a/src/designer/elsa-workflows-designer/src/components/designer/activity-templates/default-activity-template.tsx b/src/designer/elsa-workflows-designer/src/components/designer/activity-templates/default-activity-template.tsx index f32fbed06..45843669c 100644 --- a/src/designer/elsa-workflows-designer/src/components/designer/activity-templates/default-activity-template.tsx +++ b/src/designer/elsa-workflows-designer/src/components/designer/activity-templates/default-activity-template.tsx @@ -119,7 +119,7 @@ export class DefaultActivityTemplate { }; private renderPort = (activity: Activity, port: Port) => { - const canStartWorkflow = activity.canStartWorkflow; + const canStartWorkflow = activity?.canStartWorkflow == true; const textColor = canStartWorkflow ? 'text-white' : 'text-gray-700'; const borderColor = port.name == this.selectedPortName ? 'border-blue-600' : 'border-gray-300'; const portName = camelCase(port.name); diff --git a/src/designer/elsa-workflows-designer/src/components/designer/variables-editor/variables-editor.tsx b/src/designer/elsa-workflows-designer/src/components/designer/variables-editor/variables-editor.tsx index dd035b803..c60aff0bb 100644 --- a/src/designer/elsa-workflows-designer/src/components/designer/variables-editor/variables-editor.tsx +++ b/src/designer/elsa-workflows-designer/src/components/designer/variables-editor/variables-editor.tsx @@ -33,7 +33,7 @@ export class VariablesEditor {
- +
diff --git a/src/designer/elsa-workflows-designer/src/components/designer/workflow-definition-editor/workflow-definition-editor.tsx b/src/designer/elsa-workflows-designer/src/components/designer/workflow-definition-editor/workflow-definition-editor.tsx index d7b648531..f9526e19d 100644 --- a/src/designer/elsa-workflows-designer/src/components/designer/workflow-definition-editor/workflow-definition-editor.tsx +++ b/src/designer/elsa-workflows-designer/src/components/designer/workflow-definition-editor/workflow-definition-editor.tsx @@ -16,7 +16,7 @@ import { ActivityUpdatedArgs, DeleteActivityRequestedArgs } from './activity-properties-editor'; -import {PluginRegistry, ActivityNameFormatter, ActivityDriverRegistry, EventBus, findActivity, walkActivities, flattenList, flatten, ActivityNode} from '../../../services'; +import {PluginRegistry, ActivityNameFormatter, ActivityDriverRegistry, EventBus, findActivity, walkActivities, flattenList, flatten, ActivityNode, createActivityMap} from '../../../services'; import {MonacoEditorSettings} from "../../../services/monaco-editor-settings"; import {Flowchart} from "../../activities/flowchart/models"; import {ActivityPropertyChangedEventArgs, WorkflowDefinitionPropsUpdatedArgs, WorkflowDefinitionUpdatedArgs, WorkflowEditorEventTypes} from "./models"; @@ -164,13 +164,7 @@ export class WorkflowDefinitionEditor { @Method() async updateWorkflowDefinition(workflowDefinition: WorkflowDefinition): Promise { this.workflowDefinitionState = workflowDefinition; - const nodes = flatten(walkActivities(workflowDefinition.root)); - const nodeMap = {}; - - for (const node of nodes) - nodeMap[node.activity.id] = node.activity; - - this.nodeMap = nodeMap; + this.nodeMap = createActivityMap(flatten(walkActivities(workflowDefinition.root))); if (this.currentWorkflowPath.length == 0) this.currentWorkflowPath = [{activityId: workflowDefinition.root.id, portName: null}]; diff --git a/src/designer/elsa-workflows-designer/src/components/designer/workflow-instance-viewer/models.ts b/src/designer/elsa-workflows-designer/src/components/designer/workflow-instance-viewer/models.ts index 64f564de1..67bcfeedf 100644 --- a/src/designer/elsa-workflows-designer/src/components/designer/workflow-instance-viewer/models.ts +++ b/src/designer/elsa-workflows-designer/src/components/designer/workflow-instance-viewer/models.ts @@ -39,6 +39,8 @@ export interface WorkflowInstancePropertiesViewerModel { export interface ActivityExecutionEventBlock { activityId: string; + parents: Array; + children: Array; completed: boolean; timestamp: Date; duration?: moment.Duration; diff --git a/src/designer/elsa-workflows-designer/src/components/designer/workflow-instance-viewer/workflow-journal.scss b/src/designer/elsa-workflows-designer/src/components/designer/workflow-instance-viewer/workflow-journal.scss new file mode 100644 index 000000000..fe886f947 --- /dev/null +++ b/src/designer/elsa-workflows-designer/src/components/designer/workflow-instance-viewer/workflow-journal.scss @@ -0,0 +1,9 @@ +table.workflow-journal-table { + tbody tr td { + @apply pl-3 pr-0 py-2; + } + + tbody tr td:first-child { + @apply pl-3 pr-0 py-2; + } +} diff --git a/src/designer/elsa-workflows-designer/src/components/designer/workflow-instance-viewer/workflow-journal.tsx b/src/designer/elsa-workflows-designer/src/components/designer/workflow-instance-viewer/workflow-journal.tsx index 0ef90577d..17ed91111 100644 --- a/src/designer/elsa-workflows-designer/src/components/designer/workflow-instance-viewer/workflow-journal.tsx +++ b/src/designer/elsa-workflows-designer/src/components/designer/workflow-instance-viewer/workflow-journal.tsx @@ -1,29 +1,36 @@ import {Component, h, Prop, State, Watch} from "@stencil/core"; -import {ActionDefinition, ActionType, ActivityDescriptor, ActivityMetadata, WorkflowDefinition, WorkflowExecutionLogRecord, WorkflowInstance} from "../../../models"; +import {ActionDefinition, ActionType, Activity, ActivityDescriptor, ActivityMetadata, WorkflowDefinition, WorkflowExecutionLogRecord, WorkflowInstance} from "../../../models"; import {Container} from "typedi"; -import {ActivityNode, ElsaApiClientProvider, flatten, walkActivities} from "../../../services"; -import {durationToString, formatTime, formatTimestamp, getDuration, isNullOrWhitespace} from "../../../utils"; +import {ActivityIconRegistry, ActivityNode, createActivityMap, createActivityNodeMap, ElsaApiClientProvider, flatten, walkActivities} from "../../../services"; +import {durationToString, formatTime, formatTimestamp, getDuration, Hash, isNullOrWhitespace} from "../../../utils"; import descriptorsStore from '../../../data/descriptors-store'; import {ActivityExecutionEventBlock} from "./models"; +import {ActivityIconSize} from "../../icons/activities"; const PAGE_SIZE: number = 20; @Component({ tag: 'elsa-workflow-journal', - shadow: false + shadow: false, + styleUrl: 'workflow-journal.scss' }) export class WorkflowJournal { private readonly elsaApiClientProvider: ElsaApiClientProvider; + private readonly iconRegistry: ActivityIconRegistry; constructor() { this.elsaApiClientProvider = Container.get(ElsaApiClientProvider); + this.iconRegistry = Container.get(ActivityIconRegistry); } @Prop() workflowInstance: WorkflowInstance; @Prop() workflowDefinition: WorkflowDefinition; - @State() activityNodes: Array = []; + @State() nodeMap: Hash = {}; + @State() nodes: Array = []; @State() workflowExecutionLogRecords: Array = []; @State() activityExecutionEventBlocks: Array = []; + @State() rootBlocks: Array = []; + @State() expandedBlocks: Array = []; @Watch('workflowInstance') async onWorkflowInstanceChanged(value: string) { @@ -42,12 +49,14 @@ export class WorkflowJournal { await this.loadJournalPage(0); } - public render() { + render() { const workflowInstance = this.workflowInstance; const workflowDefinition = this.workflowDefinition; - const activityNodes = this.activityNodes; + const nodeMap = this.nodeMap; const activityDescriptors: Array = descriptorsStore.activityDescriptors; - const eventBlocks = this.activityExecutionEventBlocks; + const blocks = this.rootBlocks; + const iconRegistry = this.iconRegistry; + const expandedBlocks = this.expandedBlocks; return ( @@ -68,40 +77,19 @@ export class WorkflowJournal {
-
Name
+
+ - + - {eventBlocks.map((eventBlock, index) => { - const activityNode = activityNodes.find(x => x.activity.id == eventBlock.activityId); - const activity = activityNode.activity; - const activityDescriptor = activityDescriptors.find(x => x.activityType == activityNode.activity.typeName); - const activityMetadata = activity.metadata; - const activityDisplayText = isNullOrWhitespace(activityMetadata.displayText) ? activity.typeName : activityMetadata.displayText; - const duration = durationToString(eventBlock.duration); - const status = eventBlock.completed ? 'Completed' : 'Started'; - - return ( - - - - - - - ); - })} + {this.renderBlocks()}
TimeActivityActivity Status Duration
{formatTime(eventBlock.timestamp)} -
{activityDisplayText}
-
{activityDescriptor.activityType}
-
- {status} - {duration}
@@ -112,13 +100,72 @@ export class WorkflowJournal { ); } + private renderBlocks = (activityId?: string) => { + const nodeMap = this.nodeMap; + const iconRegistry = this.iconRegistry; + const expandedBlocks = this.expandedBlocks; + const blocks = this.findChildBlocks(activityId); + + return blocks.map((block, index) => { + const activityNode = nodeMap[block.activityId]; + const activity = activityNode.activity; + const activityMetadata = activity.metadata; + const activityDisplayText = isNullOrWhitespace(activityMetadata.displayText) ? activity.id : activityMetadata.displayText; + const duration = durationToString(block.duration); + const status = block.completed ? 'Completed' : 'Started'; + const icon = iconRegistry.get(activity.typeName)({size: ActivityIconSize.Small}); + const expanded = !!expandedBlocks.find(x => x == block); + + const toggleIcon = expanded + ? ( + + + + + + ) + : ( + + + + + + + ); + + return ( + [ + + {block.children.length > 0 ? ( this.onBlockClick(e, block)}> + {toggleIcon} + ) : undefined} + + {formatTime(block.timestamp)} + +
+
+
+ {icon} +
+
+
{activityDisplayText}
+
+ + + {status} + + {duration} + , expanded ? this.renderBlocks(block.activityId) : undefined] + ); + }); + } + private createGraph = () => { if (!this.workflowInstance || !this.workflowDefinition) return; - const rootNode = walkActivities(this.workflowDefinition.root); - const nodes = flatten(rootNode); - this.activityNodes = nodes; + this.nodes = flatten(walkActivities(this.workflowDefinition.root)); + this.nodeMap = createActivityNodeMap(this.nodes); }; private loadJournalPage = async (page: number): Promise => { @@ -131,18 +178,25 @@ export class WorkflowJournal { const blocks = this.groupRecords(pageOfRecords.items); this.workflowExecutionLogRecords = [...this.workflowExecutionLogRecords, ...pageOfRecords.items]; this.activityExecutionEventBlocks = [...this.activityExecutionEventBlocks, ...blocks]; + this.rootBlocks = this.findChildBlocks(null); } private groupRecords = (records: Array): Array => { const startedEvents = records.filter(x => x.eventName == 'Started'); const completedEvents = records.filter(x => x.eventName == 'Completed'); + const nodeMap = this.nodeMap; const blocks: Array = startedEvents.map(startedRecord => { const completedRecord = completedEvents.find(x => x.activityInstanceId == startedRecord.activityInstanceId); const duration = !!completedRecord ? getDuration(completedRecord.timestamp, startedRecord.timestamp) : null; + const node = nodeMap[startedRecord.activityId]; + const parents = node.parents.map(x => x.activity.id); + const children = node.children.map(x => x.activity.id); return { activityId: startedRecord.activityId, + parents: parents, + children: children, completed: !!completedRecord, timestamp: startedRecord.timestamp, duration: duration, @@ -153,4 +207,23 @@ export class WorkflowJournal { return blocks; }; + + private findChildBlocks = (parentActivityId?: string): Array => { + const blocks = this.activityExecutionEventBlocks; + + if (blocks.length == 0) + return []; + + if (!!parentActivityId) + return blocks.filter(x => !!x.parents.find(p => p == parentActivityId)); + + return blocks.filter(x => x.parents.length == 0); + } + + private onBlockClick = (e: MouseEvent, block: ActivityExecutionEventBlock) => { + e.preventDefault(); + + const existingBlock = this.expandedBlocks.find(x => x == block); + this.expandedBlocks = existingBlock ? this.expandedBlocks.filter(x => x != existingBlock) : [...this.expandedBlocks, block]; + }; } diff --git a/src/designer/elsa-workflows-designer/src/components/icons/activities/delay.tsx b/src/designer/elsa-workflows-designer/src/components/icons/activities/delay.tsx index d2a2aee39..9f0e9bf8d 100644 --- a/src/designer/elsa-workflows-designer/src/components/icons/activities/delay.tsx +++ b/src/designer/elsa-workflows-designer/src/components/icons/activities/delay.tsx @@ -1,7 +1,8 @@ import {FunctionalComponent, h} from '@stencil/core'; +import {getActivityIconCssClass, ActivityIconSettings} from "./models"; -export const DelayIcon: FunctionalComponent = () => ( - +export const DelayIcon: FunctionalComponent = (settings) => ( + diff --git a/src/designer/elsa-workflows-designer/src/components/icons/activities/event.tsx b/src/designer/elsa-workflows-designer/src/components/icons/activities/event.tsx index 846a77d42..1a23a08b7 100644 --- a/src/designer/elsa-workflows-designer/src/components/icons/activities/event.tsx +++ b/src/designer/elsa-workflows-designer/src/components/icons/activities/event.tsx @@ -1,7 +1,8 @@ import {FunctionalComponent, h} from '@stencil/core'; +import {ActivityIconSettings, getActivityIconCssClass} from "./models"; -export const EventIcon: FunctionalComponent = () => ( - +export const EventIcon: FunctionalComponent = (settings) => ( + diff --git a/src/designer/elsa-workflows-designer/src/components/icons/activities/flowchart.tsx b/src/designer/elsa-workflows-designer/src/components/icons/activities/flowchart.tsx index 295631304..211afdaf2 100644 --- a/src/designer/elsa-workflows-designer/src/components/icons/activities/flowchart.tsx +++ b/src/designer/elsa-workflows-designer/src/components/icons/activities/flowchart.tsx @@ -1,7 +1,8 @@ import {FunctionalComponent, h} from '@stencil/core'; +import {getActivityIconCssClass, ActivityIconSettings} from "./models"; -export const FlowchartIcon: FunctionalComponent = () => ( - +export const FlowchartIcon: FunctionalComponent = (settings) => ( + diff --git a/src/designer/elsa-workflows-designer/src/components/icons/activities/foreach.tsx b/src/designer/elsa-workflows-designer/src/components/icons/activities/foreach.tsx index 85465d419..b30af99b5 100644 --- a/src/designer/elsa-workflows-designer/src/components/icons/activities/foreach.tsx +++ b/src/designer/elsa-workflows-designer/src/components/icons/activities/foreach.tsx @@ -1,7 +1,8 @@ import {FunctionalComponent, h} from '@stencil/core'; +import {ActivityIconSettings, getActivityIconCssClass} from "./models"; -export const ForEachIcon: FunctionalComponent = () => ( - +export const ForEachIcon: FunctionalComponent = (settings) => ( + diff --git a/src/designer/elsa-workflows-designer/src/components/icons/activities/http-endpoint.tsx b/src/designer/elsa-workflows-designer/src/components/icons/activities/http-endpoint.tsx index 57110bf02..522004d43 100644 --- a/src/designer/elsa-workflows-designer/src/components/icons/activities/http-endpoint.tsx +++ b/src/designer/elsa-workflows-designer/src/components/icons/activities/http-endpoint.tsx @@ -1,7 +1,8 @@ import {FunctionalComponent, h} from '@stencil/core'; +import {ActivityIconSettings, getActivityIconCssClass} from "./models"; -export const HttpEndpointIcon: FunctionalComponent = () => ( - = (settings) => ( + diff --git a/src/designer/elsa-workflows-designer/src/components/icons/activities/if.tsx b/src/designer/elsa-workflows-designer/src/components/icons/activities/if.tsx index 8a9886b94..b8fce3cf4 100644 --- a/src/designer/elsa-workflows-designer/src/components/icons/activities/if.tsx +++ b/src/designer/elsa-workflows-designer/src/components/icons/activities/if.tsx @@ -1,7 +1,8 @@ import {FunctionalComponent, h} from '@stencil/core'; +import {ActivityIconSettings, getActivityIconCssClass} from "./models"; -export const IfIcon: FunctionalComponent = () => ( - +export const IfIcon: FunctionalComponent = (settings) => ( + ); diff --git a/src/designer/elsa-workflows-designer/src/components/icons/activities/index.tsx b/src/designer/elsa-workflows-designer/src/components/icons/activities/index.tsx index e51842866..e356c67d1 100644 --- a/src/designer/elsa-workflows-designer/src/components/icons/activities/index.tsx +++ b/src/designer/elsa-workflows-designer/src/components/icons/activities/index.tsx @@ -8,3 +8,4 @@ export * from "./foreach"; export * from "./delay"; export * from "./timer"; export * from "./run-javascript"; +export * from "./models"; diff --git a/src/designer/elsa-workflows-designer/src/components/icons/activities/models.ts b/src/designer/elsa-workflows-designer/src/components/icons/activities/models.ts new file mode 100644 index 000000000..eb92c5b86 --- /dev/null +++ b/src/designer/elsa-workflows-designer/src/components/icons/activities/models.ts @@ -0,0 +1,27 @@ +export enum ActivityIconSize { + Small, + Medium, + Large +} + +export interface ActivityIconSettings { + size?: ActivityIconSize; +} + +export function getActivityIconCssClass(settings: ActivityIconSettings) { + const cssClasses = ['text-white', sizeToClass(settings.size)]; + return cssClasses.join(' '); +} + +function sizeToClass(size?: ActivityIconSize) { + switch (size) { + case ActivityIconSize.Small: + return 'h-4 w-4'; + case ActivityIconSize.Medium: + return 'h-6 w-6'; + case ActivityIconSize.Large: + return 'h-10 w-10'; + default: + return 'h-6 w-6'; + } +} diff --git a/src/designer/elsa-workflows-designer/src/components/icons/activities/read-line.tsx b/src/designer/elsa-workflows-designer/src/components/icons/activities/read-line.tsx index dcaa82091..73d2e535d 100644 --- a/src/designer/elsa-workflows-designer/src/components/icons/activities/read-line.tsx +++ b/src/designer/elsa-workflows-designer/src/components/icons/activities/read-line.tsx @@ -1,7 +1,8 @@ import {FunctionalComponent, h} from '@stencil/core'; +import {ActivityIconSettings, getActivityIconCssClass} from "./models"; -export const ReadLineIcon: FunctionalComponent = () => ( - +export const ReadLineIcon: FunctionalComponent = (settings) => ( + diff --git a/src/designer/elsa-workflows-designer/src/components/icons/activities/run-javascript.tsx b/src/designer/elsa-workflows-designer/src/components/icons/activities/run-javascript.tsx index f82578ad8..e62fb62cb 100644 --- a/src/designer/elsa-workflows-designer/src/components/icons/activities/run-javascript.tsx +++ b/src/designer/elsa-workflows-designer/src/components/icons/activities/run-javascript.tsx @@ -1,7 +1,8 @@ import {FunctionalComponent, h} from '@stencil/core'; +import {ActivityIconSettings, getActivityIconCssClass} from "./models"; -export const RunJavaScriptIcon: FunctionalComponent = () => ( - +export const RunJavaScriptIcon: FunctionalComponent = (settings) => ( + diff --git a/src/designer/elsa-workflows-designer/src/components/icons/activities/timer.tsx b/src/designer/elsa-workflows-designer/src/components/icons/activities/timer.tsx index 2ce3b350c..4ff91736b 100644 --- a/src/designer/elsa-workflows-designer/src/components/icons/activities/timer.tsx +++ b/src/designer/elsa-workflows-designer/src/components/icons/activities/timer.tsx @@ -1,7 +1,8 @@ import {FunctionalComponent, h} from '@stencil/core'; +import {ActivityIconSettings, getActivityIconCssClass} from "./models"; -export const TimerIcon: FunctionalComponent = () => ( - +export const TimerIcon: FunctionalComponent = (settings) => ( + diff --git a/src/designer/elsa-workflows-designer/src/components/icons/activities/write-line.tsx b/src/designer/elsa-workflows-designer/src/components/icons/activities/write-line.tsx index 91b6b14aa..681c6d13e 100644 --- a/src/designer/elsa-workflows-designer/src/components/icons/activities/write-line.tsx +++ b/src/designer/elsa-workflows-designer/src/components/icons/activities/write-line.tsx @@ -1,7 +1,8 @@ import {FunctionalComponent, h} from '@stencil/core'; +import {ActivityIconSettings, getActivityIconCssClass} from "./models"; -export const WriteLineIcon: FunctionalComponent = () => ( - +export const WriteLineIcon: FunctionalComponent = (settings) => ( + diff --git a/src/designer/elsa-workflows-designer/src/components/modals/workflow-definition-browser/workflow-definition-browser.tsx b/src/designer/elsa-workflows-designer/src/components/modals/workflow-definition-browser/workflow-definition-browser.tsx index 196a96c58..2fb89bf88 100644 --- a/src/designer/elsa-workflows-designer/src/components/modals/workflow-definition-browser/workflow-definition-browser.tsx +++ b/src/designer/elsa-workflows-designer/src/components/modals/workflow-definition-browser/workflow-definition-browser.tsx @@ -154,7 +154,7 @@ export class WorkflowDefinitionBrowser {

Workflow Definitions

- +
diff --git a/src/designer/elsa-workflows-designer/src/components/modals/workflow-instance-browser/workflow-instance-browser.tsx b/src/designer/elsa-workflows-designer/src/components/modals/workflow-instance-browser/workflow-instance-browser.tsx index acbbbe417..cfb5b7dd6 100644 --- a/src/designer/elsa-workflows-designer/src/components/modals/workflow-instance-browser/workflow-instance-browser.tsx +++ b/src/designer/elsa-workflows-designer/src/components/modals/workflow-instance-browser/workflow-instance-browser.tsx @@ -98,7 +98,7 @@ export class WorkflowInstanceBrowser {
- +
diff --git a/src/designer/elsa-workflows-designer/src/global/tailwind.css b/src/designer/elsa-workflows-designer/src/global/tailwind.scss similarity index 83% rename from src/designer/elsa-workflows-designer/src/global/tailwind.css rename to src/designer/elsa-workflows-designer/src/global/tailwind.scss index 7d43d697d..3cd238054 100644 --- a/src/designer/elsa-workflows-designer/src/global/tailwind.css +++ b/src/designer/elsa-workflows-designer/src/global/tailwind.scss @@ -83,34 +83,34 @@ textarea { /* Tables */ table { @apply min-w-full; -} -thead tr { - @apply border-t border-gray-200; -} + thead tr { + @apply border-t border-gray-200; + } -thead tr th { - @apply px-6 py-3 border-b border-gray-200 bg-gray-50 text-xs leading-4 font-medium text-left text-gray-500 uppercase tracking-wider; -} + thead tr th { + @apply px-6 py-3 border-b border-gray-200 bg-gray-50 text-xs leading-4 font-medium text-left text-gray-500 uppercase tracking-wider; + } -thead tr th.optional, tbody tr td.optional { - @apply hidden md:table-cell; -} + thead tr th.optional, tbody tr td.optional { + @apply hidden md:table-cell; + } -table thead tr th.align-right, tbody tr td.align-right { - @apply text-right; -} + table thead tr th.align-right, tbody tr td.align-right { + @apply text-right; + } -tbody { - @apply bg-white divide-y divide-gray-100; -} + tbody { + @apply bg-white divide-y divide-gray-100; + } -tbody tr td { - @apply px-6 py-3 text-sm leading-5 text-gray-500 font-medium; -} + tbody tr td { + @apply px-6 py-3 text-sm leading-5 text-gray-500 font-medium; + } -tbody tr td:first-child { - @apply px-6 py-3 whitespace-nowrap text-sm leading-5 font-medium text-gray-900; + tbody tr td:first-child { + @apply px-6 py-3 whitespace-nowrap text-sm leading-5 font-medium text-gray-900; + } } /* Pager */ diff --git a/src/designer/elsa-workflows-designer/src/plugins/sequence/sequence-plugin.tsx b/src/designer/elsa-workflows-designer/src/plugins/sequence/sequence-plugin.tsx index 7d6597ba7..b373fef57 100644 --- a/src/designer/elsa-workflows-designer/src/plugins/sequence/sequence-plugin.tsx +++ b/src/designer/elsa-workflows-designer/src/plugins/sequence/sequence-plugin.tsx @@ -3,6 +3,7 @@ import {FunctionalComponent, h} from '@stencil/core'; import {Container, Service} from "typedi"; import {ActivityIconRegistry} from "../../services"; import {Plugin} from "../../models"; +import {ActivityIconSettings, getActivityIconCssClass} from "../../components/icons/activities"; @Service() export class SequencePlugin implements Plugin { @@ -11,12 +12,12 @@ export class SequencePlugin implements Plugin { constructor() { const iconRegistry = Container.get(ActivityIconRegistry); - iconRegistry.add(SequencePlugin.ActivityTypeName, () => ); + iconRegistry.add(SequencePlugin.ActivityTypeName, settings => ); } } -const SequenceIcon: FunctionalComponent = () => ( - +const SequenceIcon: FunctionalComponent = (settings) => ( + diff --git a/src/designer/elsa-workflows-designer/src/plugins/switch/switch-plugin.tsx b/src/designer/elsa-workflows-designer/src/plugins/switch/switch-plugin.tsx index 339817173..ad1354670 100644 --- a/src/designer/elsa-workflows-designer/src/plugins/switch/switch-plugin.tsx +++ b/src/designer/elsa-workflows-designer/src/plugins/switch/switch-plugin.tsx @@ -4,6 +4,7 @@ import {Container, Service} from "typedi"; import {ActivityIconRegistry, InputControlRegistry, PortProviderRegistry} from "../../services"; import {Plugin} from "../../models"; import {SwitchPortProvider} from "./switch-port-provider"; +import {ActivityIconSettings, getActivityIconCssClass} from "../../components/icons/activities"; @Service() export class SwitchPlugin implements Plugin { @@ -17,12 +18,12 @@ export class SwitchPlugin implements Plugin { inputControlRegistry.add('switch-editor', c => ); portProviderRegistry.add(activityTypeName, () => Container.get(SwitchPortProvider)); - iconRegistry.add(SwitchPlugin.ActivityTypeName, () => ); + iconRegistry.add(SwitchPlugin.ActivityTypeName, settings => ); } } -const SwitchIcon: FunctionalComponent = () => ( - +const SwitchIcon: FunctionalComponent = (settings) => ( + diff --git a/src/designer/elsa-workflows-designer/src/services/activity-icon-registry.tsx b/src/designer/elsa-workflows-designer/src/services/activity-icon-registry.tsx index 2a58680f6..5176cd407 100644 --- a/src/designer/elsa-workflows-designer/src/services/activity-icon-registry.tsx +++ b/src/designer/elsa-workflows-designer/src/services/activity-icon-registry.tsx @@ -16,7 +16,7 @@ import { } from "../components/icons/activities"; export type ActivityType = string; -export type ActivityIcon = () => any; +export type ActivityIcon = (ActivityIconSettings?) => any; // A registry of activity icons. @Service() @@ -24,16 +24,16 @@ export class ActivityIconRegistry { private iconMap: Map = new Map(); constructor() { - this.add('Elsa.WriteLine', () => ); - this.add('Elsa.ReadLine', () => ); - this.add('Elsa.If', () => ); - this.add('Elsa.Flowchart', () => ); - this.add('Elsa.HttpEndpoint', () => ); - this.add('Elsa.ForEach', () => ); - this.add('Elsa.Delay', () => ); - this.add('Elsa.Timer', () => ); - this.add('Elsa.Event', () => ); - this.add('Elsa.RunJavaScript', () => ); + this.add('Elsa.WriteLine', settings => ); + this.add('Elsa.ReadLine', settings => ); + this.add('Elsa.If', settings => ); + this.add('Elsa.Flowchart', settings => ); + this.add('Elsa.HttpEndpoint', settings => ); + this.add('Elsa.ForEach', settings => ); + this.add('Elsa.Delay', settings => ); + this.add('Elsa.Timer', settings => ); + this.add('Elsa.Event', settings => ); + this.add('Elsa.RunJavaScript', settings => ); } public add(activityType: ActivityType, icon: ActivityIcon) { diff --git a/src/designer/elsa-workflows-designer/src/services/activity-walker.ts b/src/designer/elsa-workflows-designer/src/services/activity-walker.ts index 9e41966d9..5fd80886d 100644 --- a/src/designer/elsa-workflows-designer/src/services/activity-walker.ts +++ b/src/designer/elsa-workflows-designer/src/services/activity-walker.ts @@ -4,6 +4,7 @@ import {Container} from "typedi" import {Activity, ActivityDescriptor} from "../models"; import {PortProviderRegistry} from "./port-provider-registry"; import descriptorsStore from '../data/descriptors-store'; +import {Hash} from "../utils"; export interface ActivityNode { activity: Activity; @@ -17,6 +18,24 @@ export interface ActivityPort { port: string; } +export function createActivityMap(nodes: Array): Hash { + const map = {}; + + for (const node of nodes) + map[node.activity.id] = node.activity; + + return map; +} + +export function createActivityNodeMap(nodes: Array): Hash { + const map = {}; + + for (const node of nodes) + map[node.activity.id] = node; + + return map; +} + export function walkActivities(root: Activity): ActivityNode { const descriptors = descriptorsStore.activityDescriptors; const collectedActivities = new Set([root]); diff --git a/src/designer/elsa-workflows-designer/stencil.config.ts b/src/designer/elsa-workflows-designer/stencil.config.ts index 1a00120cb..bba2f4412 100644 --- a/src/designer/elsa-workflows-designer/stencil.config.ts +++ b/src/designer/elsa-workflows-designer/stencil.config.ts @@ -10,7 +10,7 @@ const dev: boolean = process.argv && process.argv.indexOf('--dev') > -1; export const config: Config = { namespace: 'elsa-workflows-designer', - globalStyle: 'src/global/tailwind.css', + globalStyle: 'src/global/tailwind.scss', outputTargets: [ { type: 'dist',