Implement versioned activities
This commit is contained in:
parent
4a2325d207
commit
7870012254
|
|
@ -96,6 +96,7 @@ export namespace Components {
|
|||
interface ElsaDefaultActivityTemplate {
|
||||
"activityId": string;
|
||||
"activityType": string;
|
||||
"activityTypeVersion": number;
|
||||
"displayType": string;
|
||||
}
|
||||
interface ElsaDropdownButton {
|
||||
|
|
@ -728,6 +729,7 @@ declare namespace LocalJSX {
|
|||
interface ElsaDefaultActivityTemplate {
|
||||
"activityId"?: string;
|
||||
"activityType"?: string;
|
||||
"activityTypeVersion"?: number;
|
||||
"displayType"?: string;
|
||||
"onChildActivitySelected"?: (event: CustomEvent<ChildActivitySelectedArgs>) => void;
|
||||
"onEditChildActivity"?: (event: CustomEvent<EditChildActivityArgs>) => void;
|
||||
|
|
|
|||
|
|
@ -8,11 +8,12 @@ export class DefaultActivityDriver implements ActivityDriver {
|
|||
|
||||
display(context: ActivityDisplayContext): any {
|
||||
const activityDescriptor = context.activityDescriptor;
|
||||
const activityType = activityDescriptor.activityType;
|
||||
const type = activityDescriptor.type;
|
||||
const version = activityDescriptor.version;
|
||||
const activity = context.activity;
|
||||
const activityId = activity?.id;
|
||||
const displayType = context.displayType;
|
||||
|
||||
return (`<elsa-default-activity-template activity-type="${activityType}" activity-id="${activityId}" display-type="${displayType}" />`);
|
||||
return (`<elsa-default-activity-template activity-type="${type}" activity-type-version="${version}" activity-id="${activityId}" display-type="${displayType}" />`);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
activityNameFormatter.strategy = ActivityNameFormatter.PascalCaseStrategy;
|
||||
|
||||
// Or install a custom name formatter strategy.
|
||||
//activityNameFormatter.strategy = context => `${stripActivityNameSpace(context.activityDescriptor.activityType)}_${context.count}`;
|
||||
//activityNameFormatter.strategy = context => `${stripActivityNameSpace(context.activityDescriptor.type)}_${context.count}`;
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ export type Lookup<T> = { [key: string]: T };
|
|||
|
||||
export interface Activity {
|
||||
id: string;
|
||||
typeName: string;
|
||||
type: string;
|
||||
version: number;
|
||||
metadata: any;
|
||||
canStartWorkflow?: boolean;
|
||||
applicationProperties: any;
|
||||
|
|
@ -64,7 +65,8 @@ export interface WorkflowState {
|
|||
}
|
||||
|
||||
export interface ActivityDescriptor {
|
||||
activityType: string;
|
||||
type: string;
|
||||
version: number;
|
||||
displayName: string;
|
||||
category: string;
|
||||
description: string;
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ export class ActivityDefinitionBrowser {
|
|||
const publishedVersionNumber = !!publishedVersion ? publishedVersion.version : '-';
|
||||
|
||||
const isSelected = this.selectedActivityDefinitionIds.findIndex(x => x === definition.definitionId) >= 0;
|
||||
let displayName = definition.displayName || definition.typeName;
|
||||
let displayName = definition.displayName || definition.type;
|
||||
|
||||
if (!displayName || displayName.trim().length == 0) displayName = 'Untitled';
|
||||
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ export class Editor {
|
|||
const activityDefinition: ActivityDefinition = {
|
||||
root: newRoot,
|
||||
id: '',
|
||||
typeName: 'Activity1',
|
||||
type: 'Activity1',
|
||||
displayName: 'Activity 1',
|
||||
category: 'Custom',
|
||||
definitionId: '',
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ export class Properties {
|
|||
content: () => {
|
||||
const definition = this.activityDefinition;
|
||||
return <FormEntry label="Type Name" fieldId="activityDefinitionTypeName" hint="The type name of the custom activity.">
|
||||
<input type="text" name="activityDefinitionTypeName" id="activityDefinitionTypeName" value={definition.typeName} onChange={e => this.onPropertyEditorChanged(a => a.typeName = (e.target as HTMLInputElement).value)}/>
|
||||
<input type="text" name="activityDefinitionTypeName" id="activityDefinitionTypeName" value={definition.type} onChange={e => this.onPropertyEditorChanged(a => a.type = (e.target as HTMLInputElement).value)}/>
|
||||
</FormEntry>;
|
||||
},
|
||||
order: 0
|
||||
|
|
@ -164,7 +164,7 @@ export class Properties {
|
|||
|
||||
render() {
|
||||
const activityDefinition = this.activityDefinition;
|
||||
const title = activityDefinition?.displayName ?? activityDefinition?.typeName ?? 'Untitled';
|
||||
const title = activityDefinition?.displayName ?? activityDefinition?.type ?? 'Untitled';
|
||||
const subTitle = 'Activity Definition'
|
||||
const tabs = this.model.tabModels.map(x => x.tab);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import {TabModel} from "../workflow-definitions/models/ui";
|
|||
|
||||
export interface ActivityDefinition extends VersionedEntity {
|
||||
definitionId: string;
|
||||
typeName: string;
|
||||
type: string;
|
||||
displayName?: string;
|
||||
category?: string;
|
||||
description?: string;
|
||||
|
|
@ -18,7 +18,7 @@ export interface ActivityDefinitionSummary {
|
|||
id: string;
|
||||
definitionId: string;
|
||||
version: number;
|
||||
typeName: string;
|
||||
type: string;
|
||||
displayName?: string;
|
||||
category?: string;
|
||||
description?: string;
|
||||
|
|
@ -28,7 +28,7 @@ export interface ActivityDefinitionSummary {
|
|||
|
||||
export interface SaveActivityDefinitionRequest {
|
||||
definitionId: string;
|
||||
typeName: string;
|
||||
type: string;
|
||||
displayName?: string;
|
||||
category?: string;
|
||||
description?: string;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,8 @@ export class ActivityDefinitionsPlugin implements Plugin {
|
|||
const newName = await this.generateUniqueActivityName(flowchartDescriptor);
|
||||
|
||||
const flowchart = {
|
||||
typeName: flowchartDescriptor.activityType,
|
||||
type: flowchartDescriptor.type,
|
||||
version: 1,
|
||||
activities: [],
|
||||
connections: [],
|
||||
id: newName,
|
||||
|
|
@ -75,7 +76,7 @@ export class ActivityDefinitionsPlugin implements Plugin {
|
|||
root: flowchart,
|
||||
id: '',
|
||||
definitionId: '',
|
||||
typeName: 'Activity1',
|
||||
type: 'Activity1',
|
||||
category: 'Custom',
|
||||
displayName: 'Activity 1',
|
||||
version: 1,
|
||||
|
|
@ -87,7 +88,7 @@ export class ActivityDefinitionsPlugin implements Plugin {
|
|||
};
|
||||
|
||||
private getFlowchartDescriptor = () => this.getActivityDescriptor(FlowchartTypeName);
|
||||
private getActivityDescriptor = (typeName: string): ActivityDescriptor => descriptorsStore.activityDescriptors.find(x => x.activityType == typeName)
|
||||
private getActivityDescriptor = (typeName: string): ActivityDescriptor => descriptorsStore.activityDescriptors.find(x => x.type == typeName)
|
||||
private generateUniqueActivityName = async (activityDescriptor: ActivityDescriptor): Promise<string> => await generateUniqueActivityName([], activityDescriptor);
|
||||
|
||||
private saveActivityDefinition = async (definition: ActivityDefinition, publish: boolean): Promise<ActivityDefinition> => {
|
||||
|
|
@ -132,9 +133,9 @@ export class ActivityDefinitionsPlugin implements Plugin {
|
|||
private onPublishClicked = async (e: CustomEvent<PublishClickedArgs>) => {
|
||||
e.detail.begin();
|
||||
const activityDefinition = await this.activityDefinitionEditorElement.getActivityDefinition();
|
||||
await this.eventBus.emit(NotificationEventTypes.Add, this, {id: activityDefinition.definitionId, message: `Starting publishing ${activityDefinition.typeName}`});
|
||||
await this.eventBus.emit(NotificationEventTypes.Add, this, {id: activityDefinition.definitionId, message: `Starting publishing ${activityDefinition.type}`});
|
||||
await this.saveActivityDefinition(activityDefinition, true);
|
||||
await this.eventBus.emit(NotificationEventTypes.Update, this, {id: activityDefinition.definitionId, message: `${activityDefinition.typeName} publish finished`});
|
||||
await this.eventBus.emit(NotificationEventTypes.Update, this, {id: activityDefinition.definitionId, message: `${activityDefinition.type} publish finished`});
|
||||
e.detail.complete();
|
||||
|
||||
// Reload activity descriptors.
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export class ActivityDefinitionManager {
|
|||
public save = async (definition: ActivityDefinition, publish: boolean): Promise<ActivityDefinition> => {
|
||||
const request: SaveActivityDefinitionRequest = {
|
||||
definitionId: definition.definitionId,
|
||||
typeName: definition.typeName,
|
||||
type: definition.type,
|
||||
displayName: definition.displayName,
|
||||
category: definition.category,
|
||||
description: definition.description,
|
||||
|
|
|
|||
|
|
@ -18,12 +18,10 @@ export class FlowSwitchPortProvider implements PortProvider {
|
|||
}
|
||||
|
||||
resolvePort(portName: string, context: PortProviderContext): Activity | Array<Activity> {
|
||||
debugger;
|
||||
return null;
|
||||
}
|
||||
|
||||
assignPort(portName: string, activity: Activity, context: PortProviderContext) {
|
||||
debugger;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ export class DefaultActivityTemplate {
|
|||
}
|
||||
|
||||
@Prop({attribute: 'activity-type'}) activityType: string;
|
||||
@Prop({attribute: 'activity-type-version'}) activityTypeVersion: number = 1;
|
||||
@Prop({attribute: 'display-type'}) displayType: string;
|
||||
@Prop({attribute: 'activity-id'}) activityId: string;
|
||||
@Event() editChildActivity: EventEmitter<EditChildActivityArgs>;
|
||||
|
|
@ -31,8 +32,9 @@ export class DefaultActivityTemplate {
|
|||
|
||||
componentWillLoad() {
|
||||
const iconRegistry = this.iconRegistry;
|
||||
this.activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.activityType == this.activityType);
|
||||
const activityType = this.activityType;
|
||||
const activityTypeVersion = this.activityTypeVersion ?? 0;
|
||||
this.activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.type == activityType && x.version == activityTypeVersion);
|
||||
this.icon = iconRegistry.has(activityType) ? iconRegistry.get(activityType) : null;
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +109,7 @@ export class DefaultActivityTemplate {
|
|||
return;
|
||||
|
||||
const activityDescriptor = this.activityDescriptor;
|
||||
const portProvider = this.portProviderRegistry.get(activityDescriptor.activityType);
|
||||
const portProvider = this.portProviderRegistry.get(activityDescriptor.type);
|
||||
const ports = portProvider.getOutboundPorts({ activityDescriptor, activity });
|
||||
const embeddedPorts = ports.filter(x => x.mode == PortMode.Embedded);
|
||||
|
||||
|
|
@ -126,9 +128,9 @@ export class DefaultActivityTemplate {
|
|||
const textColor = canStartWorkflow ? 'text-white' : 'text-gray-700';
|
||||
const borderColor = port.name == this.selectedPortName ? 'border-blue-600' : 'border-gray-300';
|
||||
const activityDescriptor = this.activityDescriptor;
|
||||
const portProvider = this.portProviderRegistry.get(activityDescriptor.activityType);
|
||||
const portProvider = this.portProviderRegistry.get(activityDescriptor.type);
|
||||
const activityProperty = portProvider.resolvePort(port.name, { activity, activityDescriptor }) as Activity;
|
||||
const childActivityDescriptor: ActivityDescriptor = activityProperty != null ? descriptorsStore.activityDescriptors.find(x => x.activityType == activityProperty.typeName) : null;
|
||||
const childActivityDescriptor: ActivityDescriptor = activityProperty != null ? descriptorsStore.activityDescriptors.find(x => x.type == activityProperty.type) : null;
|
||||
let childActivityDisplayText = activityProperty?.metadata?.displayText;
|
||||
|
||||
if (isNullOrWhitespace(childActivityDisplayText))
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export class DefaultNodeHandler implements ActivityNodeHandler {
|
|||
|
||||
createDesignerNode(context: CreateUINodeContext): Node.Metadata {
|
||||
const {activityDescriptor, activity, x, y} = context;
|
||||
const provider = this.portProviderRegistry.get(activityDescriptor.activityType);
|
||||
const provider = this.portProviderRegistry.get(activityDescriptor.type);
|
||||
const providerContext: PortProviderContext = {activityDescriptor, activity};
|
||||
const inPorts = [{name: 'In', displayName: null, mode: PortMode.Port}];
|
||||
let outPorts = provider.getOutboundPorts(providerContext).filter(x => x.mode == PortMode.Port);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,8 @@ export class FlowchartComponent implements ContainerActivityComponent {
|
|||
const newName = await this.generateUniqueActivityName(flowchartDescriptor);
|
||||
|
||||
const flowchart = {
|
||||
typeName: flowchartDescriptor.activityType,
|
||||
type: flowchartDescriptor.type,
|
||||
version: 1,
|
||||
activities: [],
|
||||
connections: [],
|
||||
id: newName,
|
||||
|
|
@ -120,7 +121,8 @@ export class FlowchartComponent implements ContainerActivityComponent {
|
|||
|
||||
const activity: Activity = {
|
||||
id: id,
|
||||
typeName: descriptor.activityType,
|
||||
type: descriptor.type,
|
||||
version: descriptor.version,
|
||||
applicationProperties: {},
|
||||
metadata: {
|
||||
designer: {
|
||||
|
|
@ -218,7 +220,7 @@ export class FlowchartComponent implements ContainerActivityComponent {
|
|||
const currentActivityId = this.currentPath[this.currentPath.length - 1].activityId;
|
||||
const currentActivity = this.activityLookup[currentActivityId];
|
||||
const parentActivity = this.activityLookup[parentActivityId] as Flowchart;
|
||||
const parentActivityDescriptor = descriptorsStore.activityDescriptors.find(x => x.activityType == parentActivity.typeName);
|
||||
const parentActivityDescriptor = descriptorsStore.activityDescriptors.find(x => x.type == parentActivity.type);
|
||||
const indexInParent = currentActivity.activities?.findIndex(x => x == parentActivity);
|
||||
const portName = e.detail.port.name;
|
||||
|
||||
|
|
@ -228,7 +230,7 @@ export class FlowchartComponent implements ContainerActivityComponent {
|
|||
index: indexInParent
|
||||
};
|
||||
|
||||
const portProvider = this.portProviderRegistry.get(parentActivity.typeName);
|
||||
const portProvider = this.portProviderRegistry.get(parentActivity.type);
|
||||
let activityProperty = portProvider.resolvePort(portName, {activity: parentActivity, activityDescriptor: parentActivityDescriptor}) as Flowchart;
|
||||
|
||||
if (!activityProperty) {
|
||||
|
|
@ -254,7 +256,8 @@ export class FlowchartComponent implements ContainerActivityComponent {
|
|||
const activityId = await this.generateUniqueActivityName(descriptor);
|
||||
|
||||
return {
|
||||
typeName: descriptor.activityType,
|
||||
type: descriptor.type,
|
||||
version: descriptor.version,
|
||||
id: activityId,
|
||||
start: null,
|
||||
activities: [],
|
||||
|
|
@ -326,10 +329,10 @@ export class FlowchartComponent implements ContainerActivityComponent {
|
|||
const currentNavigationItem = currentPath[currentPath.length - 1];
|
||||
const currentPortName = currentNavigationItem?.portName;
|
||||
const currentScope = this.activityLookup[currentNavigationItem.activityId] as Activity;
|
||||
const currentScopeDescriptor = this.getActivityDescriptor(currentScope.typeName);
|
||||
const currentScopeDescriptor = this.getActivityDescriptor(currentScope.type);
|
||||
|
||||
if (!!currentPortName) {
|
||||
const portProvider = this.portProviderRegistry.get(currentScope.typeName);
|
||||
const portProvider = this.portProviderRegistry.get(currentScope.type);
|
||||
portProvider.assignPort(currentPortName, currentLevel, {activity: currentScope, activityDescriptor: currentScopeDescriptor});
|
||||
} else {
|
||||
this.activity = currentLevel;
|
||||
|
|
@ -354,7 +357,7 @@ export class FlowchartComponent implements ContainerActivityComponent {
|
|||
await this.setupGraph(flowchart);
|
||||
};
|
||||
|
||||
private getActivityDescriptor = (typeName: string): ActivityDescriptor => descriptorsStore.activityDescriptors.find(x => x.activityType == typeName)
|
||||
private getActivityDescriptor = (typeName: string): ActivityDescriptor => descriptorsStore.activityDescriptors.find(x => x.type == typeName)
|
||||
|
||||
private setupGraph = async (flowchart: Flowchart) => {
|
||||
const activities = flowchart.activities;
|
||||
|
|
@ -365,7 +368,7 @@ export class FlowchartComponent implements ContainerActivityComponent {
|
|||
const nodes: Array<Node.Metadata> = activities.map(activity => {
|
||||
const position = activity.metadata.designer?.position || {x: 100, y: 100};
|
||||
const {x, y} = position;
|
||||
const descriptor = this.getActivityDescriptor(activity.typeName);
|
||||
const descriptor = this.getActivityDescriptor(activity.type);
|
||||
return this.nodeFactory.createNode(descriptor, activity, x, y);
|
||||
});
|
||||
|
||||
|
|
@ -443,12 +446,12 @@ export class FlowchartComponent implements ContainerActivityComponent {
|
|||
return this.activity;
|
||||
|
||||
const activity = this.activityLookup[currentItem.activityId] as Flowchart;
|
||||
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.activityType == activity.typeName);
|
||||
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.type == activity.type);
|
||||
|
||||
if (activityDescriptor.isContainer)
|
||||
return activity;
|
||||
|
||||
const portProvider = this.portProviderRegistry.get(activity.typeName);
|
||||
const portProvider = this.portProviderRegistry.get(activity.type);
|
||||
return portProvider.resolvePort(currentItem.portName, {activity, activityDescriptor}) as Flowchart;
|
||||
}
|
||||
|
||||
|
|
@ -643,7 +646,7 @@ export class FlowchartComponent implements ContainerActivityComponent {
|
|||
const item = e.detail;
|
||||
const activityId = item.activityId;
|
||||
let activity = this.activityLookup[activityId];
|
||||
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.activityType == activity.typeName);
|
||||
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.type == activity.type);
|
||||
const path = this.currentPath;
|
||||
const index = path.indexOf(item);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export class NodeFactory {
|
|||
}
|
||||
|
||||
public createNode(activityDescriptor: ActivityDescriptor, activity: Activity, x: number, y: number): Node.Metadata {
|
||||
const handler = this.handlerRegistry.createHandler(activityDescriptor.activityType);
|
||||
const handler = this.handlerRegistry.createHandler(activityDescriptor.type);
|
||||
return handler.createDesignerNode({activityDescriptor, activity, x, y});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ export class ActivityNodeShape extends Shape.HTML {
|
|||
createHtml() {
|
||||
const activityDescriptor = this.activityDescriptor as ActivityDescriptor;
|
||||
const activity = this.activity as Activity;
|
||||
const activityType = activityDescriptor.activityType;
|
||||
const activityType = activityDescriptor.type;
|
||||
const driverRegistry = Container.get(ActivityDriverRegistry);
|
||||
const driver = driverRegistry.createDriver(activityType);
|
||||
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ export class WorkflowNavigator {
|
|||
private renderPathItem = (item: FlowchartNavigationItem, index: number, nodes: Array<ActivityNode>) => {
|
||||
const activityId = item.activityId;
|
||||
const activity = nodes.find(x => x.activity.id == activityId).activity;
|
||||
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.activityType == activity.typeName);
|
||||
const icon = this.iconRegistry.get(activity.typeName)();
|
||||
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.type == activity.type);
|
||||
const icon = this.iconRegistry.get(activity.type)();
|
||||
const listElements = [];
|
||||
const isLastItem = index == this.items.length - 1;
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ export class WorkflowNavigator {
|
|||
let port: Port = null;
|
||||
|
||||
if (!!item.portName) {
|
||||
const portProvider = this.portProviderRegistry.get(activity.typeName);
|
||||
const portProvider = this.portProviderRegistry.get(activity.type);
|
||||
const ports = portProvider.getOutboundPorts({activity, activityDescriptor});
|
||||
|
||||
if (ports.length > 1)
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ export class ActivityPropertiesEditor {
|
|||
const activity = this.activity;
|
||||
const activityId = activity.id;
|
||||
const activityDescriptor = this.findActivityDescriptor();
|
||||
const title = activityDescriptor?.displayName ?? activityDescriptor?.activityType ?? 'Unknown Activity';
|
||||
const title = activityDescriptor?.displayName ?? activityDescriptor?.type ?? 'Unknown Activity';
|
||||
const driverRegistry = this.inputDriverRegistry;
|
||||
|
||||
const onInputChanged = (inputDescriptor: InputDescriptor) => this.activityUpdated.emit({
|
||||
|
|
@ -156,7 +156,7 @@ export class ActivityPropertiesEditor {
|
|||
);
|
||||
}
|
||||
|
||||
private findActivityDescriptor = (): ActivityDescriptor => !!this.activity ? descriptorsStore.activityDescriptors.find(x => x.activityType == this.activity.typeName) : null;
|
||||
private findActivityDescriptor = (): ActivityDescriptor => !!this.activity ? descriptorsStore.activityDescriptors.find(x => x.type == this.activity.type) : null;
|
||||
private onSelectedTabIndexChanged = (e: CustomEvent<TabChangedArgs>) => this.selectedTabIndex = e.detail.selectedTabIndex
|
||||
|
||||
private onActivityIdChanged = (e: any) => {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export class ToolboxActivities {
|
|||
const activityDriverRegistry = Container.get(ActivityDriverRegistry);
|
||||
|
||||
for (const activityDescriptor of browsableDescriptors) {
|
||||
const activityType = activityDescriptor.activityType;
|
||||
const activityType = activityDescriptor.type;
|
||||
const driver = activityDriverRegistry.createDriver(activityType);
|
||||
const html = driver.display({displayType: 'picker', activityDescriptor: activityDescriptor});
|
||||
|
||||
|
|
@ -86,14 +86,14 @@ export class ToolboxActivities {
|
|||
render() {
|
||||
|
||||
const model = this.buildModel();
|
||||
const categoryModels = model.categories;
|
||||
const categoryModels:Array<ActivityCategoryModel> = model.categories;
|
||||
const renderedActivities = model.activities;
|
||||
|
||||
return <nav class="flex-1 px-2 space-y-1 font-sans text-sm text-gray-600">
|
||||
{categoryModels.map(categoryModel => {
|
||||
|
||||
const category = categoryModel.category;
|
||||
const activityDescriptors = categoryModel.activities;
|
||||
const activityDescriptors: Array<ActivityDescriptor> = categoryModel.activities;
|
||||
const categoryButtonClass = categoryModel.expanded ? 'rotate-90' : '';
|
||||
const categoryContentClass = categoryModel.expanded ? '' : 'hidden';
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ export class ToolboxActivities {
|
|||
<div class={`space-y-0.5 ${categoryContentClass}`}>
|
||||
|
||||
{activityDescriptors.map(activityDescriptor => {
|
||||
const activityHtml = renderedActivities.get(activityDescriptor.activityType);
|
||||
const activityHtml = renderedActivities.get(activityDescriptor.type);
|
||||
return (
|
||||
<div class="w-full flex items-center pl-10 pr-2 py-2">
|
||||
<div class="relative cursor-move" onDragStart={e => ToolboxActivities.onActivityStartDrag(e, activityDescriptor)}>
|
||||
|
|
|
|||
|
|
@ -60,8 +60,9 @@ export class WorkflowDefinitionsPlugin implements Plugin {
|
|||
const flowchartDescriptor = this.getFlowchartDescriptor();
|
||||
const newName = await this.generateUniqueActivityName(flowchartDescriptor);
|
||||
|
||||
const flowchart = {
|
||||
typeName: flowchartDescriptor.activityType,
|
||||
const flowchart: Flowchart = {
|
||||
type: flowchartDescriptor.type,
|
||||
version: 1,
|
||||
activities: [],
|
||||
connections: [],
|
||||
id: newName,
|
||||
|
|
@ -85,7 +86,7 @@ export class WorkflowDefinitionsPlugin implements Plugin {
|
|||
};
|
||||
|
||||
private getFlowchartDescriptor = () => this.getActivityDescriptor(FlowchartTypeName);
|
||||
private getActivityDescriptor = (typeName: string): ActivityDescriptor => descriptorsStore.activityDescriptors.find(x => x.activityType == typeName)
|
||||
private getActivityDescriptor = (typeName: string): ActivityDescriptor => descriptorsStore.activityDescriptors.find(x => x.type == typeName)
|
||||
private generateUniqueActivityName = async (activityDescriptor: ActivityDescriptor): Promise<string> => await generateUniqueActivityName([], activityDescriptor);
|
||||
|
||||
private saveWorkflowDefinition = async (definition: WorkflowDefinition, publish: boolean): Promise<WorkflowDefinition> => {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export class ActivityProperties {
|
|||
);
|
||||
}
|
||||
|
||||
private findActivityDescriptor = (): ActivityDescriptor => !!this.activity ? descriptorsStore.activityDescriptors.find(x => x.activityType == this.activity.typeName) : null;
|
||||
private findActivityDescriptor = (): ActivityDescriptor => !!this.activity ? descriptorsStore.activityDescriptors.find(x => x.type == this.activity.type) : null;
|
||||
private onSelectedTabIndexChanged = (e: CustomEvent<TabChangedArgs>) => this.selectedTabIndex = e.detail.selectedTabIndex
|
||||
|
||||
private renderPropertiesTab = () => {
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ export class Journal {
|
|||
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 icon = iconRegistry.get(activity.type)({size: ActivityIconSize.Small});
|
||||
const expanded = !!expandedBlocks.find(x => x == block);
|
||||
|
||||
const toggleIcon = expanded
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ export interface ActivityNameFormatterContext {
|
|||
@Service()
|
||||
export class ActivityNameFormatter {
|
||||
|
||||
public static readonly DefaultStrategy: ActivityNameStrategy = context => `${stripActivityNameSpace(context.activityDescriptor.activityType)}${context.count}`;
|
||||
public static readonly UnderscoreStrategy: ActivityNameStrategy = context => `${stripActivityNameSpace(context.activityDescriptor.activityType)}_${context.count}`;
|
||||
public static readonly DefaultStrategy: ActivityNameStrategy = context => `${stripActivityNameSpace(context.activityDescriptor.type)}${context.count}`;
|
||||
public static readonly UnderscoreStrategy: ActivityNameStrategy = context => `${stripActivityNameSpace(context.activityDescriptor.type)}_${context.count}`;
|
||||
public static readonly PascalCaseStrategy: ActivityNameStrategy = context => startCase(camelCase(ActivityNameFormatter.DefaultStrategy(context))).replace(/ /g, '');
|
||||
public static readonly CamelCaseStrategy: ActivityNameStrategy = context => camelCase(ActivityNameFormatter.DefaultStrategy(context));
|
||||
public static readonly SnakeCaseStrategy: ActivityNameStrategy = context => snakeCase(ActivityNameFormatter.DefaultStrategy(context));
|
||||
|
|
|
|||
|
|
@ -90,8 +90,8 @@ function walkRecursive(node: ActivityNode, activity: Activity, collectedActiviti
|
|||
|
||||
function getPorts(node: ActivityNode, activity: Activity, descriptors: Array<ActivityDescriptor>): Array<ActivityPort> {
|
||||
const portProviderRegistry = Container.get(PortProviderRegistry);
|
||||
const portProvider = portProviderRegistry.get(activity.typeName);
|
||||
const activityDescriptor = descriptors.find(x => x.activityType == activity.typeName);
|
||||
const portProvider = portProviderRegistry.get(activity.type);
|
||||
const activityDescriptor = descriptors.find(x => x.type == activity.type);
|
||||
const ports = portProvider.getOutboundPorts({activity, activityDescriptor});
|
||||
let activityPorts: Array<ActivityPort> = [];
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import {Container} from "typedi";
|
|||
const activityNameFormatter = Container.get(ActivityNameFormatter);
|
||||
|
||||
export async function generateUniqueActivityName(activityNodes: Array<ActivityNode>, activityDescriptor: ActivityDescriptor): Promise<string> {
|
||||
const activityType = activityDescriptor.activityType;
|
||||
const activityCount = activityNodes.filter(x => x.activity.typeName == activityType).length;
|
||||
const activityType = activityDescriptor.type;
|
||||
const activityCount = activityNodes.filter(x => x.activity.type == activityType).length;
|
||||
let counter = activityCount + 1;
|
||||
let newName = activityNameFormatter.format({activityDescriptor, count: counter, activityNodes});
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|||
namespace Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite.Migrations
|
||||
{
|
||||
[DbContext(typeof(ActivityDefinitionsDbContext))]
|
||||
[Migration("20220721084744_Initial")]
|
||||
[Migration("20220811151921_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
|
|
@ -49,7 +49,7 @@ namespace Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite.Migrations
|
|||
b.Property<bool>("IsPublished")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("TypeName")
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
|
|
@ -64,8 +64,8 @@ namespace Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite.Migrations
|
|||
b.HasIndex("IsPublished")
|
||||
.HasDatabaseName("IX_ActivityDefinition_IsPublished");
|
||||
|
||||
b.HasIndex("TypeName")
|
||||
.HasDatabaseName("IX_ActivityDefinition_TypeName");
|
||||
b.HasIndex("Type")
|
||||
.HasDatabaseName("IX_ActivityDefinition_Type");
|
||||
|
||||
b.HasIndex("Version")
|
||||
.HasDatabaseName("IX_ActivityDefinition_Version");
|
||||
|
|
@ -14,7 +14,7 @@ namespace Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite.Migrations
|
|||
{
|
||||
Id = table.Column<string>(type: "TEXT", nullable: false),
|
||||
DefinitionId = table.Column<string>(type: "TEXT", nullable: false),
|
||||
TypeName = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Type = table.Column<string>(type: "TEXT", nullable: false),
|
||||
DisplayName = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Description = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Category = table.Column<string>(type: "TEXT", nullable: true),
|
||||
|
|
@ -46,9 +46,9 @@ namespace Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite.Migrations
|
|||
column: "IsPublished");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ActivityDefinition_TypeName",
|
||||
name: "IX_ActivityDefinition_Type",
|
||||
table: "ActivityDefinitions",
|
||||
column: "TypeName");
|
||||
column: "Type");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ActivityDefinition_Version",
|
||||
|
|
@ -47,7 +47,7 @@ namespace Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite.Migrations
|
|||
b.Property<bool>("IsPublished")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("TypeName")
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
|
|
@ -62,8 +62,8 @@ namespace Elsa.ActivityDefinitions.EntityFrameworkCore.Sqlite.Migrations
|
|||
b.HasIndex("IsPublished")
|
||||
.HasDatabaseName("IX_ActivityDefinition_IsPublished");
|
||||
|
||||
b.HasIndex("TypeName")
|
||||
.HasDatabaseName("IX_ActivityDefinition_TypeName");
|
||||
b.HasIndex("Type")
|
||||
.HasDatabaseName("IX_ActivityDefinition_Type");
|
||||
|
||||
b.HasIndex("Version")
|
||||
.HasDatabaseName("IX_ActivityDefinition_Version");
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ public class ActivityDefinitionConfiguration : IEntityTypeConfiguration<Activity
|
|||
|
||||
builder.HasIndex(x => new {x.DefinitionId, x.Version}).HasDatabaseName($"IX_{nameof(ActivityDefinition)}_{nameof(ActivityDefinition.DefinitionId)}_{nameof(ActivityDefinition.Version)}").IsUnique();
|
||||
builder.HasIndex(x => x.Version).HasDatabaseName($"IX_{nameof(ActivityDefinition)}_{nameof(ActivityDefinition.Version)}");
|
||||
builder.HasIndex(x => x.TypeName).HasDatabaseName($"IX_{nameof(ActivityDefinition)}_{nameof(ActivityDefinition.TypeName)}");
|
||||
builder.HasIndex(x => x.Type).HasDatabaseName($"IX_{nameof(ActivityDefinition)}_{nameof(ActivityDefinition.Type)}");
|
||||
builder.HasIndex(x => x.IsLatest).HasDatabaseName($"IX_{nameof(ActivityDefinition)}_{nameof(ActivityDefinition.IsLatest)}");
|
||||
builder.HasIndex(x => x.IsPublished).HasDatabaseName($"IX_{nameof(ActivityDefinition)}_{nameof(ActivityDefinition.IsPublished)}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ public class EFCoreActivityDefinitionStore : IActivityDefinitionStore
|
|||
|
||||
if (versionOptions != null) query = query.WithVersion(versionOptions.Value);
|
||||
|
||||
query = query.OrderBy(x => x.DisplayName).ThenBy(x => x.TypeName);
|
||||
query = query.OrderBy(x => x.DisplayName).ThenBy(x => x.Type);
|
||||
|
||||
return await query.PaginateAsync(pageArgs);
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ public class EFCoreActivityDefinitionStore : IActivityDefinitionStore
|
|||
|
||||
if (versionOptions != null) query = query.WithVersion(versionOptions.Value);
|
||||
|
||||
query = query.OrderBy(x => x.DisplayName).ThenBy(x => x.TypeName);
|
||||
query = query.OrderBy(x => x.DisplayName).ThenBy(x => x.Type);
|
||||
|
||||
return await query.PaginateAsync(x => ActivityDefinitionSummary.FromDefinition(x), pageArgs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ public class Get : ProtectedEndpoint<Request, ActivityDefinitionModel>
|
|||
var model = new ActivityDefinitionModel(
|
||||
definition.Id,
|
||||
definition.DefinitionId,
|
||||
definition.TypeName,
|
||||
definition.Type,
|
||||
definition.DisplayName,
|
||||
definition.Category,
|
||||
definition.Description,
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public class Post : ProtectedEndpoint<Request, Response>
|
|||
var variables = _variableDefinitionMapper.Map(request.Variables).ToList();
|
||||
|
||||
draft!.Data = data;
|
||||
draft.TypeName = request.TypeName;
|
||||
draft.Type = request.Type;
|
||||
draft.DisplayName = request.DisplayName?.Trim();
|
||||
draft.Category = request.Category?.Trim();
|
||||
draft.Description = request.Description?.Trim();
|
||||
|
|
@ -70,7 +70,7 @@ public class Post : ProtectedEndpoint<Request, Response>
|
|||
var response = new Response(
|
||||
draft.Id,
|
||||
draft.DefinitionId,
|
||||
draft.TypeName,
|
||||
draft.Type,
|
||||
draft.DisplayName,
|
||||
draft.Category,
|
||||
draft.Description,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace Elsa.ActivityDefinitions.Endpoints.ActivityDefinitions.Post;
|
|||
public class Request
|
||||
{
|
||||
public string DefinitionId { get; set; } = default!;
|
||||
public string TypeName { get; set; } = default!;
|
||||
public string Type { get; set; } = default!;
|
||||
public string? DisplayName { get; set; }
|
||||
public string? Category { get; set; }
|
||||
public string? Description { get; set; }
|
||||
|
|
@ -26,7 +26,7 @@ public class Response
|
|||
public Response(
|
||||
string id,
|
||||
string definitionId,
|
||||
string typeName,
|
||||
string type,
|
||||
string? displayName,
|
||||
string? category,
|
||||
string? description,
|
||||
|
|
@ -41,7 +41,7 @@ public class Response
|
|||
{
|
||||
Id = id;
|
||||
DefinitionId = definitionId;
|
||||
TypeName = typeName;
|
||||
Type = type;
|
||||
DisplayName = displayName;
|
||||
Category = category;
|
||||
Description = description;
|
||||
|
|
@ -57,7 +57,7 @@ public class Response
|
|||
|
||||
public string Id { get; set; } = default!;
|
||||
public string DefinitionId { get; set; } = default!;
|
||||
public string TypeName { get; set; } = default!;
|
||||
public string Type { get; set; } = default!;
|
||||
public string? DisplayName { get; set; }
|
||||
public string? Category { get; set; }
|
||||
public string? Description { get; set; }
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace Elsa.ActivityDefinitions.Entities;
|
|||
public class ActivityDefinition : VersionedEntity
|
||||
{
|
||||
public string DefinitionId { get; set; } = default!;
|
||||
public string TypeName { get; set; } = default!;
|
||||
public string Type { get; set; } = default!;
|
||||
public string? DisplayName { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? Category { get; set; }
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public class ActivityDefinitionActivityProvider : IActivityProvider
|
|||
|
||||
public async ValueTask<IEnumerable<ActivityDescriptor>> GetDescriptorsAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var definitions = await _store.ListAsync(VersionOptions.Published, cancellationToken).ToList();
|
||||
var definitions = await _store.ListAsync(VersionOptions.All, cancellationToken).ToList();
|
||||
var descriptors = CreateDescriptors(definitions).ToList();
|
||||
return descriptors;
|
||||
}
|
||||
|
|
@ -35,20 +35,20 @@ public class ActivityDefinitionActivityProvider : IActivityProvider
|
|||
|
||||
private ActivityDescriptor CreateDescriptor(ActivityDefinition definition)
|
||||
{
|
||||
var typeName = definition.TypeName!;
|
||||
|
||||
return new()
|
||||
{
|
||||
ActivityType = typeName,
|
||||
DisplayName = definition.DisplayName.WithDefault(typeName),
|
||||
Type = definition.Type,
|
||||
Version = definition.Version,
|
||||
DisplayName = definition.DisplayName.WithDefault(definition.Type),
|
||||
Description = definition.Description,
|
||||
Category = definition.Category.WithDefault("Custom"),
|
||||
Kind = ActivityKind.Action,
|
||||
IsBrowsable = true,
|
||||
IsBrowsable = definition.IsPublished,
|
||||
Constructor = context =>
|
||||
{
|
||||
var activity = (ActivityDefinitionActivity)_activityFactory.Create(typeof(ActivityDefinitionActivity), context);
|
||||
activity.TypeName = typeName;
|
||||
activity.Type = definition.Type;
|
||||
activity.Version = definition.Version;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(activity.DefinitionId))
|
||||
activity.DefinitionId = definition.DefinitionId;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ public class ActivityDefinitionModel
|
|||
public ActivityDefinitionModel(
|
||||
string id,
|
||||
string definitionId,
|
||||
string typeName,
|
||||
string type,
|
||||
string? displayName,
|
||||
string? category,
|
||||
string? description,
|
||||
|
|
@ -27,7 +27,7 @@ public class ActivityDefinitionModel
|
|||
{
|
||||
Id = id;
|
||||
DefinitionId = definitionId;
|
||||
TypeName = typeName;
|
||||
Type = type;
|
||||
DisplayName = displayName;
|
||||
Category = category;
|
||||
Description = description;
|
||||
|
|
@ -43,7 +43,7 @@ public class ActivityDefinitionModel
|
|||
|
||||
public string Id { get; init; } = default!;
|
||||
public string DefinitionId { get; init; } = default!;
|
||||
public string TypeName { get; init; } = default!;
|
||||
public string Type { get; init; } = default!;
|
||||
public string? DisplayName { get; init; }
|
||||
public string? Category { get; init; }
|
||||
public string? Description { get; init; }
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ using Elsa.ActivityDefinitions.Entities;
|
|||
|
||||
namespace Elsa.ActivityDefinitions.Models;
|
||||
|
||||
public record ActivityDefinitionSummary(string Id, string DefinitionId, string TypeName, string? DisplayName, string? Description, int? Version, bool IsLatest, bool IsPublished, DateTimeOffset CreatedAt)
|
||||
public record ActivityDefinitionSummary(string Id, string DefinitionId, string Type, string? DisplayName, string? Description, int? Version, bool IsLatest, bool IsPublished, DateTimeOffset CreatedAt)
|
||||
{
|
||||
public static ActivityDefinitionSummary FromDefinition(ActivityDefinition definition) => new(
|
||||
definition.Id,
|
||||
definition.DefinitionId,
|
||||
definition.TypeName,
|
||||
definition.Type,
|
||||
definition.DisplayName,
|
||||
definition.Description,
|
||||
definition.Version,
|
||||
|
|
|
|||
|
|
@ -17,16 +17,16 @@ public class JobAttribute : Attribute
|
|||
Category = @namespace;
|
||||
}
|
||||
|
||||
public JobAttribute(string @namespace, string? typeName, string? description = default, string? category = default)
|
||||
public JobAttribute(string @namespace, string? activityType, string? description = default, string? category = default)
|
||||
{
|
||||
Namespace = @namespace;
|
||||
TypeName = typeName;
|
||||
ActivityType = activityType;
|
||||
Description = description;
|
||||
Category = category;
|
||||
}
|
||||
|
||||
public string? Namespace { get; set;}
|
||||
public string? TypeName { get; set;}
|
||||
public string? ActivityType { get; set;}
|
||||
public string? Description { get; set;}
|
||||
public string? DisplayName { get; set; }
|
||||
public string? Category { get; set;}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ public static class JobTypeNameHelper
|
|||
public static string GenerateTypeName(Type type, string? ns)
|
||||
{
|
||||
var activityAttr = type.GetCustomAttribute<JobAttribute>();
|
||||
var typeName = activityAttr?.TypeName ?? type.Name;
|
||||
var typeName = activityAttr?.ActivityType ?? type.Name;
|
||||
return ns != null ? $"{ns}.{typeName}" : typeName;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public class JobActivityProvider : IActivityProvider
|
|||
{
|
||||
var jobAttr = jobType.GetCustomAttribute<JobAttribute>();
|
||||
var ns = jobAttr?.Namespace ?? JobTypeNameHelper.GenerateNamespace(jobType);
|
||||
var typeName = jobAttr?.TypeName ?? jobType.Name;
|
||||
var typeName = jobAttr?.ActivityType ?? jobType.Name;
|
||||
var fullTypeName = JobTypeNameHelper.GenerateTypeName(jobType);
|
||||
var displayNameAttr = jobType.GetCustomAttribute<DisplayNameAttribute>();
|
||||
var displayName = displayNameAttr?.DisplayName ?? jobAttr?.DisplayName ?? typeName.Humanize(LetterCasing.Title);
|
||||
|
|
@ -51,7 +51,8 @@ public class JobActivityProvider : IActivityProvider
|
|||
|
||||
return new()
|
||||
{
|
||||
ActivityType = fullTypeName,
|
||||
Type = fullTypeName,
|
||||
Version = 1,
|
||||
DisplayName = displayName,
|
||||
Description = description,
|
||||
Category = category,
|
||||
|
|
@ -60,7 +61,7 @@ public class JobActivityProvider : IActivityProvider
|
|||
Constructor = context =>
|
||||
{
|
||||
var activity = _activityFactory.Create<JobActivity>(context);
|
||||
activity.TypeName = fullTypeName;
|
||||
activity.Type = fullTypeName;
|
||||
activity.JobType = jobType;
|
||||
|
||||
return activity;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Elsa.Workflows.Core.Activities.Flowchart.Models;
|
||||
using Elsa.Workflows.Core.Helpers;
|
||||
using Elsa.Workflows.Core.Services;
|
||||
|
||||
namespace Elsa.Workflows.Core.Activities.Flowchart.Serialization;
|
||||
|
|
@ -65,7 +66,8 @@ public class FlowchartJsonConverter : JsonConverter<Activities.Flowchart>
|
|||
|
||||
var model = new
|
||||
{
|
||||
value.TypeName,
|
||||
Type = value.Type,
|
||||
Version = value.Version,
|
||||
value.Id,
|
||||
value.Metadata,
|
||||
ApplicationProperties = applicationProperties,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,12 @@ public class NotFoundActivity : Activity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// The type name of the missing activity.
|
||||
/// The type name of the missing activity type.
|
||||
/// </summary>
|
||||
public string MissingTypeName { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The version of the missing activity type.
|
||||
/// </summary>
|
||||
public int MissingTypeVersion { get; set; }
|
||||
}
|
||||
|
|
@ -17,17 +17,19 @@ public class ActivityAttribute : Attribute
|
|||
Category = @namespace;
|
||||
}
|
||||
|
||||
public ActivityAttribute(string @namespace, string? typeName, string? description = default, string? category = default)
|
||||
public ActivityAttribute(string @namespace, string? type, int version = 1, string? description = default, string? category = default)
|
||||
{
|
||||
Namespace = @namespace;
|
||||
TypeName = typeName;
|
||||
Type = type;
|
||||
Version = version;
|
||||
Description = description;
|
||||
Category = category;
|
||||
}
|
||||
|
||||
public string? Namespace { get; set;}
|
||||
public string? TypeName { get; set;}
|
||||
public string? Description { get; set;}
|
||||
public string? Namespace { get; set; }
|
||||
public string? Type { get; set; }
|
||||
public int Version { get; set; } = 1;
|
||||
public string? Description { get; set; }
|
||||
public string? DisplayName { get; set; }
|
||||
public string? Category { get; set;}
|
||||
public string? Category { get; set; }
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ public static class ActivityExecutionContextExtensions
|
|||
var parentActivityInstanceId = context.ParentActivityExecutionContext?.Id;
|
||||
var workflowExecutionContext = context.WorkflowExecutionContext;
|
||||
var now = context.GetRequiredService<ISystemClock>().UtcNow;
|
||||
var logEntry = new WorkflowExecutionLogEntry(activityInstanceId, parentActivityInstanceId, activity.Id, activity.TypeName, now, eventName, message, source, payload);
|
||||
var logEntry = new WorkflowExecutionLogEntry(activityInstanceId, parentActivityInstanceId, activity.Id, activity.Type, now, eventName, message, source, payload);
|
||||
workflowExecutionContext.ExecutionLog.Add(logEntry);
|
||||
return logEntry;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ public static class ActivityTypeNameHelper
|
|||
public static string GenerateTypeName(Type type, string? ns)
|
||||
{
|
||||
var activityAttr = type.GetCustomAttribute<ActivityAttribute>();
|
||||
var typeName = activityAttr?.TypeName ?? type.Name;
|
||||
var typeName = activityAttr?.Type ?? type.Name;
|
||||
return ns != null ? $"{ns}.{typeName}" : typeName;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ public class IdentityGraphService : IIdentityGraphService
|
|||
|
||||
while (true)
|
||||
{
|
||||
var fullTypeName = activityNode.Activity.TypeName;
|
||||
var fullTypeName = activityNode.Activity.Type;
|
||||
var shortTypeName = fullTypeName.Split('.').Last();
|
||||
var index = GetNextIndexFor(shortTypeName, identityCounters);
|
||||
var name = $"{shortTypeName}{index + 1}";
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ public abstract class Activity : ActivityBase
|
|||
|
||||
protected Activity(string activityType) : this()
|
||||
{
|
||||
TypeName = activityType;
|
||||
Type = activityType;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,21 +8,24 @@ namespace Elsa.Workflows.Core.Models;
|
|||
public abstract class ActivityBase : IActivity, ISignalHandler
|
||||
{
|
||||
private readonly ICollection<SignalHandlerRegistration> _signalHandlers = new List<SignalHandlerRegistration>();
|
||||
|
||||
|
||||
protected ActivityBase()
|
||||
{
|
||||
TypeName = ActivityTypeNameHelper.GenerateTypeName(GetType());
|
||||
Type = ActivityTypeNameHelper.GenerateTypeName(GetType());
|
||||
Version = 1;
|
||||
Behaviors.Add<ExecutionLoggingBehavior>(this);
|
||||
Behaviors.Add<ScheduledChildCallbackBehavior>(this);
|
||||
}
|
||||
|
||||
protected ActivityBase(string activityType) : this()
|
||||
protected ActivityBase(string activityType, int version = 1) : this()
|
||||
{
|
||||
TypeName = activityType;
|
||||
Type = activityType;
|
||||
Version = version;
|
||||
}
|
||||
|
||||
public string Id { get; set; } = default!;
|
||||
public string TypeName { get; set; }
|
||||
public string Type { get; set; }
|
||||
public int Version { get; set; }
|
||||
public bool CanStartWorkflow { get; set; }
|
||||
public IDictionary<string, object> ApplicationProperties { get; set; } = new Dictionary<string, object>();
|
||||
public IDictionary<string, object> Metadata { get; set; } = new Dictionary<string, object>();
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ namespace Elsa.Workflows.Core.Models;
|
|||
/// </summary>
|
||||
public class ActivityDescriptor
|
||||
{
|
||||
public string ActivityType { get; init; } = default!;
|
||||
public string Type { get; init; } = default!;
|
||||
public int Version { get; init; }
|
||||
public string Category { get; init; } = default!;
|
||||
public string? DisplayName { get; init; }
|
||||
public string? Description { get; init; }
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ public class ActivityExecutionContext
|
|||
|
||||
var bookmark = new Bookmark(
|
||||
identityGenerator.GenerateId(),
|
||||
Activity.TypeName,
|
||||
Activity.Type,
|
||||
hash,
|
||||
payloadJson,
|
||||
Activity.Id,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,12 @@ public interface IActivity
|
|||
/// <summary>
|
||||
/// The logical type name of the activity.
|
||||
/// </summary>
|
||||
string TypeName { get; set; }
|
||||
string Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The version of the activity type.
|
||||
/// </summary>
|
||||
int Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A value indicating whether this activity can start instances of the workflow it is a part of.
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ public class ActivityDescriber : IActivityDescriber
|
|||
{
|
||||
var activityAttr = activityType.GetCustomAttribute<ActivityAttribute>();
|
||||
var ns = activityAttr?.Namespace ?? ActivityTypeNameHelper.GenerateNamespace(activityType);
|
||||
var typeName = activityAttr?.TypeName ?? activityType.Name;
|
||||
var typeName = activityAttr?.Type ?? activityType.Name;
|
||||
var typeVersion = activityAttr?.Version ?? 1;
|
||||
var fullTypeName = ActivityTypeNameHelper.GenerateTypeName(activityType);
|
||||
var displayNameAttr = activityType.GetCustomAttribute<DisplayNameAttribute>();
|
||||
var displayName = displayNameAttr?.DisplayName ?? activityAttr?.DisplayName ?? typeName.Humanize(LetterCasing.Title);
|
||||
|
|
@ -71,7 +72,8 @@ public class ActivityDescriber : IActivityDescriber
|
|||
{
|
||||
Category = category,
|
||||
Description = description,
|
||||
ActivityType = fullTypeName,
|
||||
Type = fullTypeName,
|
||||
Version = typeVersion,
|
||||
DisplayName = displayName,
|
||||
Kind = isTrigger ? ActivityKind.Trigger : ActivityKind.Action,
|
||||
Ports = allPorts.ToList(),
|
||||
|
|
@ -82,7 +84,7 @@ public class ActivityDescriber : IActivityDescriber
|
|||
Constructor = context =>
|
||||
{
|
||||
var activity = _activityFactory.Create(activityType, context);
|
||||
activity.TypeName = fullTypeName;
|
||||
activity.Type = fullTypeName;
|
||||
return activity;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace Elsa.Workflows.Management.Implementations;
|
|||
public class ActivityRegistry : IActivityRegistry
|
||||
{
|
||||
private readonly IDictionary<Type, ICollection<ActivityDescriptor>> _providedActivityDescriptors = new Dictionary<Type, ICollection<ActivityDescriptor>>();
|
||||
private readonly IDictionary<string, ActivityDescriptor> _activityDescriptors = new Dictionary<string, ActivityDescriptor>();
|
||||
private readonly IDictionary<(string Type, int Version), ActivityDescriptor> _activityDescriptors = new Dictionary<(string Type, int Version), ActivityDescriptor>();
|
||||
|
||||
public void Add(Type providerType, ActivityDescriptor descriptor) => Add(descriptor, GetOrCreateDescriptors(providerType));
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ public class ActivityRegistry : IActivityRegistry
|
|||
var descriptors = ListByProvider(providerType).ToList();
|
||||
|
||||
foreach (var descriptor in descriptors)
|
||||
_activityDescriptors.Remove(descriptor.ActivityType);
|
||||
_activityDescriptors.Remove((descriptor.Type, descriptor.Version));
|
||||
|
||||
_providedActivityDescriptors.Remove(providerType);
|
||||
}
|
||||
|
|
@ -37,11 +37,11 @@ public class ActivityRegistry : IActivityRegistry
|
|||
public IEnumerable<ActivityDescriptor> ListAll() => _activityDescriptors.Values;
|
||||
public IEnumerable<ActivityDescriptor> ListByProvider(Type providerType) => _providedActivityDescriptors.TryGetValue(providerType, out var descriptors) ? descriptors : ArraySegment<ActivityDescriptor>.Empty;
|
||||
public ActivityDescriptor? Find(Func<ActivityDescriptor, bool> predicate) => _activityDescriptors.Values.FirstOrDefault(predicate);
|
||||
public ActivityDescriptor? Find(string activityType) => _activityDescriptors.TryGetValue(activityType, out var descriptor) ? descriptor : null;
|
||||
public ActivityDescriptor? Find(string type, int version) => _activityDescriptors.TryGetValue((type, version), out var descriptor) ? descriptor : null;
|
||||
|
||||
private void Add(ActivityDescriptor descriptor, ICollection<ActivityDescriptor> target)
|
||||
{
|
||||
_activityDescriptors.Add(descriptor.ActivityType, descriptor);
|
||||
_activityDescriptors.Add((descriptor.Type, descriptor.Version), descriptor);
|
||||
target.Add(descriptor);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,11 +29,15 @@ public class ActivityJsonConverter : JsonConverter<IActivity>
|
|||
if (!JsonDocument.TryParseValue(ref reader, out var doc))
|
||||
throw new JsonException("Failed to parse JsonDocument");
|
||||
|
||||
if (!doc.RootElement.TryGetProperty("typeName", out var activityTypeNameElement))
|
||||
if (!doc.RootElement.TryGetProperty("type", out var activityTypeNameElement))
|
||||
throw new JsonException("Failed to extract activity type property");
|
||||
|
||||
if (!doc.RootElement.TryGetProperty("version", out var activityTypeVersionElement))
|
||||
throw new JsonException("Failed to extract activity type version property");
|
||||
|
||||
var activityTypeName = activityTypeNameElement.GetString()!;
|
||||
var activityDescriptor = _activityRegistry.Find(activityTypeName);
|
||||
var activityTypeVersion = activityTypeVersionElement.GetInt32();
|
||||
var activityDescriptor = _activityRegistry.Find(activityTypeName, activityTypeVersion);
|
||||
|
||||
var newOptions = new JsonSerializerOptions(options);
|
||||
newOptions.Converters.Add(new InputJsonConverterFactory(_serviceProvider));
|
||||
|
|
@ -44,8 +48,9 @@ public class ActivityJsonConverter : JsonConverter<IActivity>
|
|||
var notFoundContext = new ActivityConstructorContext(doc.RootElement, newOptions);
|
||||
var notFoundActivity = (NotFoundActivity)_activityFactory.Create(typeof(NotFoundActivity), notFoundContext);
|
||||
|
||||
notFoundActivity.TypeName = ActivityTypeNameHelper.GenerateTypeName<NotFoundActivity>();
|
||||
notFoundActivity.Type = ActivityTypeNameHelper.GenerateTypeName<NotFoundActivity>();
|
||||
notFoundActivity.MissingTypeName = activityTypeName;
|
||||
notFoundActivity.MissingTypeVersion = activityTypeVersion;
|
||||
return notFoundActivity;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,5 +11,5 @@ public interface IActivityRegistry
|
|||
IEnumerable<ActivityDescriptor> ListAll();
|
||||
IEnumerable<ActivityDescriptor> ListByProvider(Type providerType);
|
||||
ActivityDescriptor? Find(Func<ActivityDescriptor, bool> predicate);
|
||||
ActivityDescriptor? Find(string activityType);
|
||||
ActivityDescriptor? Find(string type, int version);
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|||
namespace Elsa.Workflows.Persistence.EntityFrameworkCore.Sqlite.Migrations
|
||||
{
|
||||
[DbContext(typeof(WorkflowsDbContext))]
|
||||
[Migration("20220711181415_Initial")]
|
||||
[Migration("20220811151755_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
|
|
@ -123,7 +123,7 @@ public class TriggerIndexer : ITriggerIndexer
|
|||
{
|
||||
Id = _identityGenerator.GenerateId(),
|
||||
WorkflowDefinitionId = workflow.Identity.DefinitionId,
|
||||
Name = activity.TypeName
|
||||
Name = activity.Type
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ public class TriggerIndexer : ITriggerIndexer
|
|||
|
||||
var triggerIndexingContext = new TriggerIndexingContext(context, expressionExecutionContext, trigger, cancellationToken);
|
||||
var triggerData = await TryGetTriggerDataAsync(trigger, triggerIndexingContext);
|
||||
var triggerTypeName = trigger.TypeName;
|
||||
var triggerTypeName = trigger.Type;
|
||||
|
||||
var triggers = triggerData.Select(x => new WorkflowTrigger
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue