@acorex/connectivity 20.6.0-next.1 → 20.6.0-next.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/acorex-connectivity-mock.mjs +1954 -468
- package/fesm2022/acorex-connectivity-mock.mjs.map +1 -1
- package/mock/index.d.ts +306 -61
- package/package.json +2 -2
|
@@ -11,12 +11,13 @@ import { RootConfig, AXMUsersEntityService, AXMPolicyService } from '@acorex/mod
|
|
|
11
11
|
import { Router } from '@angular/router';
|
|
12
12
|
import { of, delay, filter, take, map, throttleTime } from 'rxjs';
|
|
13
13
|
import { AXMPermissionsKeys, RootConfig as RootConfig$8, AXMFormTemplateTypes } from '@acorex/modules/form-template-management';
|
|
14
|
-
import { AXMPermissionsKeys as AXMPermissionsKeys$1, RootConfig as RootConfig$
|
|
14
|
+
import { AXMPermissionsKeys as AXMPermissionsKeys$1, RootConfig as RootConfig$q } from '@acorex/modules/help-desk';
|
|
15
15
|
import { RootConfig as RootConfig$1 } from '@acorex/modules/calendar-management';
|
|
16
16
|
import { AXPFileStorageStatus, AXPFileStorageService, AXVChangeType as AXVChangeType$1, AXP_SEARCH_PROVIDER, AXPLockService, AXPVersioningService, AXPAppVersionService } from '@acorex/platform/common';
|
|
17
17
|
import Dexie from 'dexie';
|
|
18
18
|
import { AXFileService } from '@acorex/core/file';
|
|
19
19
|
import { AXPActivityProviderService, AXP_ACTIVITY_CATEGORY_PROVIDER, AXP_ACTIVITY_PROVIDER, AXPWorkflowExecutionService } from '@acorex/platform/workflow';
|
|
20
|
+
import { AXPCommandService, provideCommandSetups, provideQuerySetups, AXPQueryService, AXPRuntimeModule } from '@acorex/platform/runtime';
|
|
20
21
|
import { RootConfig as RootConfig$2 } from '@acorex/modules/contact-management';
|
|
21
22
|
import { RootConfig as RootConfig$3 } from '@acorex/modules/content-management';
|
|
22
23
|
import { AXMChatManagementService, AXMChatRealtimeService, AXMCommentManagementService, AXMCommentRealtimeService, RootConfig as RootConfig$4 } from '@acorex/modules/conversation';
|
|
@@ -25,7 +26,6 @@ import { AXPTaskBoardShortcut, AXPTaskBoardWidget, RootConfig as RootConfig$k, A
|
|
|
25
26
|
import { AXPMyNotificationDashboardWidget, RootConfig as RootConfig$e, AXMNotificationEntityServiceImpl, AXMNotificationEntityService } from '@acorex/modules/notification-management';
|
|
26
27
|
import { RootConfig as RootConfig$6, AXMMetaDataDefinitionService } from '@acorex/modules/data-management';
|
|
27
28
|
import { get, upperFirst, set } from 'lodash-es';
|
|
28
|
-
import { provideQuerySetups, AXPCommandService, provideCommandSetups, AXPQueryService, AXPRuntimeModule } from '@acorex/platform/runtime';
|
|
29
29
|
import { AXMDistributionServiceImpl, AXMDocumentService, AXMDistributionInteractionService, RootConfig as RootConfig$7, AXMFolderServiceImpl, AXMDocumentServiceImpl, AXMReviewService, AXMReviewServiceImpl, AXMDistributionInteractionServiceImpl, AXMFolderService, AXMDistributionService } from '@acorex/modules/document-management';
|
|
30
30
|
import { AXDataSource } from '@acorex/cdk/common';
|
|
31
31
|
import { AXPWidgetsCatalog } from '@acorex/platform/layout/widget-core';
|
|
@@ -44,10 +44,11 @@ import { RootConfig as RootConfig$i } from '@acorex/modules/project-management';
|
|
|
44
44
|
import * as i1 from '@acorex/components/dialog';
|
|
45
45
|
import * as i2 from '@acorex/core/translation';
|
|
46
46
|
import { RootConfig as RootConfig$l } from '@acorex/modules/training-management';
|
|
47
|
+
import { RootConfig as RootConfig$m } from '@acorex/modules/workflow-management';
|
|
47
48
|
import { AXCalendarService } from '@acorex/core/date-time';
|
|
48
|
-
import { RootConfig as RootConfig$
|
|
49
|
-
import { RootConfig as RootConfig$
|
|
50
|
-
import { RootConfig as RootConfig$
|
|
49
|
+
import { RootConfig as RootConfig$n } from '@acorex/modules/application-management';
|
|
50
|
+
import { RootConfig as RootConfig$o } from '@acorex/modules/assessment-management';
|
|
51
|
+
import { RootConfig as RootConfig$p } from '@acorex/modules/customer-management';
|
|
51
52
|
import { AXCExternalAuthorizationService } from '@acorex/connectivity/utils';
|
|
52
53
|
|
|
53
54
|
class AXCUserPassStrategyMock extends AXPAuthStrategy {
|
|
@@ -1516,7 +1517,7 @@ function computeFileDiff(prev, next, basePath, push) {
|
|
|
1516
1517
|
}
|
|
1517
1518
|
//#endregion
|
|
1518
1519
|
//#region ---- Service ----
|
|
1519
|
-
class
|
|
1520
|
+
class AXCVersioningService {
|
|
1520
1521
|
constructor() {
|
|
1521
1522
|
this.db = axVersionDB;
|
|
1522
1523
|
this.fileStorage = inject(AXPFileStorageService);
|
|
@@ -1613,10 +1614,10 @@ class VersioningService {
|
|
|
1613
1614
|
newValue: d.newValue,
|
|
1614
1615
|
}));
|
|
1615
1616
|
}
|
|
1616
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type:
|
|
1617
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type:
|
|
1617
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCVersioningService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1618
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCVersioningService, providedIn: 'root' }); }
|
|
1618
1619
|
}
|
|
1619
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type:
|
|
1620
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCVersioningService, decorators: [{
|
|
1620
1621
|
type: Injectable,
|
|
1621
1622
|
args: [{ providedIn: 'root' }]
|
|
1622
1623
|
}] });
|
|
@@ -2665,8 +2666,120 @@ class AXCActivityProvider {
|
|
|
2665
2666
|
},
|
|
2666
2667
|
});
|
|
2667
2668
|
// ============================================
|
|
2669
|
+
// SECURITY ACTIVITIES
|
|
2670
|
+
// ============================================
|
|
2671
|
+
context.registerActivity({
|
|
2672
|
+
key: 'workflow-activity:check-permission',
|
|
2673
|
+
descriptor: {
|
|
2674
|
+
type: 'workflow-activity:check-permission',
|
|
2675
|
+
displayName: 'Check Permission',
|
|
2676
|
+
description: 'Checks if current user has specific permission',
|
|
2677
|
+
category: 'Security',
|
|
2678
|
+
icon: 'fa-light fa-shield-check',
|
|
2679
|
+
executionMode: 'backend', // Backend activity - permission check on server
|
|
2680
|
+
inputs: [
|
|
2681
|
+
{
|
|
2682
|
+
name: 'permission',
|
|
2683
|
+
title: 'Permission',
|
|
2684
|
+
description: 'Permission key to check (e.g., "Users.Create")',
|
|
2685
|
+
schema: {
|
|
2686
|
+
dataType: 'string',
|
|
2687
|
+
},
|
|
2688
|
+
validations: [{ rule: 'required' }],
|
|
2689
|
+
},
|
|
2690
|
+
{
|
|
2691
|
+
name: 'userId',
|
|
2692
|
+
title: 'User ID',
|
|
2693
|
+
description: 'User ID to check (optional, defaults to current user)',
|
|
2694
|
+
schema: {
|
|
2695
|
+
dataType: 'string',
|
|
2696
|
+
},
|
|
2697
|
+
},
|
|
2698
|
+
],
|
|
2699
|
+
outputs: [
|
|
2700
|
+
{
|
|
2701
|
+
name: 'hasPermission',
|
|
2702
|
+
title: 'Has Permission',
|
|
2703
|
+
description: 'Whether user has the permission',
|
|
2704
|
+
schema: {
|
|
2705
|
+
dataType: 'boolean',
|
|
2706
|
+
},
|
|
2707
|
+
},
|
|
2708
|
+
],
|
|
2709
|
+
outcomes: ['HasPermission', 'NoPermission'],
|
|
2710
|
+
isBrowsable: true,
|
|
2711
|
+
isContainer: false,
|
|
2712
|
+
},
|
|
2713
|
+
});
|
|
2714
|
+
// ============================================
|
|
2668
2715
|
// FORM ACTIVITIES
|
|
2669
2716
|
// ============================================
|
|
2717
|
+
context.registerActivity({
|
|
2718
|
+
key: 'workflow-activity:show-dialog',
|
|
2719
|
+
descriptor: {
|
|
2720
|
+
type: 'workflow-activity:show-dialog',
|
|
2721
|
+
displayName: 'Show Dialog',
|
|
2722
|
+
description: 'Shows a dialog with form or custom content',
|
|
2723
|
+
category: 'Dialog',
|
|
2724
|
+
icon: 'fa-light fa-window',
|
|
2725
|
+
executionMode: 'frontend', // Frontend activity - shows UI dialog
|
|
2726
|
+
inputs: [
|
|
2727
|
+
{
|
|
2728
|
+
name: 'title',
|
|
2729
|
+
title: 'Title',
|
|
2730
|
+
description: 'Dialog title',
|
|
2731
|
+
schema: {
|
|
2732
|
+
dataType: 'string',
|
|
2733
|
+
},
|
|
2734
|
+
},
|
|
2735
|
+
{
|
|
2736
|
+
name: 'formDefinition',
|
|
2737
|
+
title: 'Form Definition',
|
|
2738
|
+
description: 'Form definition key or inline definition',
|
|
2739
|
+
schema: {
|
|
2740
|
+
dataType: 'string',
|
|
2741
|
+
},
|
|
2742
|
+
},
|
|
2743
|
+
{
|
|
2744
|
+
name: 'size',
|
|
2745
|
+
title: 'Size',
|
|
2746
|
+
description: 'Dialog size (sm, md, lg, xl)',
|
|
2747
|
+
schema: {
|
|
2748
|
+
dataType: 'string',
|
|
2749
|
+
},
|
|
2750
|
+
},
|
|
2751
|
+
{
|
|
2752
|
+
name: 'closeButton',
|
|
2753
|
+
title: 'Close Button',
|
|
2754
|
+
description: 'Show close button',
|
|
2755
|
+
schema: {
|
|
2756
|
+
dataType: 'boolean',
|
|
2757
|
+
},
|
|
2758
|
+
},
|
|
2759
|
+
],
|
|
2760
|
+
outputs: [
|
|
2761
|
+
{
|
|
2762
|
+
name: 'formData',
|
|
2763
|
+
title: 'Form Data',
|
|
2764
|
+
description: 'Form data submitted by user',
|
|
2765
|
+
schema: {
|
|
2766
|
+
dataType: 'object',
|
|
2767
|
+
},
|
|
2768
|
+
},
|
|
2769
|
+
{
|
|
2770
|
+
name: 'action',
|
|
2771
|
+
title: 'Action',
|
|
2772
|
+
description: 'Action taken by user',
|
|
2773
|
+
schema: {
|
|
2774
|
+
dataType: 'string',
|
|
2775
|
+
},
|
|
2776
|
+
},
|
|
2777
|
+
],
|
|
2778
|
+
outcomes: ['Submitted', 'Cancelled'],
|
|
2779
|
+
isBrowsable: true,
|
|
2780
|
+
isContainer: false,
|
|
2781
|
+
},
|
|
2782
|
+
});
|
|
2670
2783
|
context.registerActivity({
|
|
2671
2784
|
key: 'workflow-activity:show-form',
|
|
2672
2785
|
descriptor: {
|
|
@@ -2853,7 +2966,7 @@ class AXCActivityProvider {
|
|
|
2853
2966
|
isContainer: false,
|
|
2854
2967
|
},
|
|
2855
2968
|
});
|
|
2856
|
-
console.log('[AXPBuiltinActivityProvider] Registered
|
|
2969
|
+
console.log('[AXPBuiltinActivityProvider] Registered 19 built-in activities');
|
|
2857
2970
|
}
|
|
2858
2971
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCActivityProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2859
2972
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCActivityProvider }); }
|
|
@@ -2862,14 +2975,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
|
|
|
2862
2975
|
type: Injectable
|
|
2863
2976
|
}] });
|
|
2864
2977
|
|
|
2865
|
-
//#endregion
|
|
2866
2978
|
//#region ---- Dexie DB ----
|
|
2867
2979
|
/**
|
|
2868
|
-
* Dexie database for workflow
|
|
2980
|
+
* Dexie database for workflow instances.
|
|
2869
2981
|
*/
|
|
2870
2982
|
class AXCWorkflowExecutionDB extends Dexie {
|
|
2871
2983
|
constructor() {
|
|
2872
2984
|
super('ACoreXWorkflowExecutions');
|
|
2985
|
+
this.version(2).stores({
|
|
2986
|
+
instances: 'id, definitionId, status, subStatus, createdAt, updatedAt',
|
|
2987
|
+
});
|
|
2988
|
+
// Migration from v1 to v2: clear old executions table
|
|
2873
2989
|
this.version(1).stores({
|
|
2874
2990
|
executions: 'executionId, workflowId, status, currentStepId, lastUpdated',
|
|
2875
2991
|
});
|
|
@@ -2899,13 +3015,15 @@ class AXCWorkflowExecutionService {
|
|
|
2899
3015
|
constructor() {
|
|
2900
3016
|
this.db = axWorkflowExecutionDB;
|
|
2901
3017
|
this.activityProviderService = inject(AXPActivityProviderService);
|
|
3018
|
+
this.commandService = inject(AXPCommandService);
|
|
2902
3019
|
}
|
|
2903
3020
|
/**
|
|
2904
3021
|
* Start a new workflow execution.
|
|
3022
|
+
* Creates a workflow instance and stores it in IndexedDB.
|
|
2905
3023
|
*/
|
|
2906
3024
|
async startExecution(request) {
|
|
2907
|
-
const
|
|
2908
|
-
const now = new Date();
|
|
3025
|
+
const instanceId = AXPDataGenerator.uuid();
|
|
3026
|
+
const now = new Date().toISOString();
|
|
2909
3027
|
// Get workflow definition to find first step
|
|
2910
3028
|
const workflowResponse = await this.getWorkflowDefinition({
|
|
2911
3029
|
workflowId: request.workflowId
|
|
@@ -2913,129 +3031,188 @@ class AXCWorkflowExecutionService {
|
|
|
2913
3031
|
if (!workflowResponse.workflow) {
|
|
2914
3032
|
throw new Error(`Workflow definition not found: ${request.workflowId}`);
|
|
2915
3033
|
}
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
const
|
|
2919
|
-
const
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
// Convert Date to ISO string for IndexedDB storage
|
|
2930
|
-
const stateToStore = {
|
|
2931
|
-
...state,
|
|
2932
|
-
lastUpdated: state.lastUpdated.toISOString(),
|
|
2933
|
-
};
|
|
2934
|
-
await this.db.executions.add(stateToStore, state.executionId);
|
|
2935
|
-
// Return first task metadata (without full workflow definition)
|
|
2936
|
-
const pendingTask = rootActivity ? this.createTaskFromStep(rootActivity, state) : null;
|
|
2937
|
-
return {
|
|
2938
|
-
executionId,
|
|
2939
|
-
state,
|
|
2940
|
-
pendingTask
|
|
2941
|
-
};
|
|
2942
|
-
}
|
|
2943
|
-
/**
|
|
2944
|
-
* Execute a backend activity.
|
|
2945
|
-
*
|
|
2946
|
-
* In mock implementation, this simulates backend activity execution.
|
|
2947
|
-
* For real backend activities (execute-command, execute-query, set-variable),
|
|
2948
|
-
* you would typically make an HTTP call. In mock, we just update state.
|
|
2949
|
-
*/
|
|
2950
|
-
async executeBackendActivity(request) {
|
|
2951
|
-
// Get current state
|
|
2952
|
-
const state = await this.getExecutionState({
|
|
2953
|
-
executionId: request.executionId,
|
|
3034
|
+
const workflow = workflowResponse.workflow;
|
|
3035
|
+
// Find first step from Flowchart (activity with no incoming connections)
|
|
3036
|
+
const flowchart = workflow.root;
|
|
3037
|
+
const activities = flowchart.activities || [];
|
|
3038
|
+
const connections = flowchart.connections || [];
|
|
3039
|
+
// Build connection map: target -> source[]
|
|
3040
|
+
const incomingConnections = new Map();
|
|
3041
|
+
connections.forEach((conn) => {
|
|
3042
|
+
const targetId = conn.target.activity;
|
|
3043
|
+
if (!incomingConnections.has(targetId)) {
|
|
3044
|
+
incomingConnections.set(targetId, []);
|
|
3045
|
+
}
|
|
3046
|
+
incomingConnections.get(targetId).push(conn.source.activity);
|
|
2954
3047
|
});
|
|
2955
|
-
|
|
2956
|
-
|
|
3048
|
+
// Find root activity (activity with no incoming connections, or first activity)
|
|
3049
|
+
let firstActivity = null;
|
|
3050
|
+
for (const activity of activities) {
|
|
3051
|
+
if (!incomingConnections.has(activity.id)) {
|
|
3052
|
+
firstActivity = activity;
|
|
3053
|
+
break;
|
|
3054
|
+
}
|
|
2957
3055
|
}
|
|
2958
|
-
//
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
}
|
|
2962
|
-
const
|
|
2963
|
-
//
|
|
2964
|
-
const
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
3056
|
+
// If no root found, use first activity
|
|
3057
|
+
if (!firstActivity && activities.length > 0) {
|
|
3058
|
+
firstActivity = activities[0];
|
|
3059
|
+
}
|
|
3060
|
+
const firstStepId = firstActivity?.id || 'root';
|
|
3061
|
+
// Create workflow state
|
|
3062
|
+
const workflowState = {
|
|
3063
|
+
id: `state-${instanceId}`,
|
|
3064
|
+
definitionId: workflow.definitionId,
|
|
3065
|
+
definitionVersion: workflow.version,
|
|
3066
|
+
correlationId: null,
|
|
3067
|
+
status: 'Running',
|
|
3068
|
+
subStatus: 'Executing',
|
|
3069
|
+
bookmarks: [],
|
|
3070
|
+
incidents: [],
|
|
3071
|
+
fault: null,
|
|
3072
|
+
completionCallbacks: [],
|
|
3073
|
+
activityExecutionContexts: firstActivity ? [{
|
|
3074
|
+
id: `ctx-${firstStepId}`,
|
|
3075
|
+
parentContextId: null,
|
|
3076
|
+
scheduledActivityNodeId: firstStepId,
|
|
3077
|
+
ownerActivityNodeId: null,
|
|
3078
|
+
properties: {},
|
|
3079
|
+
activityState: null,
|
|
3080
|
+
dynamicVariables: [],
|
|
3081
|
+
status: 'Running',
|
|
3082
|
+
isExecuting: false,
|
|
3083
|
+
faultCount: 0,
|
|
3084
|
+
startedAt: now,
|
|
3085
|
+
completedAt: null,
|
|
3086
|
+
tag: null
|
|
3087
|
+
}] : [],
|
|
3088
|
+
input: request.input || {},
|
|
3089
|
+
output: {},
|
|
3090
|
+
properties: {},
|
|
3091
|
+
createdAt: now,
|
|
3092
|
+
updatedAt: now,
|
|
3093
|
+
finishedAt: null
|
|
2974
3094
|
};
|
|
2975
|
-
//
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
3095
|
+
// Create workflow instance
|
|
3096
|
+
const instance = {
|
|
3097
|
+
$schema: 'https://elsaworkflows.io/schemas/workflow-instance/v3.0.0/schema.json',
|
|
3098
|
+
id: instanceId,
|
|
3099
|
+
definitionId: workflow.definitionId,
|
|
3100
|
+
definitionVersionId: workflow.id,
|
|
3101
|
+
version: workflow.version,
|
|
3102
|
+
parentWorkflowInstanceId: null,
|
|
3103
|
+
workflowState,
|
|
3104
|
+
status: 'Running',
|
|
3105
|
+
subStatus: 'Executing',
|
|
3106
|
+
correlationId: null,
|
|
3107
|
+
name: workflow.name || null,
|
|
3108
|
+
incidentCount: 0,
|
|
3109
|
+
createdAt: now,
|
|
3110
|
+
updatedAt: now,
|
|
3111
|
+
finishedAt: null
|
|
3112
|
+
};
|
|
3113
|
+
// Store instance in IndexedDB
|
|
3114
|
+
await this.db.instances.add(instance, instance.id);
|
|
3115
|
+
// Convert to execution state for response
|
|
3116
|
+
let state = this.instanceToExecutionState(instance);
|
|
3117
|
+
// 🎯 KEY LOGIC: Execute all backend activities until we reach a frontend activity
|
|
3118
|
+
let currentActivity = firstActivity;
|
|
3119
|
+
let executionCount = 0;
|
|
3120
|
+
const maxExecutions = 100; // Prevent infinite loops
|
|
3121
|
+
while (currentActivity && executionCount < maxExecutions) {
|
|
3122
|
+
executionCount++;
|
|
3123
|
+
// Map activity type to ACoreX format
|
|
3124
|
+
let activityType = currentActivity.type;
|
|
3125
|
+
if (activityType.startsWith('Elsa.')) {
|
|
3126
|
+
let type = activityType.replace(/^Elsa\./, '');
|
|
3127
|
+
type = type.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
|
|
3128
|
+
activityType = `workflow-activity:${type}`;
|
|
2988
3129
|
}
|
|
3130
|
+
// Determine execution mode
|
|
3131
|
+
const executionMode = this.determineExecutionMode(activityType, currentActivity);
|
|
3132
|
+
// If frontend activity → stop and return as pendingTask
|
|
3133
|
+
if (executionMode === 'frontend') {
|
|
3134
|
+
const pendingTask = this.createTaskFromActivity(currentActivity, state);
|
|
3135
|
+
// Update state to suspended (waiting for frontend)
|
|
3136
|
+
state = {
|
|
3137
|
+
...state,
|
|
3138
|
+
status: 'suspended',
|
|
3139
|
+
currentStepId: currentActivity.id,
|
|
3140
|
+
};
|
|
3141
|
+
await this.updateInstanceFromExecutionState(instanceId, state);
|
|
3142
|
+
return {
|
|
3143
|
+
executionId: instanceId,
|
|
3144
|
+
state,
|
|
3145
|
+
pendingTask
|
|
3146
|
+
};
|
|
3147
|
+
}
|
|
3148
|
+
// Backend activity → execute it
|
|
3149
|
+
console.log(`[WorkflowExecutionService] Executing backend activity '${currentActivity.name || currentActivity.id}' (${activityType})`);
|
|
3150
|
+
const executionResult = await this.executeBackendActivityLocally(currentActivity, { ...state.variables, ...state.input }, state);
|
|
3151
|
+
// Update variables with output
|
|
3152
|
+
state = {
|
|
3153
|
+
...state,
|
|
3154
|
+
variables: {
|
|
3155
|
+
...state.variables,
|
|
3156
|
+
...executionResult.output
|
|
3157
|
+
},
|
|
3158
|
+
currentStepId: currentActivity.id,
|
|
3159
|
+
lastUpdated: new Date()
|
|
3160
|
+
};
|
|
3161
|
+
// Find next activity based on outcome
|
|
3162
|
+
const outcome = Object.keys(executionResult.outcomes)[0] || 'Done';
|
|
3163
|
+
const nextConnection = connections.find((conn) => conn.source.activity === currentActivity.id &&
|
|
3164
|
+
(conn.source.port === outcome || (!conn.source.port && outcome === 'Done')));
|
|
3165
|
+
if (!nextConnection) {
|
|
3166
|
+
// No next activity → workflow completed
|
|
3167
|
+
state = {
|
|
3168
|
+
...state,
|
|
3169
|
+
status: 'completed',
|
|
3170
|
+
currentStepId: undefined,
|
|
3171
|
+
output: state.variables
|
|
3172
|
+
};
|
|
3173
|
+
await this.updateInstanceFromExecutionState(instanceId, state);
|
|
3174
|
+
return {
|
|
3175
|
+
executionId: instanceId,
|
|
3176
|
+
state,
|
|
3177
|
+
pendingTask: null
|
|
3178
|
+
};
|
|
3179
|
+
}
|
|
3180
|
+
// Find next activity
|
|
3181
|
+
currentActivity = this.findActivityInFlowchart(flowchart, nextConnection.target.activity);
|
|
2989
3182
|
}
|
|
2990
|
-
//
|
|
2991
|
-
|
|
3183
|
+
// If we exit loop without frontend activity, workflow is complete
|
|
3184
|
+
state = {
|
|
2992
3185
|
...state,
|
|
2993
|
-
status:
|
|
2994
|
-
currentStepId:
|
|
2995
|
-
|
|
2996
|
-
lastUpdated: new Date(),
|
|
2997
|
-
};
|
|
2998
|
-
// Update nextTask with updated state
|
|
2999
|
-
if (nextTask && nextStepId) {
|
|
3000
|
-
nextTask = this.createTaskFromStep(this.findActivityInWorkflow(workflow.root, nextStepId), updatedState);
|
|
3001
|
-
}
|
|
3002
|
-
// Save to IndexedDB (convert Date to ISO string)
|
|
3003
|
-
const stateToStore = {
|
|
3004
|
-
...updatedState,
|
|
3005
|
-
lastUpdated: updatedState.lastUpdated.toISOString(),
|
|
3186
|
+
status: 'completed',
|
|
3187
|
+
currentStepId: undefined,
|
|
3188
|
+
output: state.variables
|
|
3006
3189
|
};
|
|
3007
|
-
await this.
|
|
3190
|
+
await this.updateInstanceFromExecutionState(instanceId, state);
|
|
3008
3191
|
return {
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
state: updatedState,
|
|
3192
|
+
executionId: instanceId,
|
|
3193
|
+
state,
|
|
3194
|
+
pendingTask: null
|
|
3013
3195
|
};
|
|
3014
3196
|
}
|
|
3015
3197
|
/**
|
|
3016
|
-
* Find activity in
|
|
3198
|
+
* Find activity in Flowchart by ID.
|
|
3017
3199
|
*/
|
|
3018
|
-
|
|
3019
|
-
const
|
|
3020
|
-
|
|
3021
|
-
return activity;
|
|
3022
|
-
}
|
|
3023
|
-
if (activityAny.children && Array.isArray(activityAny.children)) {
|
|
3024
|
-
for (const child of activityAny.children) {
|
|
3025
|
-
const found = this.findActivityInWorkflow(child, activityId);
|
|
3026
|
-
if (found) {
|
|
3027
|
-
return found;
|
|
3028
|
-
}
|
|
3029
|
-
}
|
|
3030
|
-
}
|
|
3031
|
-
return null;
|
|
3200
|
+
findActivityInFlowchart(flowchart, activityId) {
|
|
3201
|
+
const activities = flowchart.activities || [];
|
|
3202
|
+
return activities.find(a => a.id === activityId) || null;
|
|
3032
3203
|
}
|
|
3033
3204
|
/**
|
|
3034
3205
|
* Resume a suspended workflow execution.
|
|
3206
|
+
*
|
|
3207
|
+
* After frontend completes its task:
|
|
3208
|
+
* 1. Validates taskToken
|
|
3209
|
+
* 2. Finds next activity based on outcome
|
|
3210
|
+
* 3. Executes ALL backend activities in sequence
|
|
3211
|
+
* 4. Stops at first frontend activity and returns it as pendingTask
|
|
3035
3212
|
*/
|
|
3036
3213
|
async resumeExecution(request) {
|
|
3037
3214
|
// Get current state
|
|
3038
|
-
|
|
3215
|
+
let state = await this.getExecutionState({
|
|
3039
3216
|
executionId: request.executionId,
|
|
3040
3217
|
});
|
|
3041
3218
|
if (!state) {
|
|
@@ -3044,78 +3221,139 @@ class AXCWorkflowExecutionService {
|
|
|
3044
3221
|
if (state.status !== 'suspended') {
|
|
3045
3222
|
throw new Error(`Cannot resume workflow with status: ${state.status}. Expected: suspended`);
|
|
3046
3223
|
}
|
|
3047
|
-
//
|
|
3224
|
+
// TODO: Validate taskToken here for security
|
|
3225
|
+
// For now, just verify stepId matches
|
|
3226
|
+
if (state.currentStepId !== request.stepId) {
|
|
3227
|
+
throw new Error(`Step mismatch: expected '${state.currentStepId}', got '${request.stepId}'`);
|
|
3228
|
+
}
|
|
3229
|
+
// Get workflow definition
|
|
3048
3230
|
const workflowResponse = await this.getWorkflowDefinition({
|
|
3049
3231
|
workflowId: state.workflowId
|
|
3050
3232
|
});
|
|
3051
3233
|
const workflow = workflowResponse.workflow;
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
let nextStepId = undefined;
|
|
3056
|
-
if (currentStep && currentStep.outcomeConnections) {
|
|
3057
|
-
// Find connection for the outcome
|
|
3058
|
-
const connection = currentStep.outcomeConnections.find((conn) => conn.outcome === request.outcome);
|
|
3059
|
-
if (connection && connection.targetNodeId) {
|
|
3060
|
-
const targetStep = this.findActivityInWorkflow(workflow.root, connection.targetNodeId);
|
|
3061
|
-
if (targetStep) {
|
|
3062
|
-
nextStepId = targetStep.id || connection.targetNodeId;
|
|
3063
|
-
nextTask = this.createTaskFromStep(targetStep, state);
|
|
3064
|
-
}
|
|
3065
|
-
}
|
|
3066
|
-
}
|
|
3067
|
-
// Update state with outcome and user input
|
|
3068
|
-
const updatedVariables = {
|
|
3069
|
-
...state.variables,
|
|
3070
|
-
[`${request.stepId}_outcome`]: request.outcome,
|
|
3071
|
-
[`${request.stepId}_userInput`]: request.userInput || {},
|
|
3072
|
-
};
|
|
3073
|
-
const updatedState = {
|
|
3234
|
+
const connections = workflow.root.connections || [];
|
|
3235
|
+
// Update state with frontend activity outcome and user input
|
|
3236
|
+
state = {
|
|
3074
3237
|
...state,
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
const stateToStore = {
|
|
3082
|
-
...updatedState,
|
|
3083
|
-
lastUpdated: updatedState.lastUpdated.toISOString(),
|
|
3238
|
+
variables: {
|
|
3239
|
+
...state.variables,
|
|
3240
|
+
[`${request.stepId}_outcome`]: request.outcome,
|
|
3241
|
+
[`${request.stepId}_userInput`]: request.userInput || {},
|
|
3242
|
+
},
|
|
3243
|
+
lastUpdated: new Date()
|
|
3084
3244
|
};
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3245
|
+
// Find next activity based on outcome from frontend
|
|
3246
|
+
const nextConnection = connections.find((conn) => conn.source.activity === request.stepId &&
|
|
3247
|
+
(conn.source.port === request.outcome || (!conn.source.port && request.outcome === 'Done')));
|
|
3248
|
+
if (!nextConnection) {
|
|
3249
|
+
// No next activity → workflow completed
|
|
3250
|
+
state = {
|
|
3251
|
+
...state,
|
|
3252
|
+
status: 'completed',
|
|
3253
|
+
currentStepId: undefined,
|
|
3254
|
+
output: state.variables
|
|
3255
|
+
};
|
|
3256
|
+
await this.updateInstanceFromExecutionState(request.executionId, state);
|
|
3257
|
+
return {
|
|
3258
|
+
output: { outcome: request.outcome, userInput: request.userInput },
|
|
3259
|
+
outcomes: { [request.outcome]: true },
|
|
3260
|
+
nextTask: null,
|
|
3261
|
+
state
|
|
3262
|
+
};
|
|
3089
3263
|
}
|
|
3090
|
-
//
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3264
|
+
// 🎯 KEY LOGIC: Execute all backend activities until we reach next frontend activity
|
|
3265
|
+
let currentActivity = this.findActivityInFlowchart(workflow.root, nextConnection.target.activity);
|
|
3266
|
+
let executionCount = 0;
|
|
3267
|
+
const maxExecutions = 100;
|
|
3268
|
+
while (currentActivity && executionCount < maxExecutions) {
|
|
3269
|
+
executionCount++;
|
|
3270
|
+
// Map activity type
|
|
3271
|
+
let activityType = currentActivity.type;
|
|
3272
|
+
if (activityType.startsWith('Elsa.')) {
|
|
3273
|
+
let type = activityType.replace(/^Elsa\./, '');
|
|
3274
|
+
type = type.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
|
|
3275
|
+
activityType = `workflow-activity:${type}`;
|
|
3276
|
+
}
|
|
3277
|
+
// Determine execution mode
|
|
3278
|
+
const executionMode = this.determineExecutionMode(activityType, currentActivity);
|
|
3279
|
+
// If frontend activity → stop and return as pendingTask
|
|
3280
|
+
if (executionMode === 'frontend') {
|
|
3281
|
+
const pendingTask = this.createTaskFromActivity(currentActivity, state);
|
|
3282
|
+
state = {
|
|
3283
|
+
...state,
|
|
3284
|
+
status: 'suspended',
|
|
3285
|
+
currentStepId: currentActivity.id,
|
|
3286
|
+
};
|
|
3287
|
+
await this.updateInstanceFromExecutionState(request.executionId, state);
|
|
3288
|
+
return {
|
|
3289
|
+
output: { outcome: request.outcome, userInput: request.userInput },
|
|
3290
|
+
outcomes: { [request.outcome]: true },
|
|
3291
|
+
nextTask: pendingTask,
|
|
3292
|
+
state
|
|
3293
|
+
};
|
|
3294
|
+
}
|
|
3295
|
+
// Backend activity → execute it
|
|
3296
|
+
console.log(`[WorkflowExecutionService] Executing backend activity '${currentActivity.name || currentActivity.id}' (${activityType})`);
|
|
3297
|
+
const executionResult = await this.executeBackendActivityLocally(currentActivity, { ...state.variables, ...state.input }, state);
|
|
3298
|
+
// Update variables with output
|
|
3299
|
+
state = {
|
|
3300
|
+
...state,
|
|
3301
|
+
variables: {
|
|
3302
|
+
...state.variables,
|
|
3303
|
+
...executionResult.output
|
|
3304
|
+
},
|
|
3305
|
+
currentStepId: currentActivity.id,
|
|
3306
|
+
lastUpdated: new Date()
|
|
3307
|
+
};
|
|
3308
|
+
// Find next activity based on outcome
|
|
3309
|
+
const outcome = Object.keys(executionResult.outcomes)[0] || 'Done';
|
|
3310
|
+
const nextConn = connections.find((conn) => conn.source.activity === currentActivity.id &&
|
|
3311
|
+
(conn.source.port === outcome || (!conn.source.port && outcome === 'Done')));
|
|
3312
|
+
if (!nextConn) {
|
|
3313
|
+
// No next activity → workflow completed
|
|
3314
|
+
state = {
|
|
3315
|
+
...state,
|
|
3316
|
+
status: 'completed',
|
|
3317
|
+
currentStepId: undefined,
|
|
3318
|
+
output: state.variables
|
|
3319
|
+
};
|
|
3320
|
+
await this.updateInstanceFromExecutionState(request.executionId, state);
|
|
3321
|
+
return {
|
|
3322
|
+
output: state.variables,
|
|
3323
|
+
outcomes: { Done: true },
|
|
3324
|
+
nextTask: null,
|
|
3325
|
+
state
|
|
3326
|
+
};
|
|
3327
|
+
}
|
|
3328
|
+
// Find next activity
|
|
3329
|
+
currentActivity = this.findActivityInFlowchart(workflow.root, nextConn.target.activity);
|
|
3330
|
+
}
|
|
3331
|
+
// If we exit loop, workflow is complete
|
|
3332
|
+
state = {
|
|
3333
|
+
...state,
|
|
3334
|
+
status: 'completed',
|
|
3335
|
+
currentStepId: undefined,
|
|
3336
|
+
output: state.variables
|
|
3096
3337
|
};
|
|
3338
|
+
await this.updateInstanceFromExecutionState(request.executionId, state);
|
|
3097
3339
|
return {
|
|
3098
|
-
output,
|
|
3099
|
-
outcomes: {
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
nextTask, // Next task from outcomeConnections
|
|
3103
|
-
state: updatedState,
|
|
3340
|
+
output: state.variables,
|
|
3341
|
+
outcomes: { Done: true },
|
|
3342
|
+
nextTask: null,
|
|
3343
|
+
state
|
|
3104
3344
|
};
|
|
3105
3345
|
}
|
|
3106
3346
|
/**
|
|
3107
3347
|
* Get current workflow execution state.
|
|
3108
3348
|
*/
|
|
3109
3349
|
async getExecutionState(request) {
|
|
3110
|
-
|
|
3111
|
-
|
|
3350
|
+
// Get instance from IndexedDB
|
|
3351
|
+
const instance = await this.getInstance(request.executionId);
|
|
3352
|
+
if (!instance) {
|
|
3112
3353
|
throw new Error(`Workflow execution not found: ${request.executionId}`);
|
|
3113
3354
|
}
|
|
3114
|
-
// Convert
|
|
3115
|
-
return
|
|
3116
|
-
...state,
|
|
3117
|
-
lastUpdated: new Date(state.lastUpdated),
|
|
3118
|
-
};
|
|
3355
|
+
// Convert instance to execution state
|
|
3356
|
+
return this.instanceToExecutionState(instance);
|
|
3119
3357
|
}
|
|
3120
3358
|
/**
|
|
3121
3359
|
* Get workflow definition by ID.
|
|
@@ -3131,10 +3369,28 @@ class AXCWorkflowExecutionService {
|
|
|
3131
3369
|
const storedWorkflow = localStorage.getItem(`workflow:${request.workflowId}`);
|
|
3132
3370
|
if (storedWorkflow) {
|
|
3133
3371
|
try {
|
|
3134
|
-
const
|
|
3135
|
-
//
|
|
3136
|
-
|
|
3137
|
-
|
|
3372
|
+
const workflowDefinition = JSON.parse(storedWorkflow);
|
|
3373
|
+
// Validate format
|
|
3374
|
+
if (workflowDefinition.root && workflowDefinition.root.type === 'Elsa.Flowchart') {
|
|
3375
|
+
return { workflow: workflowDefinition };
|
|
3376
|
+
}
|
|
3377
|
+
// If stored in materializerContext.stringData, parse it
|
|
3378
|
+
if (workflowDefinition.materializerContext?.stringData) {
|
|
3379
|
+
try {
|
|
3380
|
+
const rootFlowchart = JSON.parse(workflowDefinition.materializerContext.stringData);
|
|
3381
|
+
if (rootFlowchart.type === 'Elsa.Flowchart') {
|
|
3382
|
+
return {
|
|
3383
|
+
workflow: {
|
|
3384
|
+
...workflowDefinition,
|
|
3385
|
+
root: rootFlowchart
|
|
3386
|
+
}
|
|
3387
|
+
};
|
|
3388
|
+
}
|
|
3389
|
+
}
|
|
3390
|
+
catch (error) {
|
|
3391
|
+
console.warn('Failed to parse stringData from materializerContext:', error);
|
|
3392
|
+
}
|
|
3393
|
+
}
|
|
3138
3394
|
}
|
|
3139
3395
|
catch (error) {
|
|
3140
3396
|
console.warn(`Failed to parse stored workflow ${request.workflowId}:`, error);
|
|
@@ -3142,181 +3398,39 @@ class AXCWorkflowExecutionService {
|
|
|
3142
3398
|
}
|
|
3143
3399
|
// If not found in localStorage, return a default mock workflow
|
|
3144
3400
|
// In production, this would be an HTTP call to backend
|
|
3401
|
+
const now = new Date().toISOString();
|
|
3145
3402
|
const defaultWorkflow = {
|
|
3403
|
+
$schema: 'https://elsaworkflows.io/schemas/workflow-definition/v3.0.0/schema.json',
|
|
3146
3404
|
id: request.workflowId,
|
|
3147
|
-
|
|
3405
|
+
definitionId: request.workflowId,
|
|
3406
|
+
createdAt: now,
|
|
3148
3407
|
version: 1,
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3408
|
+
isLatest: true,
|
|
3409
|
+
isPublished: false,
|
|
3410
|
+
isReadonly: false,
|
|
3411
|
+
isSystem: false,
|
|
3412
|
+
name: `Workflow ${request.workflowId}`,
|
|
3413
|
+
description: 'Default mock workflow',
|
|
3414
|
+
variables: [],
|
|
3415
|
+
inputs: [],
|
|
3416
|
+
outputs: [],
|
|
3417
|
+
outcomes: ['Done'],
|
|
3418
|
+
customProperties: {},
|
|
3419
|
+
options: {
|
|
3420
|
+
usableAsActivity: false,
|
|
3421
|
+
autoUpdateConsumingWorkflows: false
|
|
3153
3422
|
},
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
convertElsaToWorkflowEngine(elsaDefinition) {
|
|
3163
|
-
// Extract root activity from Elsa format
|
|
3164
|
-
let rootActivity;
|
|
3165
|
-
if (elsaDefinition.root) {
|
|
3166
|
-
// Root activity is directly available
|
|
3167
|
-
rootActivity = elsaDefinition.root;
|
|
3168
|
-
}
|
|
3169
|
-
else if (elsaDefinition.materializerContext?.stringData) {
|
|
3170
|
-
// Root activity is stored in materializerContext.stringData
|
|
3171
|
-
try {
|
|
3172
|
-
rootActivity = JSON.parse(elsaDefinition.materializerContext.stringData);
|
|
3173
|
-
}
|
|
3174
|
-
catch (error) {
|
|
3175
|
-
console.warn('Failed to parse stringData from materializerContext:', error);
|
|
3176
|
-
// Fallback to default
|
|
3177
|
-
rootActivity = {
|
|
3178
|
-
type: 'workflow-activity:sequence',
|
|
3179
|
-
name: 'Root Sequence'
|
|
3180
|
-
};
|
|
3423
|
+
root: {
|
|
3424
|
+
id: 'root-flowchart',
|
|
3425
|
+
nodeId: 'root-flowchart',
|
|
3426
|
+
type: 'Elsa.Flowchart',
|
|
3427
|
+
version: 1,
|
|
3428
|
+
activities: [],
|
|
3429
|
+
connections: [],
|
|
3430
|
+
variables: []
|
|
3181
3431
|
}
|
|
3182
|
-
}
|
|
3183
|
-
else {
|
|
3184
|
-
// Fallback to default
|
|
3185
|
-
rootActivity = {
|
|
3186
|
-
type: 'workflow-activity:sequence',
|
|
3187
|
-
name: 'Root Sequence'
|
|
3188
|
-
};
|
|
3189
|
-
}
|
|
3190
|
-
// Convert to AXPWorkflowEngine format
|
|
3191
|
-
const workflow = {
|
|
3192
|
-
id: elsaDefinition.id || elsaDefinition.definitionId || 'unknown',
|
|
3193
|
-
name: elsaDefinition.name || 'Untitled Workflow',
|
|
3194
|
-
description: elsaDefinition.description,
|
|
3195
|
-
version: elsaDefinition.version || 1,
|
|
3196
|
-
root: rootActivity,
|
|
3197
|
-
activities: this.extractActivities(rootActivity)
|
|
3198
3432
|
};
|
|
3199
|
-
return workflow;
|
|
3200
|
-
}
|
|
3201
|
-
/**
|
|
3202
|
-
* Extract all activities from root activity recursively
|
|
3203
|
-
*/
|
|
3204
|
-
extractActivities(activity) {
|
|
3205
|
-
const activities = [];
|
|
3206
|
-
if (!activity) {
|
|
3207
|
-
return activities;
|
|
3208
|
-
}
|
|
3209
|
-
// Add current activity
|
|
3210
|
-
activities.push(activity);
|
|
3211
|
-
// Extract from children (for sequence, parallel, etc.)
|
|
3212
|
-
if (activity.children && Array.isArray(activity.children)) {
|
|
3213
|
-
activity.children.forEach((child) => {
|
|
3214
|
-
activities.push(...this.extractActivities(child));
|
|
3215
|
-
});
|
|
3216
|
-
}
|
|
3217
|
-
// Extract from then/else (for if activity)
|
|
3218
|
-
if (activity.then) {
|
|
3219
|
-
activities.push(...this.extractActivities(activity.then));
|
|
3220
|
-
}
|
|
3221
|
-
if (activity.else) {
|
|
3222
|
-
activities.push(...this.extractActivities(activity.else));
|
|
3223
|
-
}
|
|
3224
|
-
// Extract from try/catch/finally (for try-catch activity)
|
|
3225
|
-
if (activity.try) {
|
|
3226
|
-
activities.push(...this.extractActivities(activity.try));
|
|
3227
|
-
}
|
|
3228
|
-
if (activity.catch) {
|
|
3229
|
-
activities.push(...this.extractActivities(activity.catch));
|
|
3230
|
-
}
|
|
3231
|
-
if (activity.finally) {
|
|
3232
|
-
activities.push(...this.extractActivities(activity.finally));
|
|
3233
|
-
}
|
|
3234
|
-
// Extract from branches (for parallel activity)
|
|
3235
|
-
if (activity.branches && Array.isArray(activity.branches)) {
|
|
3236
|
-
activity.branches.forEach((branch) => {
|
|
3237
|
-
activities.push(...this.extractActivities(branch));
|
|
3238
|
-
});
|
|
3239
|
-
}
|
|
3240
|
-
return activities;
|
|
3241
|
-
}
|
|
3242
|
-
/**
|
|
3243
|
-
* Execute current step from execution state.
|
|
3244
|
-
*
|
|
3245
|
-
* Backend handles everything: gets state, workflow definition, finds step, determines nextStep.
|
|
3246
|
-
*/
|
|
3247
|
-
async executeCurrentStep(request) {
|
|
3248
|
-
// Get current state
|
|
3249
|
-
const state = await this.getExecutionState({
|
|
3250
|
-
executionId: request.executionId,
|
|
3251
|
-
});
|
|
3252
|
-
if (!state.currentStepId) {
|
|
3253
|
-
throw new Error(`No current step defined for execution: ${request.executionId}`);
|
|
3254
|
-
}
|
|
3255
|
-
// Get workflow definition
|
|
3256
|
-
const workflowResponse = await this.getWorkflowDefinition({
|
|
3257
|
-
workflowId: state.workflowId
|
|
3258
|
-
});
|
|
3259
|
-
if (!workflowResponse.workflow) {
|
|
3260
|
-
throw new Error(`Workflow definition not found: ${state.workflowId}`);
|
|
3261
|
-
}
|
|
3262
|
-
// Find current step in workflow
|
|
3263
|
-
const currentStep = this.findActivityInWorkflow(workflowResponse.workflow.root, state.currentStepId);
|
|
3264
|
-
if (!currentStep) {
|
|
3265
|
-
throw new Error(`Step '${state.currentStepId}' not found in workflow '${state.workflowId}'`);
|
|
3266
|
-
}
|
|
3267
|
-
// Determine execution mode from activity definition or descriptor
|
|
3268
|
-
const stepAny = currentStep;
|
|
3269
|
-
const executionMode = this.determineExecutionMode(stepAny.type, stepAny);
|
|
3270
|
-
const isBackendActivity = executionMode === 'backend' || executionMode === 'both';
|
|
3271
|
-
if (isBackendActivity) {
|
|
3272
|
-
// Execute backend activity
|
|
3273
|
-
const backendResponse = await this.executeBackendActivity({
|
|
3274
|
-
workflowId: state.workflowId,
|
|
3275
|
-
executionId: request.executionId,
|
|
3276
|
-
activityType: stepAny.type,
|
|
3277
|
-
activityId: state.currentStepId,
|
|
3278
|
-
properties: stepAny.properties || {},
|
|
3279
|
-
workflowState: {
|
|
3280
|
-
variables: state.variables,
|
|
3281
|
-
input: state.input
|
|
3282
|
-
}
|
|
3283
|
-
});
|
|
3284
|
-
return {
|
|
3285
|
-
output: backendResponse.output,
|
|
3286
|
-
outcomes: backendResponse.outcomes,
|
|
3287
|
-
nextTask: backendResponse.nextTask || null,
|
|
3288
|
-
state: backendResponse.state
|
|
3289
|
-
};
|
|
3290
|
-
}
|
|
3291
|
-
else {
|
|
3292
|
-
// Frontend activity - return current task for frontend to execute
|
|
3293
|
-
// The nextTask should be the CURRENT activity (frontend will execute it)
|
|
3294
|
-
// After frontend executes, it will call resumeExecution with outcome
|
|
3295
|
-
// Create task for current step (frontend will execute this)
|
|
3296
|
-
const currentTask = this.createTaskFromStep(currentStep, state);
|
|
3297
|
-
// Update state to indicate step is suspended (waiting for frontend execution)
|
|
3298
|
-
const updatedState = {
|
|
3299
|
-
...state,
|
|
3300
|
-
status: 'suspended', // Frontend activities suspend the workflow
|
|
3301
|
-
lastUpdated: new Date()
|
|
3302
|
-
};
|
|
3303
|
-
// Save to IndexedDB
|
|
3304
|
-
const stateToStore = {
|
|
3305
|
-
...updatedState,
|
|
3306
|
-
lastUpdated: updatedState.lastUpdated.toISOString(),
|
|
3307
|
-
};
|
|
3308
|
-
await this.db.executions.update(state.executionId, stateToStore);
|
|
3309
|
-
return {
|
|
3310
|
-
output: {
|
|
3311
|
-
stepId: state.currentStepId,
|
|
3312
|
-
stepType: stepAny.type,
|
|
3313
|
-
properties: stepAny.properties || {}
|
|
3314
|
-
},
|
|
3315
|
-
outcomes: {},
|
|
3316
|
-
nextTask: currentTask, // Return current task so frontend can execute it
|
|
3317
|
-
state: updatedState
|
|
3318
|
-
};
|
|
3319
|
-
}
|
|
3433
|
+
return { workflow: defaultWorkflow };
|
|
3320
3434
|
}
|
|
3321
3435
|
//#region ---- Task-Based Helper Methods ----
|
|
3322
3436
|
/**
|
|
@@ -3327,19 +3441,21 @@ class AXCWorkflowExecutionService {
|
|
|
3327
3441
|
return `${executionId}:${activityId}:${Date.now()}`;
|
|
3328
3442
|
}
|
|
3329
3443
|
/**
|
|
3330
|
-
* Determine execution mode for an activity
|
|
3444
|
+
* Determine execution mode for an activity.
|
|
3331
3445
|
*
|
|
3332
|
-
*
|
|
3333
|
-
*
|
|
3446
|
+
* Priority (highest to lowest):
|
|
3447
|
+
* 1. Activity instance's executionMode (from AXPActivity in workflow definition)
|
|
3448
|
+
* 2. ActivityDescriptor's executionMode (from ActivityProviderService)
|
|
3449
|
+
* 3. Default: 'frontend'
|
|
3334
3450
|
*
|
|
3335
3451
|
* @param activityType - Activity type (e.g., 'workflow-activity:write-line')
|
|
3336
|
-
* @param
|
|
3452
|
+
* @param activity - Activity from workflow definition (AXPActivity)
|
|
3337
3453
|
* @returns Execution mode: 'frontend', 'backend', or 'both'
|
|
3338
3454
|
*/
|
|
3339
|
-
determineExecutionMode(activityType,
|
|
3340
|
-
// 1. Check if executionMode is
|
|
3341
|
-
if (
|
|
3342
|
-
return
|
|
3455
|
+
determineExecutionMode(activityType, activity) {
|
|
3456
|
+
// 1. Check if executionMode is explicitly set in activity instance (highest priority)
|
|
3457
|
+
if (activity?.executionMode) {
|
|
3458
|
+
return activity.executionMode;
|
|
3343
3459
|
}
|
|
3344
3460
|
// 2. Check ActivityDescriptor from ActivityProviderService
|
|
3345
3461
|
const descriptor = this.activityProviderService.getDescriptor(activityType);
|
|
@@ -3350,39 +3466,117 @@ class AXCWorkflowExecutionService {
|
|
|
3350
3466
|
return 'frontend';
|
|
3351
3467
|
}
|
|
3352
3468
|
/**
|
|
3353
|
-
* Create a task from a workflow
|
|
3469
|
+
* Create a task from a workflow activity.
|
|
3354
3470
|
* Inspired by Temporal's Activity Task and Elsa's Bookmark pattern.
|
|
3355
3471
|
*/
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
//
|
|
3359
|
-
const
|
|
3472
|
+
createTaskFromActivity(activity, state) {
|
|
3473
|
+
// Extract properties from activity
|
|
3474
|
+
// Activities have properties as AXPInputValue objects or primitives
|
|
3475
|
+
const properties = {};
|
|
3476
|
+
// Iterate through all properties of the activity
|
|
3477
|
+
Object.keys(activity).forEach(key => {
|
|
3478
|
+
// Skip standard Elsa fields
|
|
3479
|
+
if (['id', 'nodeId', 'name', 'type', 'version', 'customProperties', 'metadata'].includes(key)) {
|
|
3480
|
+
return;
|
|
3481
|
+
}
|
|
3482
|
+
const value = activity[key];
|
|
3483
|
+
// Handle AXPInputValue format
|
|
3484
|
+
if (value && typeof value === 'object' && 'typeName' in value && 'expression' in value) {
|
|
3485
|
+
// It's an AXPInputValue - extract the expression value
|
|
3486
|
+
if (value.expression && value.expression.value !== undefined) {
|
|
3487
|
+
properties[key] = value.expression.value;
|
|
3488
|
+
}
|
|
3489
|
+
else {
|
|
3490
|
+
properties[key] = null;
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
else {
|
|
3494
|
+
// Direct value
|
|
3495
|
+
properties[key] = value;
|
|
3496
|
+
}
|
|
3497
|
+
});
|
|
3498
|
+
// Map activity type to ACoreX activity type
|
|
3499
|
+
// Example: "Elsa.WriteLine" -> "workflow-activity:write-line"
|
|
3500
|
+
let activityType = activity.type;
|
|
3501
|
+
if (activityType.startsWith('Elsa.')) {
|
|
3502
|
+
let type = activityType.replace(/^Elsa\./, '');
|
|
3503
|
+
// Convert PascalCase to kebab-case
|
|
3504
|
+
type = type.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
|
|
3505
|
+
activityType = `workflow-activity:${type}`;
|
|
3506
|
+
}
|
|
3507
|
+
// Get executionMode from activity descriptor
|
|
3508
|
+
const executionMode = this.determineExecutionMode(activityType, activity);
|
|
3360
3509
|
return {
|
|
3361
|
-
taskToken: this.generateTaskToken(state.executionId,
|
|
3362
|
-
activityId:
|
|
3363
|
-
activityType
|
|
3364
|
-
activityName:
|
|
3510
|
+
taskToken: this.generateTaskToken(state.executionId, activity.id),
|
|
3511
|
+
activityId: activity.id,
|
|
3512
|
+
activityType,
|
|
3513
|
+
activityName: activity.name || undefined,
|
|
3365
3514
|
executionMode,
|
|
3366
|
-
input: (executionMode === 'frontend' || executionMode === 'both') ?
|
|
3367
|
-
config: (executionMode === 'frontend' || executionMode === 'both') ?
|
|
3515
|
+
input: (executionMode === 'frontend' || executionMode === 'both') ? properties : undefined,
|
|
3516
|
+
config: (executionMode === 'frontend' || executionMode === 'both') ? properties : undefined
|
|
3368
3517
|
};
|
|
3369
3518
|
}
|
|
3370
3519
|
//#endregion
|
|
3371
3520
|
//#region ---- Backend Activity Executors ----
|
|
3372
3521
|
/**
|
|
3373
|
-
* Execute backend activities locally
|
|
3374
|
-
*
|
|
3522
|
+
* Execute backend activities locally using CommandBus.
|
|
3523
|
+
*
|
|
3524
|
+
* Backend activities are registered as Commands and executed via CommandService.
|
|
3525
|
+
* This provides a unified execution channel for all activities.
|
|
3375
3526
|
*/
|
|
3376
3527
|
async executeBackendActivityLocally(activity, input, state) {
|
|
3377
|
-
|
|
3528
|
+
// Extract properties from activity
|
|
3529
|
+
const properties = {};
|
|
3530
|
+
Object.keys(activity).forEach(key => {
|
|
3531
|
+
if (['id', 'nodeId', 'name', 'type', 'version', 'customProperties', 'metadata', 'executionMode'].includes(key)) {
|
|
3532
|
+
return;
|
|
3533
|
+
}
|
|
3534
|
+
const value = activity[key];
|
|
3535
|
+
if (value && typeof value === 'object' && 'typeName' in value && 'expression' in value) {
|
|
3536
|
+
if (value.expression && value.expression.value !== undefined) {
|
|
3537
|
+
properties[key] = value.expression.value;
|
|
3538
|
+
}
|
|
3539
|
+
else {
|
|
3540
|
+
properties[key] = null;
|
|
3541
|
+
}
|
|
3542
|
+
}
|
|
3543
|
+
else {
|
|
3544
|
+
properties[key] = value;
|
|
3545
|
+
}
|
|
3546
|
+
});
|
|
3547
|
+
// Map activity type to ACoreX activity type
|
|
3548
|
+
let activityType = activity.type;
|
|
3549
|
+
if (activityType.startsWith('Elsa.')) {
|
|
3550
|
+
let type = activityType.replace(/^Elsa\./, '');
|
|
3551
|
+
type = type.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
|
|
3552
|
+
activityType = `workflow-activity:${type}`;
|
|
3553
|
+
}
|
|
3554
|
+
// Check if activity is registered as a Command
|
|
3555
|
+
if (this.commandService.exists(activityType)) {
|
|
3556
|
+
console.log(`[WorkflowExecutionService] Executing backend activity '${activityType}' via CommandBus`);
|
|
3557
|
+
try {
|
|
3558
|
+
// Execute via CommandBus
|
|
3559
|
+
const result = await this.commandService.execute(activityType, properties);
|
|
3560
|
+
return {
|
|
3561
|
+
output: result?.output || result,
|
|
3562
|
+
outcomes: result?.outcomes || { Done: true }
|
|
3563
|
+
};
|
|
3564
|
+
}
|
|
3565
|
+
catch (error) {
|
|
3566
|
+
console.error(`[WorkflowExecutionService] Backend activity '${activityType}' failed:`, error);
|
|
3567
|
+
return {
|
|
3568
|
+
output: { error: error.message || 'Unknown error' },
|
|
3569
|
+
outcomes: { Failed: true }
|
|
3570
|
+
};
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
// Fallback: Handle built-in activities that aren't Commands yet
|
|
3574
|
+
console.warn(`[WorkflowExecutionService] Activity '${activityType}' not registered as Command, using fallback`);
|
|
3575
|
+
switch (activityType) {
|
|
3378
3576
|
case 'workflow-activity:set-variable':
|
|
3379
|
-
return this.executeSetVariable(
|
|
3380
|
-
case 'workflow-activity:execute-command':
|
|
3381
|
-
return this.executeCommandMock(activity, input);
|
|
3382
|
-
case 'workflow-activity:execute-query':
|
|
3383
|
-
return this.executeQueryMock(activity, input);
|
|
3577
|
+
return this.executeSetVariable({ type: activityType, properties }, input);
|
|
3384
3578
|
case 'workflow-activity:http-request':
|
|
3385
|
-
return this.executeHttpRequest(
|
|
3579
|
+
return this.executeHttpRequest({ type: activityType, properties }, input);
|
|
3386
3580
|
default:
|
|
3387
3581
|
return { output: null, outcomes: { Done: true } };
|
|
3388
3582
|
}
|
|
@@ -3398,42 +3592,6 @@ class AXCWorkflowExecutionService {
|
|
|
3398
3592
|
outcomes: { Done: true }
|
|
3399
3593
|
};
|
|
3400
3594
|
}
|
|
3401
|
-
/**
|
|
3402
|
-
* Execute command mock - simulates backend command execution.
|
|
3403
|
-
*/
|
|
3404
|
-
async executeCommandMock(activity, input) {
|
|
3405
|
-
// Simulate delay for backend processing
|
|
3406
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
3407
|
-
return {
|
|
3408
|
-
output: {
|
|
3409
|
-
commandKey: activity.properties?.commandKey,
|
|
3410
|
-
success: true,
|
|
3411
|
-
result: {
|
|
3412
|
-
id: 'mock-' + Date.now(),
|
|
3413
|
-
timestamp: new Date().toISOString()
|
|
3414
|
-
}
|
|
3415
|
-
},
|
|
3416
|
-
outcomes: { Done: true }
|
|
3417
|
-
};
|
|
3418
|
-
}
|
|
3419
|
-
/**
|
|
3420
|
-
* Execute query mock - simulates backend query execution.
|
|
3421
|
-
*/
|
|
3422
|
-
async executeQueryMock(activity, input) {
|
|
3423
|
-
// Simulate delay for database query
|
|
3424
|
-
await new Promise(resolve => setTimeout(resolve, 300));
|
|
3425
|
-
return {
|
|
3426
|
-
output: {
|
|
3427
|
-
queryKey: activity.properties?.queryKey,
|
|
3428
|
-
data: [
|
|
3429
|
-
{ id: 1, name: 'Mock Item 1', createdAt: new Date().toISOString() },
|
|
3430
|
-
{ id: 2, name: 'Mock Item 2', createdAt: new Date().toISOString() }
|
|
3431
|
-
],
|
|
3432
|
-
count: 2
|
|
3433
|
-
},
|
|
3434
|
-
outcomes: { Done: true }
|
|
3435
|
-
};
|
|
3436
|
-
}
|
|
3437
3595
|
/**
|
|
3438
3596
|
* Execute HTTP request - makes real HTTP call.
|
|
3439
3597
|
* Supports different HTTP methods and handles timeouts.
|
|
@@ -3499,6 +3657,117 @@ class AXCWorkflowExecutionService {
|
|
|
3499
3657
|
};
|
|
3500
3658
|
}
|
|
3501
3659
|
}
|
|
3660
|
+
//#endregion
|
|
3661
|
+
//#region ---- Instance Management ----
|
|
3662
|
+
/**
|
|
3663
|
+
* Convert workflow instance to execution state (for backward compatibility).
|
|
3664
|
+
*/
|
|
3665
|
+
instanceToExecutionState(instance) {
|
|
3666
|
+
const state = instance.workflowState;
|
|
3667
|
+
// Find current activity from execution contexts
|
|
3668
|
+
const currentContext = state.activityExecutionContexts.find(ctx => ctx.status === 'Running' && !ctx.completedAt);
|
|
3669
|
+
// Map status
|
|
3670
|
+
let status = 'running';
|
|
3671
|
+
if (instance.status === 'Finished') {
|
|
3672
|
+
if (instance.subStatus === 'Faulted') {
|
|
3673
|
+
status = 'error';
|
|
3674
|
+
}
|
|
3675
|
+
else {
|
|
3676
|
+
status = 'completed';
|
|
3677
|
+
}
|
|
3678
|
+
}
|
|
3679
|
+
else if (instance.subStatus === 'Suspended') {
|
|
3680
|
+
status = 'suspended';
|
|
3681
|
+
}
|
|
3682
|
+
return {
|
|
3683
|
+
executionId: instance.id,
|
|
3684
|
+
workflowId: instance.definitionId,
|
|
3685
|
+
status,
|
|
3686
|
+
currentStepId: currentContext?.scheduledActivityNodeId,
|
|
3687
|
+
variables: state.properties || {},
|
|
3688
|
+
input: state.input || {},
|
|
3689
|
+
output: state.output || {},
|
|
3690
|
+
lastUpdated: new Date(instance.updatedAt)
|
|
3691
|
+
};
|
|
3692
|
+
}
|
|
3693
|
+
/**
|
|
3694
|
+
* Update execution state in instance and save to IndexedDB.
|
|
3695
|
+
*/
|
|
3696
|
+
async updateInstanceFromExecutionState(executionId, executionState) {
|
|
3697
|
+
const instance = await this.getInstance(executionId);
|
|
3698
|
+
if (!instance) {
|
|
3699
|
+
throw new Error(`Workflow instance not found: ${executionId}`);
|
|
3700
|
+
}
|
|
3701
|
+
// Update instance from execution state
|
|
3702
|
+
const now = new Date().toISOString();
|
|
3703
|
+
// Map execution state status to instance status
|
|
3704
|
+
let status = 'Running';
|
|
3705
|
+
let subStatus = 'Executing';
|
|
3706
|
+
if (executionState.status === 'completed') {
|
|
3707
|
+
status = 'Finished';
|
|
3708
|
+
subStatus = 'Finished';
|
|
3709
|
+
instance.finishedAt = now;
|
|
3710
|
+
}
|
|
3711
|
+
else if (executionState.status === 'error') {
|
|
3712
|
+
status = 'Finished';
|
|
3713
|
+
subStatus = 'Faulted';
|
|
3714
|
+
instance.finishedAt = now;
|
|
3715
|
+
}
|
|
3716
|
+
else if (executionState.status === 'suspended') {
|
|
3717
|
+
subStatus = 'Suspended';
|
|
3718
|
+
}
|
|
3719
|
+
instance.status = status;
|
|
3720
|
+
instance.subStatus = subStatus;
|
|
3721
|
+
instance.updatedAt = now;
|
|
3722
|
+
// Update workflow state
|
|
3723
|
+
instance.workflowState.status = status;
|
|
3724
|
+
instance.workflowState.subStatus = subStatus;
|
|
3725
|
+
instance.workflowState.input = executionState.input || {};
|
|
3726
|
+
instance.workflowState.output = executionState.output || {};
|
|
3727
|
+
instance.workflowState.properties = executionState.variables || {};
|
|
3728
|
+
instance.workflowState.updatedAt = now;
|
|
3729
|
+
if (executionState.status === 'completed' || executionState.status === 'error') {
|
|
3730
|
+
instance.workflowState.finishedAt = now;
|
|
3731
|
+
}
|
|
3732
|
+
// Update activity execution context if currentStepId changed
|
|
3733
|
+
if (executionState.currentStepId) {
|
|
3734
|
+
const existingContext = instance.workflowState.activityExecutionContexts.find(ctx => ctx.scheduledActivityNodeId === executionState.currentStepId);
|
|
3735
|
+
if (!existingContext) {
|
|
3736
|
+
// Add new context
|
|
3737
|
+
instance.workflowState.activityExecutionContexts.push({
|
|
3738
|
+
id: `ctx-${executionState.currentStepId}`,
|
|
3739
|
+
parentContextId: null,
|
|
3740
|
+
scheduledActivityNodeId: executionState.currentStepId,
|
|
3741
|
+
ownerActivityNodeId: null,
|
|
3742
|
+
properties: {},
|
|
3743
|
+
activityState: null,
|
|
3744
|
+
dynamicVariables: [],
|
|
3745
|
+
status: 'Running',
|
|
3746
|
+
isExecuting: false,
|
|
3747
|
+
faultCount: 0,
|
|
3748
|
+
startedAt: now,
|
|
3749
|
+
completedAt: null,
|
|
3750
|
+
tag: null
|
|
3751
|
+
});
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3754
|
+
// Save to IndexedDB
|
|
3755
|
+
await this.updateInstance(instance);
|
|
3756
|
+
return instance;
|
|
3757
|
+
}
|
|
3758
|
+
/**
|
|
3759
|
+
* Get workflow instance from IndexedDB.
|
|
3760
|
+
*/
|
|
3761
|
+
async getInstance(executionId) {
|
|
3762
|
+
return await this.db.instances.get(executionId) || null;
|
|
3763
|
+
}
|
|
3764
|
+
/**
|
|
3765
|
+
* Update workflow instance in IndexedDB.
|
|
3766
|
+
*/
|
|
3767
|
+
async updateInstance(instance) {
|
|
3768
|
+
instance.updatedAt = new Date().toISOString();
|
|
3769
|
+
await this.db.instances.update(instance.id, instance);
|
|
3770
|
+
}
|
|
3502
3771
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowExecutionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3503
3772
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowExecutionService }); }
|
|
3504
3773
|
}
|
|
@@ -3506,10 +3775,906 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
|
|
|
3506
3775
|
type: Injectable
|
|
3507
3776
|
}] });
|
|
3508
3777
|
|
|
3778
|
+
/**
|
|
3779
|
+
* Mock workflow definitions for testing and demonstration.
|
|
3780
|
+
*/
|
|
3781
|
+
const workflowDefinitionMock = [
|
|
3782
|
+
// Create User Workflow
|
|
3783
|
+
{
|
|
3784
|
+
$schema: 'https://elsaworkflows.io/schemas/workflow-definition/v3.0.0/schema.json',
|
|
3785
|
+
id: AXPDataGenerator.uuid(),
|
|
3786
|
+
definitionId: 'create-user-workflow',
|
|
3787
|
+
tenantId: null,
|
|
3788
|
+
name: 'Create User Workflow',
|
|
3789
|
+
description: 'Complete user registration workflow with permission check, form display, validation, and database save',
|
|
3790
|
+
createdAt: new Date().toISOString(),
|
|
3791
|
+
version: 1,
|
|
3792
|
+
toolVersion: '3.2.0.0',
|
|
3793
|
+
variables: [],
|
|
3794
|
+
inputs: [
|
|
3795
|
+
{
|
|
3796
|
+
type: 'String',
|
|
3797
|
+
name: 'currentUserId',
|
|
3798
|
+
displayName: 'Current User ID',
|
|
3799
|
+
description: 'ID of the user initiating the workflow',
|
|
3800
|
+
},
|
|
3801
|
+
],
|
|
3802
|
+
outputs: [
|
|
3803
|
+
{
|
|
3804
|
+
type: 'Object',
|
|
3805
|
+
name: 'createdUser',
|
|
3806
|
+
displayName: 'Created User',
|
|
3807
|
+
description: 'The newly created user object',
|
|
3808
|
+
},
|
|
3809
|
+
],
|
|
3810
|
+
outcomes: ['Done', 'NoPermission', 'Cancelled'],
|
|
3811
|
+
customProperties: {},
|
|
3812
|
+
isReadonly: false,
|
|
3813
|
+
isSystem: false,
|
|
3814
|
+
isLatest: true,
|
|
3815
|
+
isPublished: true,
|
|
3816
|
+
options: {
|
|
3817
|
+
usableAsActivity: false,
|
|
3818
|
+
autoUpdateConsumingWorkflows: false,
|
|
3819
|
+
},
|
|
3820
|
+
root: {
|
|
3821
|
+
id: 'root-flowchart',
|
|
3822
|
+
nodeId: 'root-flowchart',
|
|
3823
|
+
type: 'Elsa.Flowchart',
|
|
3824
|
+
version: 1,
|
|
3825
|
+
activities: [
|
|
3826
|
+
{
|
|
3827
|
+
id: 'check-permission',
|
|
3828
|
+
nodeId: 'check-permission',
|
|
3829
|
+
name: 'Check User Create Permission',
|
|
3830
|
+
type: 'Elsa.CheckPermission',
|
|
3831
|
+
version: 1,
|
|
3832
|
+
executionMode: 'backend',
|
|
3833
|
+
permission: {
|
|
3834
|
+
typeName: 'String',
|
|
3835
|
+
expression: {
|
|
3836
|
+
type: 'Literal',
|
|
3837
|
+
value: 'Users.Create',
|
|
3838
|
+
},
|
|
3839
|
+
},
|
|
3840
|
+
metadata: {
|
|
3841
|
+
designer: {
|
|
3842
|
+
position: {
|
|
3843
|
+
x: 100,
|
|
3844
|
+
y: 100,
|
|
3845
|
+
},
|
|
3846
|
+
},
|
|
3847
|
+
},
|
|
3848
|
+
},
|
|
3849
|
+
{
|
|
3850
|
+
id: 'show-error-toast',
|
|
3851
|
+
nodeId: 'show-error-toast',
|
|
3852
|
+
name: 'Show Permission Error',
|
|
3853
|
+
type: 'Elsa.ShowToast',
|
|
3854
|
+
version: 1,
|
|
3855
|
+
executionMode: 'frontend',
|
|
3856
|
+
message: {
|
|
3857
|
+
typeName: 'String',
|
|
3858
|
+
expression: {
|
|
3859
|
+
type: 'Literal',
|
|
3860
|
+
value: "You don't have permission to create users",
|
|
3861
|
+
},
|
|
3862
|
+
},
|
|
3863
|
+
type_: {
|
|
3864
|
+
typeName: 'String',
|
|
3865
|
+
expression: {
|
|
3866
|
+
type: 'Literal',
|
|
3867
|
+
value: 'error',
|
|
3868
|
+
},
|
|
3869
|
+
},
|
|
3870
|
+
metadata: {
|
|
3871
|
+
designer: {
|
|
3872
|
+
position: {
|
|
3873
|
+
x: 100,
|
|
3874
|
+
y: 250,
|
|
3875
|
+
},
|
|
3876
|
+
},
|
|
3877
|
+
},
|
|
3878
|
+
},
|
|
3879
|
+
{
|
|
3880
|
+
id: 'show-user-form',
|
|
3881
|
+
nodeId: 'show-user-form',
|
|
3882
|
+
name: 'Show User Registration Form',
|
|
3883
|
+
type: 'Elsa.ShowDialog',
|
|
3884
|
+
version: 1,
|
|
3885
|
+
executionMode: 'frontend',
|
|
3886
|
+
formDefinition: {
|
|
3887
|
+
typeName: 'String',
|
|
3888
|
+
expression: {
|
|
3889
|
+
type: 'Literal',
|
|
3890
|
+
value: 'user-create-form',
|
|
3891
|
+
},
|
|
3892
|
+
},
|
|
3893
|
+
title: {
|
|
3894
|
+
typeName: 'String',
|
|
3895
|
+
expression: {
|
|
3896
|
+
type: 'Literal',
|
|
3897
|
+
value: 'Create New User',
|
|
3898
|
+
},
|
|
3899
|
+
},
|
|
3900
|
+
metadata: {
|
|
3901
|
+
designer: {
|
|
3902
|
+
position: {
|
|
3903
|
+
x: 300,
|
|
3904
|
+
y: 100,
|
|
3905
|
+
},
|
|
3906
|
+
},
|
|
3907
|
+
},
|
|
3908
|
+
},
|
|
3909
|
+
{
|
|
3910
|
+
id: 'validate-email',
|
|
3911
|
+
nodeId: 'validate-email',
|
|
3912
|
+
name: 'Check Email Uniqueness',
|
|
3913
|
+
type: 'Elsa.ExecuteQuery',
|
|
3914
|
+
version: 1,
|
|
3915
|
+
executionMode: 'backend',
|
|
3916
|
+
queryKey: {
|
|
3917
|
+
typeName: 'String',
|
|
3918
|
+
expression: {
|
|
3919
|
+
type: 'Literal',
|
|
3920
|
+
value: 'User:CheckEmailExists',
|
|
3921
|
+
},
|
|
3922
|
+
},
|
|
3923
|
+
parameters: {
|
|
3924
|
+
typeName: 'Object',
|
|
3925
|
+
expression: {
|
|
3926
|
+
type: 'JavaScript',
|
|
3927
|
+
value: "{ email: getVariable('userEmail') }",
|
|
3928
|
+
},
|
|
3929
|
+
},
|
|
3930
|
+
metadata: {
|
|
3931
|
+
designer: {
|
|
3932
|
+
position: {
|
|
3933
|
+
x: 500,
|
|
3934
|
+
y: 100,
|
|
3935
|
+
},
|
|
3936
|
+
},
|
|
3937
|
+
},
|
|
3938
|
+
},
|
|
3939
|
+
{
|
|
3940
|
+
id: 'show-validation-error',
|
|
3941
|
+
nodeId: 'show-validation-error',
|
|
3942
|
+
name: 'Show Email Exists Error',
|
|
3943
|
+
type: 'Elsa.ShowToast',
|
|
3944
|
+
version: 1,
|
|
3945
|
+
executionMode: 'frontend',
|
|
3946
|
+
message: {
|
|
3947
|
+
typeName: 'String',
|
|
3948
|
+
expression: {
|
|
3949
|
+
type: 'Literal',
|
|
3950
|
+
value: 'Email already exists. Please use a different email.',
|
|
3951
|
+
},
|
|
3952
|
+
},
|
|
3953
|
+
type_: {
|
|
3954
|
+
typeName: 'String',
|
|
3955
|
+
expression: {
|
|
3956
|
+
type: 'Literal',
|
|
3957
|
+
value: 'error',
|
|
3958
|
+
},
|
|
3959
|
+
},
|
|
3960
|
+
metadata: {
|
|
3961
|
+
designer: {
|
|
3962
|
+
position: {
|
|
3963
|
+
x: 500,
|
|
3964
|
+
y: 250,
|
|
3965
|
+
},
|
|
3966
|
+
},
|
|
3967
|
+
},
|
|
3968
|
+
},
|
|
3969
|
+
{
|
|
3970
|
+
id: 'save-user',
|
|
3971
|
+
nodeId: 'save-user',
|
|
3972
|
+
name: 'Save User to Database',
|
|
3973
|
+
type: 'Elsa.ExecuteCommand',
|
|
3974
|
+
version: 1,
|
|
3975
|
+
executionMode: 'backend',
|
|
3976
|
+
commandKey: {
|
|
3977
|
+
typeName: 'String',
|
|
3978
|
+
expression: {
|
|
3979
|
+
type: 'Literal',
|
|
3980
|
+
value: 'User:Create',
|
|
3981
|
+
},
|
|
3982
|
+
},
|
|
3983
|
+
input: {
|
|
3984
|
+
typeName: 'Object',
|
|
3985
|
+
expression: {
|
|
3986
|
+
type: 'JavaScript',
|
|
3987
|
+
value: "{ email: getVariable('userEmail'), name: getVariable('userName'), role: getVariable('userRole') }",
|
|
3988
|
+
},
|
|
3989
|
+
},
|
|
3990
|
+
metadata: {
|
|
3991
|
+
designer: {
|
|
3992
|
+
position: {
|
|
3993
|
+
x: 700,
|
|
3994
|
+
y: 100,
|
|
3995
|
+
},
|
|
3996
|
+
},
|
|
3997
|
+
},
|
|
3998
|
+
},
|
|
3999
|
+
{
|
|
4000
|
+
id: 'show-success-toast',
|
|
4001
|
+
nodeId: 'show-success-toast',
|
|
4002
|
+
name: 'Show Success Message',
|
|
4003
|
+
type: 'Elsa.ShowToast',
|
|
4004
|
+
version: 1,
|
|
4005
|
+
executionMode: 'frontend',
|
|
4006
|
+
message: {
|
|
4007
|
+
typeName: 'String',
|
|
4008
|
+
expression: {
|
|
4009
|
+
type: 'Literal',
|
|
4010
|
+
value: 'User created successfully',
|
|
4011
|
+
},
|
|
4012
|
+
},
|
|
4013
|
+
type_: {
|
|
4014
|
+
typeName: 'String',
|
|
4015
|
+
expression: {
|
|
4016
|
+
type: 'Literal',
|
|
4017
|
+
value: 'success',
|
|
4018
|
+
},
|
|
4019
|
+
},
|
|
4020
|
+
metadata: {
|
|
4021
|
+
designer: {
|
|
4022
|
+
position: {
|
|
4023
|
+
x: 900,
|
|
4024
|
+
y: 100,
|
|
4025
|
+
},
|
|
4026
|
+
},
|
|
4027
|
+
},
|
|
4028
|
+
},
|
|
4029
|
+
],
|
|
4030
|
+
connections: [
|
|
4031
|
+
{
|
|
4032
|
+
source: {
|
|
4033
|
+
activity: 'check-permission',
|
|
4034
|
+
port: 'NoPermission',
|
|
4035
|
+
},
|
|
4036
|
+
target: {
|
|
4037
|
+
activity: 'show-error-toast',
|
|
4038
|
+
},
|
|
4039
|
+
},
|
|
4040
|
+
{
|
|
4041
|
+
source: {
|
|
4042
|
+
activity: 'check-permission',
|
|
4043
|
+
port: 'HasPermission',
|
|
4044
|
+
},
|
|
4045
|
+
target: {
|
|
4046
|
+
activity: 'show-user-form',
|
|
4047
|
+
},
|
|
4048
|
+
},
|
|
4049
|
+
{
|
|
4050
|
+
source: {
|
|
4051
|
+
activity: 'show-user-form',
|
|
4052
|
+
port: 'Submitted',
|
|
4053
|
+
},
|
|
4054
|
+
target: {
|
|
4055
|
+
activity: 'validate-email',
|
|
4056
|
+
},
|
|
4057
|
+
},
|
|
4058
|
+
{
|
|
4059
|
+
source: {
|
|
4060
|
+
activity: 'show-user-form',
|
|
4061
|
+
port: 'Cancelled',
|
|
4062
|
+
},
|
|
4063
|
+
target: {
|
|
4064
|
+
activity: 'show-error-toast',
|
|
4065
|
+
},
|
|
4066
|
+
},
|
|
4067
|
+
{
|
|
4068
|
+
source: {
|
|
4069
|
+
activity: 'validate-email',
|
|
4070
|
+
port: 'Exists',
|
|
4071
|
+
},
|
|
4072
|
+
target: {
|
|
4073
|
+
activity: 'show-validation-error',
|
|
4074
|
+
},
|
|
4075
|
+
},
|
|
4076
|
+
{
|
|
4077
|
+
source: {
|
|
4078
|
+
activity: 'show-validation-error',
|
|
4079
|
+
port: 'Done',
|
|
4080
|
+
},
|
|
4081
|
+
target: {
|
|
4082
|
+
activity: 'show-user-form',
|
|
4083
|
+
},
|
|
4084
|
+
},
|
|
4085
|
+
{
|
|
4086
|
+
source: {
|
|
4087
|
+
activity: 'validate-email',
|
|
4088
|
+
port: 'Valid',
|
|
4089
|
+
},
|
|
4090
|
+
target: {
|
|
4091
|
+
activity: 'save-user',
|
|
4092
|
+
},
|
|
4093
|
+
},
|
|
4094
|
+
{
|
|
4095
|
+
source: {
|
|
4096
|
+
activity: 'save-user',
|
|
4097
|
+
port: 'Done',
|
|
4098
|
+
},
|
|
4099
|
+
target: {
|
|
4100
|
+
activity: 'show-success-toast',
|
|
4101
|
+
},
|
|
4102
|
+
},
|
|
4103
|
+
],
|
|
4104
|
+
variables: [],
|
|
4105
|
+
},
|
|
4106
|
+
},
|
|
4107
|
+
// Simple Welcome Workflow
|
|
4108
|
+
{
|
|
4109
|
+
$schema: 'https://elsaworkflows.io/schemas/workflow-definition/v3.0.0/schema.json',
|
|
4110
|
+
id: AXPDataGenerator.uuid(),
|
|
4111
|
+
definitionId: 'welcome-workflow',
|
|
4112
|
+
tenantId: null,
|
|
4113
|
+
name: 'Welcome Workflow',
|
|
4114
|
+
description: 'Simple workflow to welcome new users',
|
|
4115
|
+
createdAt: new Date().toISOString(),
|
|
4116
|
+
version: 1,
|
|
4117
|
+
toolVersion: '3.2.0.0',
|
|
4118
|
+
variables: [],
|
|
4119
|
+
inputs: [
|
|
4120
|
+
{
|
|
4121
|
+
type: 'String',
|
|
4122
|
+
name: 'userName',
|
|
4123
|
+
displayName: 'User Name',
|
|
4124
|
+
description: 'Name of the user to welcome',
|
|
4125
|
+
},
|
|
4126
|
+
],
|
|
4127
|
+
outputs: [],
|
|
4128
|
+
outcomes: ['Done'],
|
|
4129
|
+
customProperties: {},
|
|
4130
|
+
isReadonly: false,
|
|
4131
|
+
isSystem: false,
|
|
4132
|
+
isLatest: true,
|
|
4133
|
+
isPublished: true,
|
|
4134
|
+
options: {
|
|
4135
|
+
usableAsActivity: false,
|
|
4136
|
+
autoUpdateConsumingWorkflows: false,
|
|
4137
|
+
},
|
|
4138
|
+
root: {
|
|
4139
|
+
id: 'root-flowchart',
|
|
4140
|
+
nodeId: 'root-flowchart',
|
|
4141
|
+
type: 'Elsa.Flowchart',
|
|
4142
|
+
version: 1,
|
|
4143
|
+
activities: [
|
|
4144
|
+
{
|
|
4145
|
+
id: 'welcome-toast',
|
|
4146
|
+
nodeId: 'welcome-toast',
|
|
4147
|
+
name: 'Show Welcome Message',
|
|
4148
|
+
type: 'Elsa.ShowToast',
|
|
4149
|
+
version: 1,
|
|
4150
|
+
executionMode: 'frontend',
|
|
4151
|
+
message: {
|
|
4152
|
+
typeName: 'String',
|
|
4153
|
+
expression: {
|
|
4154
|
+
type: 'JavaScript',
|
|
4155
|
+
value: "'Welcome ' + getInput('userName') + '!'",
|
|
4156
|
+
},
|
|
4157
|
+
},
|
|
4158
|
+
type_: {
|
|
4159
|
+
typeName: 'String',
|
|
4160
|
+
expression: {
|
|
4161
|
+
type: 'Literal',
|
|
4162
|
+
value: 'success',
|
|
4163
|
+
},
|
|
4164
|
+
},
|
|
4165
|
+
metadata: {
|
|
4166
|
+
designer: {
|
|
4167
|
+
position: {
|
|
4168
|
+
x: 100,
|
|
4169
|
+
y: 100,
|
|
4170
|
+
},
|
|
4171
|
+
},
|
|
4172
|
+
},
|
|
4173
|
+
},
|
|
4174
|
+
],
|
|
4175
|
+
connections: [],
|
|
4176
|
+
variables: [],
|
|
4177
|
+
},
|
|
4178
|
+
},
|
|
4179
|
+
// Data Processing Workflow
|
|
4180
|
+
{
|
|
4181
|
+
$schema: 'https://elsaworkflows.io/schemas/workflow-definition/v3.0.0/schema.json',
|
|
4182
|
+
id: AXPDataGenerator.uuid(),
|
|
4183
|
+
definitionId: 'data-processing-workflow',
|
|
4184
|
+
tenantId: null,
|
|
4185
|
+
name: 'Data Processing Workflow',
|
|
4186
|
+
description: 'Backend workflow for data processing and validation',
|
|
4187
|
+
createdAt: new Date().toISOString(),
|
|
4188
|
+
version: 1,
|
|
4189
|
+
toolVersion: '3.2.0.0',
|
|
4190
|
+
variables: [],
|
|
4191
|
+
inputs: [
|
|
4192
|
+
{
|
|
4193
|
+
type: 'Object',
|
|
4194
|
+
name: 'data',
|
|
4195
|
+
displayName: 'Data',
|
|
4196
|
+
description: 'Data to process',
|
|
4197
|
+
},
|
|
4198
|
+
],
|
|
4199
|
+
outputs: [
|
|
4200
|
+
{
|
|
4201
|
+
type: 'Object',
|
|
4202
|
+
name: 'processedData',
|
|
4203
|
+
displayName: 'Processed Data',
|
|
4204
|
+
description: 'Processed data result',
|
|
4205
|
+
},
|
|
4206
|
+
],
|
|
4207
|
+
outcomes: ['Done', 'Failed'],
|
|
4208
|
+
customProperties: {},
|
|
4209
|
+
isReadonly: false,
|
|
4210
|
+
isSystem: false,
|
|
4211
|
+
isLatest: true,
|
|
4212
|
+
isPublished: true,
|
|
4213
|
+
options: {
|
|
4214
|
+
usableAsActivity: false,
|
|
4215
|
+
autoUpdateConsumingWorkflows: false,
|
|
4216
|
+
},
|
|
4217
|
+
root: {
|
|
4218
|
+
id: 'root-flowchart',
|
|
4219
|
+
nodeId: 'root-flowchart',
|
|
4220
|
+
type: 'Elsa.Flowchart',
|
|
4221
|
+
version: 1,
|
|
4222
|
+
activities: [
|
|
4223
|
+
{
|
|
4224
|
+
id: 'validate-data',
|
|
4225
|
+
nodeId: 'validate-data',
|
|
4226
|
+
name: 'Validate Data',
|
|
4227
|
+
type: 'Elsa.ExecuteQuery',
|
|
4228
|
+
version: 1,
|
|
4229
|
+
executionMode: 'backend',
|
|
4230
|
+
queryKey: {
|
|
4231
|
+
typeName: 'String',
|
|
4232
|
+
expression: {
|
|
4233
|
+
type: 'Literal',
|
|
4234
|
+
value: 'Data:Validate',
|
|
4235
|
+
},
|
|
4236
|
+
},
|
|
4237
|
+
parameters: {
|
|
4238
|
+
typeName: 'Object',
|
|
4239
|
+
expression: {
|
|
4240
|
+
type: 'JavaScript',
|
|
4241
|
+
value: "{ data: getInput('data') }",
|
|
4242
|
+
},
|
|
4243
|
+
},
|
|
4244
|
+
metadata: {
|
|
4245
|
+
designer: {
|
|
4246
|
+
position: {
|
|
4247
|
+
x: 100,
|
|
4248
|
+
y: 100,
|
|
4249
|
+
},
|
|
4250
|
+
},
|
|
4251
|
+
},
|
|
4252
|
+
},
|
|
4253
|
+
{
|
|
4254
|
+
id: 'process-data',
|
|
4255
|
+
nodeId: 'process-data',
|
|
4256
|
+
name: 'Process Data',
|
|
4257
|
+
type: 'Elsa.ExecuteCommand',
|
|
4258
|
+
version: 1,
|
|
4259
|
+
executionMode: 'backend',
|
|
4260
|
+
commandKey: {
|
|
4261
|
+
typeName: 'String',
|
|
4262
|
+
expression: {
|
|
4263
|
+
type: 'Literal',
|
|
4264
|
+
value: 'Data:Process',
|
|
4265
|
+
},
|
|
4266
|
+
},
|
|
4267
|
+
input: {
|
|
4268
|
+
typeName: 'Object',
|
|
4269
|
+
expression: {
|
|
4270
|
+
type: 'JavaScript',
|
|
4271
|
+
value: "{ data: getInput('data') }",
|
|
4272
|
+
},
|
|
4273
|
+
},
|
|
4274
|
+
metadata: {
|
|
4275
|
+
designer: {
|
|
4276
|
+
position: {
|
|
4277
|
+
x: 300,
|
|
4278
|
+
y: 100,
|
|
4279
|
+
},
|
|
4280
|
+
},
|
|
4281
|
+
},
|
|
4282
|
+
},
|
|
4283
|
+
],
|
|
4284
|
+
connections: [
|
|
4285
|
+
{
|
|
4286
|
+
source: {
|
|
4287
|
+
activity: 'validate-data',
|
|
4288
|
+
port: 'Valid',
|
|
4289
|
+
},
|
|
4290
|
+
target: {
|
|
4291
|
+
activity: 'process-data',
|
|
4292
|
+
},
|
|
4293
|
+
},
|
|
4294
|
+
],
|
|
4295
|
+
variables: [],
|
|
4296
|
+
},
|
|
4297
|
+
},
|
|
4298
|
+
];
|
|
4299
|
+
/**
|
|
4300
|
+
* Export definitionId list for easy access
|
|
4301
|
+
*/
|
|
4302
|
+
const workflowDefinitionIds = {
|
|
4303
|
+
createUser: 'create-user-workflow',
|
|
4304
|
+
welcome: 'welcome-workflow',
|
|
4305
|
+
dataProcessing: 'data-processing-workflow',
|
|
4306
|
+
};
|
|
4307
|
+
|
|
4308
|
+
/**
|
|
4309
|
+
* Seeds workflow definitions into localStorage for mock/demo purposes.
|
|
4310
|
+
*
|
|
4311
|
+
* Workflow definitions are stored in localStorage with key pattern:
|
|
4312
|
+
* `workflow:{definitionId}`
|
|
4313
|
+
*
|
|
4314
|
+
* This allows the mock workflow execution service to retrieve definitions
|
|
4315
|
+
* without making HTTP calls.
|
|
4316
|
+
*/
|
|
4317
|
+
let AXCWorkflowDefinitionDataSeeder$1 = class AXCWorkflowDefinitionDataSeeder {
|
|
4318
|
+
constructor() {
|
|
4319
|
+
this.storageService = inject(AXPEntityStorageService);
|
|
4320
|
+
}
|
|
4321
|
+
async seed() {
|
|
4322
|
+
// Store each workflow definition in localStorage
|
|
4323
|
+
for (const workflow of workflowDefinitionMock) {
|
|
4324
|
+
localStorage.setItem(`workflow:${workflow.definitionId}`, JSON.stringify(workflow));
|
|
4325
|
+
console.log(`[WorkflowDefinitionSeeder] Seeded workflow: ${workflow.name} (${workflow.definitionId})`);
|
|
4326
|
+
}
|
|
4327
|
+
// Also store in entity storage for entity-based access
|
|
4328
|
+
await this.storageService.initial('Workflow.WorkflowDefinition', workflowDefinitionMock);
|
|
4329
|
+
console.log(`[WorkflowDefinitionSeeder] Successfully seeded ${workflowDefinitionMock.length} workflow definitions`);
|
|
4330
|
+
}
|
|
4331
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowDefinitionDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4332
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowDefinitionDataSeeder }); }
|
|
4333
|
+
};
|
|
4334
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowDefinitionDataSeeder$1, decorators: [{
|
|
4335
|
+
type: Injectable
|
|
4336
|
+
}] });
|
|
4337
|
+
|
|
4338
|
+
//#endregion
|
|
4339
|
+
/**
|
|
4340
|
+
* CheckPermission Activity (Backend)
|
|
4341
|
+
*
|
|
4342
|
+
* Checks if a user has specific permission.
|
|
4343
|
+
* This is a mock implementation that always grants permission for demo purposes.
|
|
4344
|
+
*
|
|
4345
|
+
* In production, this would check against real permission system.
|
|
4346
|
+
*
|
|
4347
|
+
* Execution Mode: backend
|
|
4348
|
+
* Activity Type: workflow-activity:check-permission
|
|
4349
|
+
*
|
|
4350
|
+
* Outcomes:
|
|
4351
|
+
* - HasPermission: User has the permission
|
|
4352
|
+
* - NoPermission: User does not have the permission
|
|
4353
|
+
*/
|
|
4354
|
+
class CheckPermissionActivity {
|
|
4355
|
+
//#region ---- AXPCommand Implementation ----
|
|
4356
|
+
async execute(input) {
|
|
4357
|
+
// Mock implementation: always grant permission for demo
|
|
4358
|
+
// In production, check against permission service
|
|
4359
|
+
const hasPermission = true; // TODO: Integrate with real permission system
|
|
4360
|
+
const output = {
|
|
4361
|
+
hasPermission,
|
|
4362
|
+
userId: input.userId || 'current-user',
|
|
4363
|
+
permission: input.permission,
|
|
4364
|
+
};
|
|
4365
|
+
// Determine outcome based on permission check
|
|
4366
|
+
const outcomes = hasPermission
|
|
4367
|
+
? { HasPermission: true }
|
|
4368
|
+
: { NoPermission: true };
|
|
4369
|
+
console.log(`[CheckPermissionActivity] Checked permission '${input.permission}' for user '${output.userId}': ${hasPermission ? 'GRANTED' : 'DENIED'}`);
|
|
4370
|
+
return {
|
|
4371
|
+
output,
|
|
4372
|
+
outcomes,
|
|
4373
|
+
};
|
|
4374
|
+
}
|
|
4375
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: CheckPermissionActivity, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4376
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: CheckPermissionActivity }); }
|
|
4377
|
+
}
|
|
4378
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: CheckPermissionActivity, decorators: [{
|
|
4379
|
+
type: Injectable
|
|
4380
|
+
}] });
|
|
4381
|
+
|
|
4382
|
+
//#endregion
|
|
4383
|
+
/**
|
|
4384
|
+
* ExecuteQuery Activity (Backend)
|
|
4385
|
+
*
|
|
4386
|
+
* Executes a query operation.
|
|
4387
|
+
* This is a mock implementation that simulates common queries.
|
|
4388
|
+
*
|
|
4389
|
+
* Execution Mode: backend
|
|
4390
|
+
* Activity Type: workflow-activity:execute-query
|
|
4391
|
+
*
|
|
4392
|
+
* Outcomes:
|
|
4393
|
+
* - Done: Query executed successfully
|
|
4394
|
+
* - Valid: Data is valid (for validation queries)
|
|
4395
|
+
* - Exists: Data exists (for existence checks)
|
|
4396
|
+
* - NotFound: Data not found
|
|
4397
|
+
* - Failed: Query execution failed
|
|
4398
|
+
*/
|
|
4399
|
+
class ExecuteQueryActivity {
|
|
4400
|
+
constructor() {
|
|
4401
|
+
//#region ---- Services ----
|
|
4402
|
+
this.storageService = inject(AXPEntityStorageService);
|
|
4403
|
+
}
|
|
4404
|
+
//#endregion
|
|
4405
|
+
//#region ---- AXPCommand Implementation ----
|
|
4406
|
+
async execute(input) {
|
|
4407
|
+
try {
|
|
4408
|
+
console.log(`[ExecuteQueryActivity] Executing query '${input.queryKey}' with parameters:`, input.parameters);
|
|
4409
|
+
// Route to appropriate query handler based on queryKey
|
|
4410
|
+
const result = await this.routeQuery(input.queryKey, input.parameters || {});
|
|
4411
|
+
return result;
|
|
4412
|
+
}
|
|
4413
|
+
catch (error) {
|
|
4414
|
+
console.error(`[ExecuteQueryActivity] Query '${input.queryKey}' failed:`, error);
|
|
4415
|
+
return {
|
|
4416
|
+
output: {
|
|
4417
|
+
data: null,
|
|
4418
|
+
success: false,
|
|
4419
|
+
error: error.message || 'Unknown error',
|
|
4420
|
+
},
|
|
4421
|
+
outcomes: {
|
|
4422
|
+
Failed: true,
|
|
4423
|
+
},
|
|
4424
|
+
};
|
|
4425
|
+
}
|
|
4426
|
+
}
|
|
4427
|
+
//#endregion
|
|
4428
|
+
//#region ---- Query Routing ----
|
|
4429
|
+
/**
|
|
4430
|
+
* Routes query to appropriate handler based on queryKey.
|
|
4431
|
+
*/
|
|
4432
|
+
async routeQuery(queryKey, parameters) {
|
|
4433
|
+
switch (queryKey) {
|
|
4434
|
+
case 'User:CheckEmailExists':
|
|
4435
|
+
return await this.checkEmailExists(parameters);
|
|
4436
|
+
case 'Data:Validate':
|
|
4437
|
+
return await this.validateData(parameters);
|
|
4438
|
+
default:
|
|
4439
|
+
// Mock: return empty result for unknown queries
|
|
4440
|
+
console.warn(`[ExecuteQueryActivity] Unknown query key: ${queryKey}`);
|
|
4441
|
+
return {
|
|
4442
|
+
output: {
|
|
4443
|
+
data: null,
|
|
4444
|
+
success: true,
|
|
4445
|
+
},
|
|
4446
|
+
outcomes: {
|
|
4447
|
+
Done: true,
|
|
4448
|
+
},
|
|
4449
|
+
};
|
|
4450
|
+
}
|
|
4451
|
+
}
|
|
4452
|
+
//#endregion
|
|
4453
|
+
//#region ---- Query Handlers ----
|
|
4454
|
+
/**
|
|
4455
|
+
* Checks if email already exists in database.
|
|
4456
|
+
*/
|
|
4457
|
+
async checkEmailExists(parameters) {
|
|
4458
|
+
const email = parameters['email'] || parameters['userEmail'];
|
|
4459
|
+
// Mock implementation: randomly decide if email exists
|
|
4460
|
+
// In production, check against real database
|
|
4461
|
+
const exists = Math.random() > 0.8; // 20% chance email exists
|
|
4462
|
+
console.log(`[ExecuteQueryActivity] Checking email '${email}': ${exists ? 'EXISTS' : 'AVAILABLE'}`);
|
|
4463
|
+
const outcome = exists ? 'Exists' : 'Valid';
|
|
4464
|
+
return {
|
|
4465
|
+
output: {
|
|
4466
|
+
data: {
|
|
4467
|
+
email,
|
|
4468
|
+
exists,
|
|
4469
|
+
available: !exists,
|
|
4470
|
+
},
|
|
4471
|
+
success: true,
|
|
4472
|
+
},
|
|
4473
|
+
outcomes: {
|
|
4474
|
+
[outcome]: true,
|
|
4475
|
+
Done: true,
|
|
4476
|
+
},
|
|
4477
|
+
};
|
|
4478
|
+
}
|
|
4479
|
+
/**
|
|
4480
|
+
* Validates data structure and content.
|
|
4481
|
+
*/
|
|
4482
|
+
async validateData(parameters) {
|
|
4483
|
+
const data = parameters['data'];
|
|
4484
|
+
// Mock validation: check if data exists and has content
|
|
4485
|
+
const isValid = data && Object.keys(data).length > 0;
|
|
4486
|
+
console.log(`[ExecuteQueryActivity] Validating data: ${isValid ? 'VALID' : 'INVALID'}`);
|
|
4487
|
+
const outcome = isValid ? 'Valid' : 'Invalid';
|
|
4488
|
+
return {
|
|
4489
|
+
output: {
|
|
4490
|
+
data: {
|
|
4491
|
+
valid: isValid,
|
|
4492
|
+
errors: isValid ? [] : ['Data is empty or invalid'],
|
|
4493
|
+
},
|
|
4494
|
+
success: true,
|
|
4495
|
+
},
|
|
4496
|
+
outcomes: {
|
|
4497
|
+
[outcome]: true,
|
|
4498
|
+
Done: true,
|
|
4499
|
+
},
|
|
4500
|
+
};
|
|
4501
|
+
}
|
|
4502
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ExecuteQueryActivity, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4503
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ExecuteQueryActivity }); }
|
|
4504
|
+
}
|
|
4505
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ExecuteQueryActivity, decorators: [{
|
|
4506
|
+
type: Injectable
|
|
4507
|
+
}] });
|
|
4508
|
+
|
|
4509
|
+
//#endregion
|
|
4510
|
+
/**
|
|
4511
|
+
* ExecuteCommand Activity (Backend)
|
|
4512
|
+
*
|
|
4513
|
+
* Executes a command operation.
|
|
4514
|
+
* This is a mock implementation that simulates common commands.
|
|
4515
|
+
*
|
|
4516
|
+
* Execution Mode: backend
|
|
4517
|
+
* Activity Type: workflow-activity:execute-command
|
|
4518
|
+
*
|
|
4519
|
+
* Outcomes:
|
|
4520
|
+
* - Done: Command executed successfully
|
|
4521
|
+
* - Failed: Command execution failed
|
|
4522
|
+
*/
|
|
4523
|
+
class ExecuteCommandActivity {
|
|
4524
|
+
constructor() {
|
|
4525
|
+
//#region ---- Services ----
|
|
4526
|
+
this.storageService = inject(AXPEntityStorageService);
|
|
4527
|
+
}
|
|
4528
|
+
//#endregion
|
|
4529
|
+
//#region ---- AXPCommand Implementation ----
|
|
4530
|
+
async execute(input) {
|
|
4531
|
+
try {
|
|
4532
|
+
console.log(`[ExecuteCommandActivity] Executing command '${input.commandKey}' with input:`, input.input);
|
|
4533
|
+
// Route to appropriate command handler based on commandKey
|
|
4534
|
+
const result = await this.routeCommand(input.commandKey, input.input || {});
|
|
4535
|
+
return result;
|
|
4536
|
+
}
|
|
4537
|
+
catch (error) {
|
|
4538
|
+
console.error(`[ExecuteCommandActivity] Command '${input.commandKey}' failed:`, error);
|
|
4539
|
+
return {
|
|
4540
|
+
output: {
|
|
4541
|
+
result: null,
|
|
4542
|
+
success: false,
|
|
4543
|
+
error: error.message || 'Unknown error',
|
|
4544
|
+
},
|
|
4545
|
+
outcomes: {
|
|
4546
|
+
Failed: true,
|
|
4547
|
+
},
|
|
4548
|
+
};
|
|
4549
|
+
}
|
|
4550
|
+
}
|
|
4551
|
+
//#endregion
|
|
4552
|
+
//#region ---- Command Routing ----
|
|
4553
|
+
/**
|
|
4554
|
+
* Routes command to appropriate handler based on commandKey.
|
|
4555
|
+
*/
|
|
4556
|
+
async routeCommand(commandKey, input) {
|
|
4557
|
+
switch (commandKey) {
|
|
4558
|
+
case 'User:Create':
|
|
4559
|
+
return await this.createUser(input);
|
|
4560
|
+
case 'Data:Process':
|
|
4561
|
+
return await this.processData(input);
|
|
4562
|
+
default:
|
|
4563
|
+
// Mock: return success for unknown commands
|
|
4564
|
+
console.warn(`[ExecuteCommandActivity] Unknown command key: ${commandKey}`);
|
|
4565
|
+
return {
|
|
4566
|
+
output: {
|
|
4567
|
+
result: { success: true },
|
|
4568
|
+
success: true,
|
|
4569
|
+
},
|
|
4570
|
+
outcomes: {
|
|
4571
|
+
Done: true,
|
|
4572
|
+
},
|
|
4573
|
+
};
|
|
4574
|
+
}
|
|
4575
|
+
}
|
|
4576
|
+
//#endregion
|
|
4577
|
+
//#region ---- Command Handlers ----
|
|
4578
|
+
/**
|
|
4579
|
+
* Creates a new user in the system.
|
|
4580
|
+
*/
|
|
4581
|
+
async createUser(input) {
|
|
4582
|
+
// Extract user data from input
|
|
4583
|
+
const email = input['email'] || input['userEmail'];
|
|
4584
|
+
const name = input['name'] || input['userName'] || 'New User';
|
|
4585
|
+
const role = input['role'] || input['userRole'] || 'User';
|
|
4586
|
+
// Create new user object
|
|
4587
|
+
const userId = AXPDataGenerator.uuid();
|
|
4588
|
+
const newUser = {
|
|
4589
|
+
id: userId,
|
|
4590
|
+
email,
|
|
4591
|
+
name,
|
|
4592
|
+
role,
|
|
4593
|
+
createdAt: new Date().toISOString(),
|
|
4594
|
+
isActive: true,
|
|
4595
|
+
};
|
|
4596
|
+
console.log(`[ExecuteCommandActivity] Creating user:`, newUser);
|
|
4597
|
+
// In production, save to database via EntityStorageService or API
|
|
4598
|
+
// For mock, we'll just simulate success
|
|
4599
|
+
// await this.storageService.create('User', newUser);
|
|
4600
|
+
return {
|
|
4601
|
+
output: {
|
|
4602
|
+
result: newUser,
|
|
4603
|
+
success: true,
|
|
4604
|
+
entityId: userId,
|
|
4605
|
+
},
|
|
4606
|
+
outcomes: {
|
|
4607
|
+
Done: true,
|
|
4608
|
+
},
|
|
4609
|
+
};
|
|
4610
|
+
}
|
|
4611
|
+
/**
|
|
4612
|
+
* Processes data according to business rules.
|
|
4613
|
+
*/
|
|
4614
|
+
async processData(input) {
|
|
4615
|
+
const data = input['data'];
|
|
4616
|
+
// Mock processing: just add timestamp and processed flag
|
|
4617
|
+
const processedData = {
|
|
4618
|
+
...data,
|
|
4619
|
+
processed: true,
|
|
4620
|
+
processedAt: new Date().toISOString(),
|
|
4621
|
+
};
|
|
4622
|
+
console.log(`[ExecuteCommandActivity] Processed data:`, processedData);
|
|
4623
|
+
return {
|
|
4624
|
+
output: {
|
|
4625
|
+
result: processedData,
|
|
4626
|
+
success: true,
|
|
4627
|
+
},
|
|
4628
|
+
outcomes: {
|
|
4629
|
+
Done: true,
|
|
4630
|
+
},
|
|
4631
|
+
};
|
|
4632
|
+
}
|
|
4633
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ExecuteCommandActivity, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4634
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ExecuteCommandActivity }); }
|
|
4635
|
+
}
|
|
4636
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ExecuteCommandActivity, decorators: [{
|
|
4637
|
+
type: Injectable
|
|
4638
|
+
}] });
|
|
4639
|
+
|
|
4640
|
+
/**
|
|
4641
|
+
* Provides all backend workflow activities as Commands.
|
|
4642
|
+
*
|
|
4643
|
+
* These activities are registered with the CommandBus and can be executed
|
|
4644
|
+
* by the workflow execution service.
|
|
4645
|
+
*
|
|
4646
|
+
* Usage:
|
|
4647
|
+
* ```typescript
|
|
4648
|
+
* @NgModule({
|
|
4649
|
+
* providers: [
|
|
4650
|
+
* provideWorkflowActivities(),
|
|
4651
|
+
* ]
|
|
4652
|
+
* })
|
|
4653
|
+
* export class AppModule {}
|
|
4654
|
+
* ```
|
|
4655
|
+
*/
|
|
4656
|
+
function provideWorkflowActivities() {
|
|
4657
|
+
return provideCommandSetups([
|
|
4658
|
+
{
|
|
4659
|
+
key: 'workflow-activity:check-permission',
|
|
4660
|
+
command: () => CheckPermissionActivity,
|
|
4661
|
+
},
|
|
4662
|
+
{
|
|
4663
|
+
key: 'workflow-activity:execute-query',
|
|
4664
|
+
command: () => ExecuteQueryActivity,
|
|
4665
|
+
},
|
|
4666
|
+
{
|
|
4667
|
+
key: 'workflow-activity:execute-command',
|
|
4668
|
+
command: () => ExecuteCommandActivity,
|
|
4669
|
+
},
|
|
4670
|
+
]);
|
|
4671
|
+
}
|
|
4672
|
+
|
|
3509
4673
|
class AXCCommonMockModule {
|
|
3510
4674
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCommonMockModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
3511
4675
|
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.10", ngImport: i0, type: AXCCommonMockModule }); }
|
|
3512
4676
|
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCommonMockModule, providers: [
|
|
4677
|
+
provideWorkflowActivities(),
|
|
3513
4678
|
{
|
|
3514
4679
|
provide: AXP_ACTIVITY_LOG_PROVIDER,
|
|
3515
4680
|
useClass: AXCPActivityLogService,
|
|
@@ -3530,7 +4695,7 @@ class AXCCommonMockModule {
|
|
|
3530
4695
|
},
|
|
3531
4696
|
{
|
|
3532
4697
|
provide: AXPVersioningService,
|
|
3533
|
-
useClass:
|
|
4698
|
+
useClass: AXCVersioningService,
|
|
3534
4699
|
},
|
|
3535
4700
|
{
|
|
3536
4701
|
provide: AXP_ACTIVITY_CATEGORY_PROVIDER,
|
|
@@ -3546,6 +4711,11 @@ class AXCCommonMockModule {
|
|
|
3546
4711
|
provide: AXPWorkflowExecutionService,
|
|
3547
4712
|
useClass: AXCWorkflowExecutionService,
|
|
3548
4713
|
},
|
|
4714
|
+
{
|
|
4715
|
+
provide: AXP_DATA_SEEDER_TOKEN,
|
|
4716
|
+
useClass: AXCWorkflowDefinitionDataSeeder$1,
|
|
4717
|
+
multi: true,
|
|
4718
|
+
},
|
|
3549
4719
|
] }); }
|
|
3550
4720
|
}
|
|
3551
4721
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCommonMockModule, decorators: [{
|
|
@@ -3555,6 +4725,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
|
|
|
3555
4725
|
exports: [],
|
|
3556
4726
|
declarations: [],
|
|
3557
4727
|
providers: [
|
|
4728
|
+
provideWorkflowActivities(),
|
|
3558
4729
|
{
|
|
3559
4730
|
provide: AXP_ACTIVITY_LOG_PROVIDER,
|
|
3560
4731
|
useClass: AXCPActivityLogService,
|
|
@@ -3575,7 +4746,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
|
|
|
3575
4746
|
},
|
|
3576
4747
|
{
|
|
3577
4748
|
provide: AXPVersioningService,
|
|
3578
|
-
useClass:
|
|
4749
|
+
useClass: AXCVersioningService,
|
|
3579
4750
|
},
|
|
3580
4751
|
{
|
|
3581
4752
|
provide: AXP_ACTIVITY_CATEGORY_PROVIDER,
|
|
@@ -3591,6 +4762,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
|
|
|
3591
4762
|
provide: AXPWorkflowExecutionService,
|
|
3592
4763
|
useClass: AXCWorkflowExecutionService,
|
|
3593
4764
|
},
|
|
4765
|
+
{
|
|
4766
|
+
provide: AXP_DATA_SEEDER_TOKEN,
|
|
4767
|
+
useClass: AXCWorkflowDefinitionDataSeeder$1,
|
|
4768
|
+
multi: true,
|
|
4769
|
+
},
|
|
3594
4770
|
],
|
|
3595
4771
|
}]
|
|
3596
4772
|
}] });
|
|
@@ -37463,6 +38639,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
|
|
|
37463
38639
|
}]
|
|
37464
38640
|
}] });
|
|
37465
38641
|
|
|
38642
|
+
/**
|
|
38643
|
+
* Mock workflow definition entities for the entity list.
|
|
38644
|
+
*/
|
|
38645
|
+
const workflowDefinitionEntityMock = workflowDefinitionMock.map((def) => ({
|
|
38646
|
+
id: def.id,
|
|
38647
|
+
definitionId: def.definitionId,
|
|
38648
|
+
name: def.name || 'Unnamed Workflow',
|
|
38649
|
+
description: def.description || undefined,
|
|
38650
|
+
version: def.version,
|
|
38651
|
+
isLatest: def.isLatest,
|
|
38652
|
+
isPublished: def.isPublished,
|
|
38653
|
+
isReadonly: def.isReadonly,
|
|
38654
|
+
isSystem: def.isSystem,
|
|
38655
|
+
createdAt: def.createdAt,
|
|
38656
|
+
workflowDefinition: def,
|
|
38657
|
+
}));
|
|
38658
|
+
|
|
38659
|
+
class AXCWorkflowDefinitionDataSeeder {
|
|
38660
|
+
constructor() {
|
|
38661
|
+
this.storageService = inject(AXPEntityStorageService);
|
|
38662
|
+
}
|
|
38663
|
+
async seed() {
|
|
38664
|
+
await this.storageService.initial(`${RootConfig$m.module.name}.${RootConfig$m.entities.workflowDefinition.name}`, workflowDefinitionEntityMock);
|
|
38665
|
+
console.log(`[WorkflowDefinitionSeeder] Seeded ${workflowDefinitionEntityMock.length} workflow definitions`);
|
|
38666
|
+
}
|
|
38667
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowDefinitionDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
38668
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowDefinitionDataSeeder }); }
|
|
38669
|
+
}
|
|
38670
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowDefinitionDataSeeder, decorators: [{
|
|
38671
|
+
type: Injectable
|
|
38672
|
+
}] });
|
|
38673
|
+
|
|
37466
38674
|
class AXCWorkflowManagementMockModule {
|
|
37467
38675
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowManagementMockModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
37468
38676
|
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowManagementMockModule }); }
|
|
@@ -37473,16 +38681,11 @@ class AXCWorkflowManagementMockModule {
|
|
|
37473
38681
|
command: () => import('./acorex-connectivity-mock-distribution-record.command-w3zoeELy.mjs').then((c) => c.AXCDistributionCommand),
|
|
37474
38682
|
},
|
|
37475
38683
|
]),
|
|
37476
|
-
|
|
37477
|
-
|
|
37478
|
-
|
|
37479
|
-
|
|
37480
|
-
|
|
37481
|
-
// {
|
|
37482
|
-
// provide: AXP_WORKFLOW_TASK_PROVIDER,
|
|
37483
|
-
// useClass: AXPTaskBoardPlatformManagementTaskProvider,
|
|
37484
|
-
// multi: true,
|
|
37485
|
-
// },
|
|
38684
|
+
{
|
|
38685
|
+
provide: AXP_DATA_SEEDER_TOKEN,
|
|
38686
|
+
useClass: AXCWorkflowDefinitionDataSeeder,
|
|
38687
|
+
multi: true,
|
|
38688
|
+
},
|
|
37486
38689
|
] }); }
|
|
37487
38690
|
}
|
|
37488
38691
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowManagementMockModule, decorators: [{
|
|
@@ -37498,16 +38701,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
|
|
|
37498
38701
|
command: () => import('./acorex-connectivity-mock-distribution-record.command-w3zoeELy.mjs').then((c) => c.AXCDistributionCommand),
|
|
37499
38702
|
},
|
|
37500
38703
|
]),
|
|
37501
|
-
|
|
37502
|
-
|
|
37503
|
-
|
|
37504
|
-
|
|
37505
|
-
|
|
37506
|
-
// {
|
|
37507
|
-
// provide: AXP_WORKFLOW_TASK_PROVIDER,
|
|
37508
|
-
// useClass: AXPTaskBoardPlatformManagementTaskProvider,
|
|
37509
|
-
// multi: true,
|
|
37510
|
-
// },
|
|
38704
|
+
{
|
|
38705
|
+
provide: AXP_DATA_SEEDER_TOKEN,
|
|
38706
|
+
useClass: AXCWorkflowDefinitionDataSeeder,
|
|
38707
|
+
multi: true,
|
|
38708
|
+
},
|
|
37511
38709
|
],
|
|
37512
38710
|
}]
|
|
37513
38711
|
}] });
|
|
@@ -38870,7 +40068,7 @@ class AXCApplicationDataSeeder {
|
|
|
38870
40068
|
this.storageService = inject(AXPEntityStorageService);
|
|
38871
40069
|
}
|
|
38872
40070
|
async seed() {
|
|
38873
|
-
await this.storageService.initial(`${RootConfig$
|
|
40071
|
+
await this.storageService.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.application.name}`, APPLICATIONS);
|
|
38874
40072
|
}
|
|
38875
40073
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCApplicationDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
38876
40074
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCApplicationDataSeeder }); }
|
|
@@ -38884,7 +40082,7 @@ class AXCEditionDataSeeder {
|
|
|
38884
40082
|
this.storageService = inject(AXPEntityStorageService);
|
|
38885
40083
|
}
|
|
38886
40084
|
async seed() {
|
|
38887
|
-
await this.storageService.initial(`${RootConfig$
|
|
40085
|
+
await this.storageService.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.edition.name}`, EDITIONS);
|
|
38888
40086
|
}
|
|
38889
40087
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCEditionDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
38890
40088
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCEditionDataSeeder }); }
|
|
@@ -38898,7 +40096,7 @@ class AXCFeatureDataSeeder {
|
|
|
38898
40096
|
this.storageService = inject(AXPEntityStorageService);
|
|
38899
40097
|
}
|
|
38900
40098
|
async seed() {
|
|
38901
|
-
await this.storageService.initial(`${RootConfig$
|
|
40099
|
+
await this.storageService.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.feature.name}`, FEATURES);
|
|
38902
40100
|
}
|
|
38903
40101
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCFeatureDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
38904
40102
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCFeatureDataSeeder }); }
|
|
@@ -38912,7 +40110,7 @@ class AXCModuleDataSeeder {
|
|
|
38912
40110
|
this.storageService = inject(AXPEntityStorageService);
|
|
38913
40111
|
}
|
|
38914
40112
|
async seed() {
|
|
38915
|
-
await this.storageService.initial(`${RootConfig$
|
|
40113
|
+
await this.storageService.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.module.name}`, MODULES);
|
|
38916
40114
|
}
|
|
38917
40115
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCModuleDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
38918
40116
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCModuleDataSeeder }); }
|
|
@@ -39195,7 +40393,7 @@ class AXMQuestionBankItemCategoryDataSeeder {
|
|
|
39195
40393
|
this.storage = inject(AXPEntityStorageService);
|
|
39196
40394
|
}
|
|
39197
40395
|
async seed() {
|
|
39198
|
-
await this.storage.initial(`${RootConfig$
|
|
40396
|
+
await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.questionBankItem.name}Category`, QUESTION_BANK_ITEM_CATEGORY_MOCK);
|
|
39199
40397
|
}
|
|
39200
40398
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionBankItemCategoryDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
39201
40399
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionBankItemCategoryDataSeeder }); }
|
|
@@ -39516,7 +40714,7 @@ class AXMQuestionnaireCategoryDataSeeder {
|
|
|
39516
40714
|
this.storage = inject(AXPEntityStorageService);
|
|
39517
40715
|
}
|
|
39518
40716
|
async seed() {
|
|
39519
|
-
await this.storage.initial(`${RootConfig$
|
|
40717
|
+
await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.questionnaire.name}Category`, QUESTIONNAIRE_CATEGORY_MOCK);
|
|
39520
40718
|
}
|
|
39521
40719
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionnaireCategoryDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
39522
40720
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionnaireCategoryDataSeeder }); }
|
|
@@ -39530,7 +40728,7 @@ class AXMQuestionBankItemDataSeeder {
|
|
|
39530
40728
|
this.storage = inject(AXPEntityStorageService);
|
|
39531
40729
|
}
|
|
39532
40730
|
async seed() {
|
|
39533
|
-
await this.storage.initial(`${RootConfig$
|
|
40731
|
+
await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.questionBankItem.name}`, questionBankItemMock);
|
|
39534
40732
|
}
|
|
39535
40733
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionBankItemDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
39536
40734
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionBankItemDataSeeder }); }
|
|
@@ -39544,7 +40742,7 @@ class AXMQuestionnaireDataSeeder {
|
|
|
39544
40742
|
this.storage = inject(AXPEntityStorageService);
|
|
39545
40743
|
}
|
|
39546
40744
|
async seed() {
|
|
39547
|
-
await this.storage.initial(`${RootConfig$
|
|
40745
|
+
await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.questionnaire.name}`, questionnaireMock);
|
|
39548
40746
|
}
|
|
39549
40747
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionnaireDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
39550
40748
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionnaireDataSeeder }); }
|
|
@@ -39631,7 +40829,7 @@ class AXMPublicationDataSeeder {
|
|
|
39631
40829
|
this.storage = inject(AXPEntityStorageService);
|
|
39632
40830
|
}
|
|
39633
40831
|
async seed() {
|
|
39634
|
-
await this.storage.initial(`${RootConfig$
|
|
40832
|
+
await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.publication.name}`, publicationMock);
|
|
39635
40833
|
}
|
|
39636
40834
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMPublicationDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
39637
40835
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMPublicationDataSeeder }); }
|
|
@@ -39732,7 +40930,7 @@ class AXMResponseSessionDataSeeder {
|
|
|
39732
40930
|
this.storage = inject(AXPEntityStorageService);
|
|
39733
40931
|
}
|
|
39734
40932
|
async seed() {
|
|
39735
|
-
await this.storage.initial(`${RootConfig$
|
|
40933
|
+
await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.responseSession.name}`, responseSessionMock);
|
|
39736
40934
|
}
|
|
39737
40935
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMResponseSessionDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
39738
40936
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMResponseSessionDataSeeder }); }
|
|
@@ -39818,7 +41016,7 @@ class AXMCollaboratorDataSeeder {
|
|
|
39818
41016
|
this.storage = inject(AXPEntityStorageService);
|
|
39819
41017
|
}
|
|
39820
41018
|
async seed() {
|
|
39821
|
-
await this.storage.initial(`${RootConfig$
|
|
41019
|
+
await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.collaborator.name}`, collaboratorMock);
|
|
39822
41020
|
}
|
|
39823
41021
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMCollaboratorDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
39824
41022
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMCollaboratorDataSeeder }); }
|
|
@@ -39927,7 +41125,7 @@ class AXMResponseEntryDataSeeder {
|
|
|
39927
41125
|
this.storage = inject(AXPEntityStorageService);
|
|
39928
41126
|
}
|
|
39929
41127
|
async seed() {
|
|
39930
|
-
await this.storage.initial(`${RootConfig$
|
|
41128
|
+
await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.responseEntry.name}`, responseEntryMock);
|
|
39931
41129
|
}
|
|
39932
41130
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMResponseEntryDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
39933
41131
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMResponseEntryDataSeeder }); }
|
|
@@ -40055,7 +41253,7 @@ class AXCCustomerTypeDataSeeder {
|
|
|
40055
41253
|
this.storageService = inject(AXPEntityStorageService);
|
|
40056
41254
|
}
|
|
40057
41255
|
async seed() {
|
|
40058
|
-
await this.storageService.initial(RootConfig$
|
|
41256
|
+
await this.storageService.initial(RootConfig$p.entities.customerType.source, CUSTOMER_TYPES_MOCK);
|
|
40059
41257
|
}
|
|
40060
41258
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCustomerTypeDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
40061
41259
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCustomerTypeDataSeeder }); }
|
|
@@ -40069,7 +41267,7 @@ class AXCCustomerSegmentDataSeeder {
|
|
|
40069
41267
|
this.storageService = inject(AXPEntityStorageService);
|
|
40070
41268
|
}
|
|
40071
41269
|
async seed() {
|
|
40072
|
-
await this.storageService.initial(RootConfig$
|
|
41270
|
+
await this.storageService.initial(RootConfig$p.entities.customerSegment.source, CUSTOMER_SEGMENTS_MOCK);
|
|
40073
41271
|
}
|
|
40074
41272
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCustomerSegmentDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
40075
41273
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCustomerSegmentDataSeeder }); }
|
|
@@ -40083,7 +41281,7 @@ class AXCCustomerDataSeeder {
|
|
|
40083
41281
|
this.storageService = inject(AXPEntityStorageService);
|
|
40084
41282
|
}
|
|
40085
41283
|
async seed() {
|
|
40086
|
-
await this.storageService.initial(RootConfig$
|
|
41284
|
+
await this.storageService.initial(RootConfig$p.entities.customer.source, CUSTOMERS_MOCK);
|
|
40087
41285
|
}
|
|
40088
41286
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCustomerDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
40089
41287
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCustomerDataSeeder }); }
|
|
@@ -40107,7 +41305,7 @@ class AXCCrmOpportunityStageDataSeeder {
|
|
|
40107
41305
|
this.storageService = inject(AXPEntityStorageService);
|
|
40108
41306
|
}
|
|
40109
41307
|
async seed() {
|
|
40110
|
-
await this.storageService.initial(RootConfig$
|
|
41308
|
+
await this.storageService.initial(RootConfig$p.entities.opportunityStage.source, OPPORTUNITY_STAGES_MOCK);
|
|
40111
41309
|
}
|
|
40112
41310
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmOpportunityStageDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
40113
41311
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmOpportunityStageDataSeeder }); }
|
|
@@ -40126,7 +41324,7 @@ class AXCCrmSalesPipelineDataSeeder {
|
|
|
40126
41324
|
this.storageService = inject(AXPEntityStorageService);
|
|
40127
41325
|
}
|
|
40128
41326
|
async seed() {
|
|
40129
|
-
await this.storageService.initial(RootConfig$
|
|
41327
|
+
await this.storageService.initial(RootConfig$p.entities.salesPipeline.source, SALES_PIPELINES_MOCK);
|
|
40130
41328
|
}
|
|
40131
41329
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmSalesPipelineDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
40132
41330
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmSalesPipelineDataSeeder }); }
|
|
@@ -40149,7 +41347,7 @@ class AXCCrmLifecycleStageDataSeeder {
|
|
|
40149
41347
|
this.storageService = inject(AXPEntityStorageService);
|
|
40150
41348
|
}
|
|
40151
41349
|
async seed() {
|
|
40152
|
-
await this.storageService.initial(RootConfig$
|
|
41350
|
+
await this.storageService.initial(RootConfig$p.entities.lifecycleStage.source, LIFECYCLE_STAGES_MOCK);
|
|
40153
41351
|
}
|
|
40154
41352
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmLifecycleStageDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
40155
41353
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmLifecycleStageDataSeeder }); }
|
|
@@ -40170,7 +41368,7 @@ class AXCCrmSalesTerritoryDataSeeder {
|
|
|
40170
41368
|
this.storageService = inject(AXPEntityStorageService);
|
|
40171
41369
|
}
|
|
40172
41370
|
async seed() {
|
|
40173
|
-
await this.storageService.initial(RootConfig$
|
|
41371
|
+
await this.storageService.initial(RootConfig$p.entities.salesTerritory.source, SALES_TERRITORIES_MOCK);
|
|
40174
41372
|
}
|
|
40175
41373
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmSalesTerritoryDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
40176
41374
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmSalesTerritoryDataSeeder }); }
|
|
@@ -40190,7 +41388,7 @@ class AXCCrmLeadDataSeeder {
|
|
|
40190
41388
|
this.storageService = inject(AXPEntityStorageService);
|
|
40191
41389
|
}
|
|
40192
41390
|
async seed() {
|
|
40193
|
-
await this.storageService.initial(RootConfig$
|
|
41391
|
+
await this.storageService.initial(RootConfig$p.entities.lead.source, LEADS_MOCK);
|
|
40194
41392
|
}
|
|
40195
41393
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmLeadDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
40196
41394
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmLeadDataSeeder }); }
|
|
@@ -40236,7 +41434,7 @@ class AXCCrmOpportunityDataSeeder {
|
|
|
40236
41434
|
this.storageService = inject(AXPEntityStorageService);
|
|
40237
41435
|
}
|
|
40238
41436
|
async seed() {
|
|
40239
|
-
await this.storageService.initial(RootConfig$
|
|
41437
|
+
await this.storageService.initial(RootConfig$p.entities.opportunity.source, OPPORTUNITIES_MOCK);
|
|
40240
41438
|
}
|
|
40241
41439
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmOpportunityDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
40242
41440
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmOpportunityDataSeeder }); }
|
|
@@ -40256,7 +41454,7 @@ class AXCCrmActivityDataSeeder {
|
|
|
40256
41454
|
this.storageService = inject(AXPEntityStorageService);
|
|
40257
41455
|
}
|
|
40258
41456
|
async seed() {
|
|
40259
|
-
await this.storageService.initial(RootConfig$
|
|
41457
|
+
await this.storageService.initial(RootConfig$p.entities.activity.source, ACTIVITIES_MOCK);
|
|
40260
41458
|
}
|
|
40261
41459
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmActivityDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
40262
41460
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmActivityDataSeeder }); }
|
|
@@ -40280,7 +41478,7 @@ class AXCCrmDealContactRoleDataSeeder {
|
|
|
40280
41478
|
this.storageService = inject(AXPEntityStorageService);
|
|
40281
41479
|
}
|
|
40282
41480
|
async seed() {
|
|
40283
|
-
await this.storageService.initial(RootConfig$
|
|
41481
|
+
await this.storageService.initial(RootConfig$p.entities.dealContactRole.source, DEAL_CONTACT_ROLES_MOCK);
|
|
40284
41482
|
}
|
|
40285
41483
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmDealContactRoleDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
40286
41484
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmDealContactRoleDataSeeder }); }
|
|
@@ -40396,7 +41594,7 @@ class AXPIssueTypeDataSeeder {
|
|
|
40396
41594
|
this.storageService = inject(AXPEntityStorageService);
|
|
40397
41595
|
}
|
|
40398
41596
|
async seed() {
|
|
40399
|
-
await this.storageService.initial(`${RootConfig$
|
|
41597
|
+
await this.storageService.initial(`${RootConfig$q.module.name}.${RootConfig$q.entities.issueType.name}`, ISSUE_TYPES);
|
|
40400
41598
|
}
|
|
40401
41599
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXPIssueTypeDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
40402
41600
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXPIssueTypeDataSeeder }); }
|
|
@@ -40827,7 +42025,7 @@ const createFileCastMiddleware = {
|
|
|
40827
42025
|
const hasValidSource = obj.source &&
|
|
40828
42026
|
typeof obj.source === 'object' &&
|
|
40829
42027
|
obj.source.kind &&
|
|
40830
|
-
['blob', 'url', 'preview', 'none', 'fileId'].includes(obj.source.kind);
|
|
42028
|
+
['blob', 'url', 'preview', 'none', 'fileId', 'reference'].includes(obj.source.kind);
|
|
40831
42029
|
// At least one of these conditions must be true for it to be a file
|
|
40832
42030
|
const isFileObject = hasValidStatus || hasValidSource;
|
|
40833
42031
|
// Additional validation for file-specific properties
|
|
@@ -40910,7 +42108,38 @@ const createFileCastMiddleware = {
|
|
|
40910
42108
|
// Return null to indicate this file should be removed from the list
|
|
40911
42109
|
return null;
|
|
40912
42110
|
}
|
|
40913
|
-
// Case 2:
|
|
42111
|
+
// Case 2: Reference-based file (handle document updates)
|
|
42112
|
+
if (file.source?.kind === 'reference' && file.source.value && typeof file.source.value === 'object' && 'id' in file.source.value && 'type' in file.source.value) {
|
|
42113
|
+
const reference = file.source.value;
|
|
42114
|
+
// Only handle document references
|
|
42115
|
+
if (reference.type === 'document' && documentService) {
|
|
42116
|
+
try {
|
|
42117
|
+
const document = await documentService.getOne(reference.id);
|
|
42118
|
+
if (document) {
|
|
42119
|
+
// Check if name has changed and update document if needed
|
|
42120
|
+
if (document.name !== file.name || document.title !== file.name) {
|
|
42121
|
+
try {
|
|
42122
|
+
await documentService.updateOne(reference.id, {
|
|
42123
|
+
name: file.name,
|
|
42124
|
+
title: file.name,
|
|
42125
|
+
});
|
|
42126
|
+
}
|
|
42127
|
+
catch (error) {
|
|
42128
|
+
console.error('[file-cast] Failed to update document name:', error);
|
|
42129
|
+
}
|
|
42130
|
+
}
|
|
42131
|
+
// Return reference identifier
|
|
42132
|
+
return { id: serializeReference(reference), kind: 'reference' };
|
|
42133
|
+
}
|
|
42134
|
+
}
|
|
42135
|
+
catch (error) {
|
|
42136
|
+
console.error('[file-cast] Failed to process reference:', error);
|
|
42137
|
+
}
|
|
42138
|
+
}
|
|
42139
|
+
// For non-document references or if document service is not available, return reference as-is
|
|
42140
|
+
return { id: serializeReference(reference), kind: 'reference' };
|
|
42141
|
+
}
|
|
42142
|
+
// Case 3: Already uploaded file (keep existing ID)
|
|
40914
42143
|
if ((file.status === 'uploaded' || file.status === 'remote') &&
|
|
40915
42144
|
file.source?.kind === 'fileId' &&
|
|
40916
42145
|
typeof file.source.value === 'string') {
|
|
@@ -40936,7 +42165,7 @@ const createFileCastMiddleware = {
|
|
|
40936
42165
|
}
|
|
40937
42166
|
return { id: cleanFileId, kind: 'file' };
|
|
40938
42167
|
}
|
|
40939
|
-
// Case
|
|
42168
|
+
// Case 4: New file that needs uploading
|
|
40940
42169
|
if (!file.source?.value) {
|
|
40941
42170
|
return null;
|
|
40942
42171
|
}
|
|
@@ -40991,25 +42220,45 @@ const createFileCastMiddleware = {
|
|
|
40991
42220
|
};
|
|
40992
42221
|
const FILE_PREFIX = 'file:';
|
|
40993
42222
|
const DOCUMENT_PREFIX = 'document:';
|
|
42223
|
+
const REFERENCE_PREFIX = 'reference:';
|
|
40994
42224
|
const addFilePrefix = (fileId) => {
|
|
40995
42225
|
return `${FILE_PREFIX}${fileId}`;
|
|
40996
42226
|
};
|
|
40997
42227
|
const addDocumentPrefix = (docId) => {
|
|
40998
42228
|
return `${DOCUMENT_PREFIX}${docId}`;
|
|
40999
42229
|
};
|
|
42230
|
+
const addReferencePrefix = (reference) => {
|
|
42231
|
+
return `${REFERENCE_PREFIX}${reference.type}:${reference.id}`;
|
|
42232
|
+
};
|
|
41000
42233
|
const removeFilePrefix = (prefixedId) => {
|
|
41001
42234
|
return prefixedId.startsWith(FILE_PREFIX) ? prefixedId.substring(FILE_PREFIX.length) : prefixedId;
|
|
41002
42235
|
};
|
|
41003
42236
|
const removeDocumentPrefix = (prefixedId) => {
|
|
41004
42237
|
return prefixedId.startsWith(DOCUMENT_PREFIX) ? prefixedId.substring(DOCUMENT_PREFIX.length) : prefixedId;
|
|
41005
42238
|
};
|
|
42239
|
+
const parseReference = (prefixedId) => {
|
|
42240
|
+
if (!prefixedId.startsWith(REFERENCE_PREFIX))
|
|
42241
|
+
return null;
|
|
42242
|
+
const withoutPrefix = prefixedId.substring(REFERENCE_PREFIX.length);
|
|
42243
|
+
const colonIndex = withoutPrefix.indexOf(':');
|
|
42244
|
+
if (colonIndex === -1)
|
|
42245
|
+
return null;
|
|
42246
|
+
return {
|
|
42247
|
+
type: withoutPrefix.substring(0, colonIndex),
|
|
42248
|
+
id: withoutPrefix.substring(colonIndex + 1),
|
|
42249
|
+
};
|
|
42250
|
+
};
|
|
42251
|
+
const serializeReference = (reference) => {
|
|
42252
|
+
return addReferencePrefix(reference);
|
|
42253
|
+
};
|
|
41006
42254
|
const ensureCleanFileId = (fileId) => {
|
|
41007
42255
|
// Remove prefix if it exists to get clean file ID
|
|
41008
42256
|
return removeFilePrefix(fileId);
|
|
41009
42257
|
};
|
|
41010
42258
|
const isFileId = (value) => value.startsWith(FILE_PREFIX);
|
|
41011
42259
|
const isDocumentId = (value) => value.startsWith(DOCUMENT_PREFIX);
|
|
41012
|
-
const
|
|
42260
|
+
const isReference = (value) => value.startsWith(REFERENCE_PREFIX);
|
|
42261
|
+
const isAnyFileRef = (value) => isFileId(value) || isDocumentId(value) || isReference(value);
|
|
41013
42262
|
const hasDocumentMeta = (obj) => {
|
|
41014
42263
|
const candidate = obj;
|
|
41015
42264
|
if (!candidate || typeof candidate !== 'object' || !candidate.meta || typeof candidate.meta !== 'object') {
|
|
@@ -41113,7 +42362,11 @@ const createFileCastMiddleware = {
|
|
|
41113
42362
|
if (isFileListItem(file)) {
|
|
41114
42363
|
const processed = await processFileForStorage(file, ctx.id?.toString());
|
|
41115
42364
|
if (processed) {
|
|
41116
|
-
const prefixedId = processed.kind === 'document'
|
|
42365
|
+
const prefixedId = processed.kind === 'document'
|
|
42366
|
+
? addDocumentPrefix(processed.id)
|
|
42367
|
+
: processed.kind === 'reference'
|
|
42368
|
+
? processed.id
|
|
42369
|
+
: addFilePrefix(processed.id);
|
|
41117
42370
|
return prefixedId;
|
|
41118
42371
|
}
|
|
41119
42372
|
else {
|
|
@@ -41135,7 +42388,11 @@ const createFileCastMiddleware = {
|
|
|
41135
42388
|
else if (isFileListItem(value)) {
|
|
41136
42389
|
const processed = await processFileForStorage(value, ctx.id?.toString());
|
|
41137
42390
|
if (processed) {
|
|
41138
|
-
const prefixedId = processed.kind === 'document'
|
|
42391
|
+
const prefixedId = processed.kind === 'document'
|
|
42392
|
+
? addDocumentPrefix(processed.id)
|
|
42393
|
+
: processed.kind === 'reference'
|
|
42394
|
+
? processed.id
|
|
42395
|
+
: addFilePrefix(processed.id);
|
|
41139
42396
|
setValueByPath(ctx.data, keyPath, prefixedId);
|
|
41140
42397
|
}
|
|
41141
42398
|
else {
|
|
@@ -41197,22 +42454,31 @@ const createFileCastMiddleware = {
|
|
|
41197
42454
|
await Promise.all(fileIdKeys.map(async (keyPath) => {
|
|
41198
42455
|
const value = getValueByPath(resultData, keyPath);
|
|
41199
42456
|
if (Array.isArray(value)) {
|
|
41200
|
-
// Split file and
|
|
42457
|
+
// Split file, document, and reference IDs
|
|
41201
42458
|
const fileIdList = [];
|
|
41202
42459
|
const documentIdList = [];
|
|
42460
|
+
const referenceList = [];
|
|
41203
42461
|
value.forEach((item) => {
|
|
41204
42462
|
if (typeof item === 'string') {
|
|
41205
42463
|
if (isFileId(item))
|
|
41206
42464
|
fileIdList.push(removeFilePrefix(item));
|
|
41207
42465
|
else if (isDocumentId(item))
|
|
41208
42466
|
documentIdList.push(removeDocumentPrefix(item));
|
|
42467
|
+
else if (isReference(item)) {
|
|
42468
|
+
const ref = parseReference(item);
|
|
42469
|
+
if (ref)
|
|
42470
|
+
referenceList.push(ref);
|
|
42471
|
+
}
|
|
41209
42472
|
}
|
|
41210
42473
|
});
|
|
41211
42474
|
try {
|
|
42475
|
+
// Fetch documents for references
|
|
42476
|
+
const referenceDocIds = referenceList.filter((ref) => ref.type === 'document').map((ref) => ref.id);
|
|
42477
|
+
const allDocIds = [...documentIdList, ...referenceDocIds];
|
|
41212
42478
|
const [manyInfos, documents] = await Promise.all([
|
|
41213
42479
|
fileIdList.length ? fileStorageService.findMany(fileIdList) : Promise.resolve([]),
|
|
41214
|
-
|
|
41215
|
-
? documentService.findMany(
|
|
42480
|
+
allDocIds.length && documentService
|
|
42481
|
+
? documentService.findMany(allDocIds)
|
|
41216
42482
|
: Promise.resolve([]),
|
|
41217
42483
|
]);
|
|
41218
42484
|
const infoMap = new Map(manyInfos.map((i) => [i.fileId, i]));
|
|
@@ -41254,6 +42520,33 @@ const createFileCastMiddleware = {
|
|
|
41254
42520
|
source: { kind: 'fileId', value: actualDocId },
|
|
41255
42521
|
};
|
|
41256
42522
|
}
|
|
42523
|
+
if (typeof item === 'string' && isReference(item)) {
|
|
42524
|
+
const reference = parseReference(item);
|
|
42525
|
+
if (reference && reference.type === 'document' && documentService) {
|
|
42526
|
+
const doc = docMap.get(reference.id);
|
|
42527
|
+
if (doc) {
|
|
42528
|
+
const listItem = {
|
|
42529
|
+
id: reference.id,
|
|
42530
|
+
name: doc.name || 'Document',
|
|
42531
|
+
size: doc.size,
|
|
42532
|
+
status: 'uploaded',
|
|
42533
|
+
source: { kind: 'reference', value: reference },
|
|
42534
|
+
};
|
|
42535
|
+
// Expose full document object for downstream listeners/plugins
|
|
42536
|
+
listItem.documentData = doc;
|
|
42537
|
+
if (doc.metaDataForm)
|
|
42538
|
+
listItem.meta = doc.metaDataForm;
|
|
42539
|
+
return listItem;
|
|
42540
|
+
}
|
|
42541
|
+
}
|
|
42542
|
+
// Fallback for non-document references or when document not found
|
|
42543
|
+
return {
|
|
42544
|
+
id: reference?.id || 'unknown',
|
|
42545
|
+
name: 'Unknown Reference',
|
|
42546
|
+
status: 'remote',
|
|
42547
|
+
source: { kind: 'reference', value: reference || { id: 'unknown', type: 'unknown' } },
|
|
42548
|
+
};
|
|
42549
|
+
}
|
|
41257
42550
|
return item;
|
|
41258
42551
|
});
|
|
41259
42552
|
setValueByPath(resultData, keyPath, convertedArray);
|
|
@@ -41339,6 +42632,55 @@ const createFileCastMiddleware = {
|
|
|
41339
42632
|
});
|
|
41340
42633
|
}
|
|
41341
42634
|
}
|
|
42635
|
+
else if (isReference(value)) {
|
|
42636
|
+
const reference = parseReference(value);
|
|
42637
|
+
if (reference && reference.type === 'document' && documentService) {
|
|
42638
|
+
try {
|
|
42639
|
+
const docs = await documentService.findMany([reference.id]);
|
|
42640
|
+
const doc = docs?.[0];
|
|
42641
|
+
if (doc) {
|
|
42642
|
+
const listItem = {
|
|
42643
|
+
id: reference.id,
|
|
42644
|
+
name: doc.name || 'Document',
|
|
42645
|
+
size: doc.size,
|
|
42646
|
+
status: 'uploaded',
|
|
42647
|
+
source: { kind: 'reference', value: reference },
|
|
42648
|
+
};
|
|
42649
|
+
// Expose full document object for downstream listeners/plugins
|
|
42650
|
+
listItem.documentData = doc;
|
|
42651
|
+
if (doc.metaDataForm)
|
|
42652
|
+
listItem.meta = doc.metaDataForm;
|
|
42653
|
+
setValueByPath(resultData, keyPath, listItem);
|
|
42654
|
+
}
|
|
42655
|
+
else {
|
|
42656
|
+
setValueByPath(resultData, keyPath, {
|
|
42657
|
+
id: reference.id,
|
|
42658
|
+
name: 'Unknown Document',
|
|
42659
|
+
status: 'remote',
|
|
42660
|
+
source: { kind: 'reference', value: reference },
|
|
42661
|
+
});
|
|
42662
|
+
}
|
|
42663
|
+
}
|
|
42664
|
+
catch (error) {
|
|
42665
|
+
console.error('[file-cast] ❌ Failed to get reference document info', { keyPath, reference, error });
|
|
42666
|
+
setValueByPath(resultData, keyPath, {
|
|
42667
|
+
id: reference.id,
|
|
42668
|
+
name: 'Unknown Document',
|
|
42669
|
+
status: 'remote',
|
|
42670
|
+
source: { kind: 'reference', value: reference },
|
|
42671
|
+
});
|
|
42672
|
+
}
|
|
42673
|
+
}
|
|
42674
|
+
else {
|
|
42675
|
+
// Fallback for non-document references
|
|
42676
|
+
setValueByPath(resultData, keyPath, {
|
|
42677
|
+
id: reference?.id || 'unknown',
|
|
42678
|
+
name: 'Unknown Reference',
|
|
42679
|
+
status: 'remote',
|
|
42680
|
+
source: { kind: 'reference', value: reference || { id: 'unknown', type: 'unknown' } },
|
|
42681
|
+
});
|
|
42682
|
+
}
|
|
42683
|
+
}
|
|
41342
42684
|
}
|
|
41343
42685
|
}));
|
|
41344
42686
|
}
|
|
@@ -41365,7 +42707,7 @@ const historyLoggerMiddleware = {
|
|
|
41365
42707
|
target: { ops: ['create', 'update', 'delete'], order: 80 },
|
|
41366
42708
|
execute: async (ctx, next) => {
|
|
41367
42709
|
const sessionService = inject(AXPSessionService);
|
|
41368
|
-
const versioning = inject(
|
|
42710
|
+
const versioning = inject(AXCVersioningService);
|
|
41369
42711
|
// Capture previous for update/delete
|
|
41370
42712
|
if (ctx.op === 'update' || ctx.op === 'delete') {
|
|
41371
42713
|
try {
|
|
@@ -42348,6 +43690,148 @@ const signatureLoaderMiddleware = {
|
|
|
42348
43690
|
//#endregion
|
|
42349
43691
|
};
|
|
42350
43692
|
|
|
43693
|
+
//#region ---- Lock Guard Middleware ----
|
|
43694
|
+
/**
|
|
43695
|
+
* Middleware that prevents editing or deleting locked records.
|
|
43696
|
+
*
|
|
43697
|
+
* Supports two types of locks:
|
|
43698
|
+
* 1. 'user' lock: Automatic lock when edit popup is opened.
|
|
43699
|
+
* - Only the user who locked it can edit
|
|
43700
|
+
* - Other users cannot edit
|
|
43701
|
+
*
|
|
43702
|
+
* 2. 'admin' lock: Manual lock by admin for a specific duration or permanently.
|
|
43703
|
+
* - Even the admin who locked it cannot edit
|
|
43704
|
+
* - All users are blocked until lock expires (if expireAt is set)
|
|
43705
|
+
*/
|
|
43706
|
+
const lockGuardMiddleware = {
|
|
43707
|
+
target: { ops: ['update', 'delete'], order: 10 },
|
|
43708
|
+
execute: async (ctx, next) => {
|
|
43709
|
+
const lockService = inject(AXPLockService);
|
|
43710
|
+
const session = inject(AXPSessionService);
|
|
43711
|
+
// Skip if no ID is provided (shouldn't happen for update/delete, but safety check)
|
|
43712
|
+
if (!ctx.id) {
|
|
43713
|
+
await next();
|
|
43714
|
+
return;
|
|
43715
|
+
}
|
|
43716
|
+
// First, check for 'admin' lock (highest priority - blocks everyone including the admin who locked it)
|
|
43717
|
+
try {
|
|
43718
|
+
const adminLockExists = await lockService.check({
|
|
43719
|
+
refId: ctx.id,
|
|
43720
|
+
refType: ctx.entityName,
|
|
43721
|
+
type: 'admin'
|
|
43722
|
+
});
|
|
43723
|
+
if (adminLockExists) {
|
|
43724
|
+
try {
|
|
43725
|
+
const adminLockInfo = await lockService.getInfo({
|
|
43726
|
+
refId: ctx.id,
|
|
43727
|
+
refType: ctx.entityName,
|
|
43728
|
+
type: 'admin'
|
|
43729
|
+
});
|
|
43730
|
+
if (adminLockInfo) {
|
|
43731
|
+
// Check if admin lock has expired
|
|
43732
|
+
let isExpired = false;
|
|
43733
|
+
if (adminLockInfo.expireAt) {
|
|
43734
|
+
const now = new Date();
|
|
43735
|
+
const expireDate = new Date(adminLockInfo.expireAt);
|
|
43736
|
+
isExpired = now > expireDate;
|
|
43737
|
+
}
|
|
43738
|
+
// If admin lock exists and hasn't expired, block everyone (including the admin who locked it)
|
|
43739
|
+
if (!isExpired) {
|
|
43740
|
+
throw new AXPMiddlewareAbortError('This record is locked by administrator and cannot be edited or deleted.', {
|
|
43741
|
+
status: 409,
|
|
43742
|
+
code: 'RECORD_ADMIN_LOCKED',
|
|
43743
|
+
details: {
|
|
43744
|
+
entity: ctx.entityName,
|
|
43745
|
+
id: ctx.id,
|
|
43746
|
+
lockedBy: adminLockInfo.lockedBy,
|
|
43747
|
+
lockType: adminLockInfo.type,
|
|
43748
|
+
expireAt: adminLockInfo.expireAt,
|
|
43749
|
+
operation: ctx.op,
|
|
43750
|
+
},
|
|
43751
|
+
});
|
|
43752
|
+
}
|
|
43753
|
+
}
|
|
43754
|
+
}
|
|
43755
|
+
catch (error) {
|
|
43756
|
+
// If getInfo throws an error (e.g., lock not found), continue to check user lock
|
|
43757
|
+
if (error instanceof AXPMiddlewareAbortError) {
|
|
43758
|
+
throw error;
|
|
43759
|
+
}
|
|
43760
|
+
// Otherwise, ignore and continue
|
|
43761
|
+
}
|
|
43762
|
+
}
|
|
43763
|
+
}
|
|
43764
|
+
catch (error) {
|
|
43765
|
+
// If it's already an AXPMiddlewareAbortError, re-throw it
|
|
43766
|
+
if (error instanceof AXPMiddlewareAbortError) {
|
|
43767
|
+
throw error;
|
|
43768
|
+
}
|
|
43769
|
+
// Otherwise, continue to check user lock
|
|
43770
|
+
}
|
|
43771
|
+
// Second, check for 'user' lock (only blocks other users, not the user who locked it)
|
|
43772
|
+
try {
|
|
43773
|
+
const userLockExists = await lockService.check({
|
|
43774
|
+
refId: ctx.id,
|
|
43775
|
+
refType: ctx.entityName,
|
|
43776
|
+
type: 'user'
|
|
43777
|
+
});
|
|
43778
|
+
if (userLockExists) {
|
|
43779
|
+
try {
|
|
43780
|
+
const userLockInfo = await lockService.getInfo({
|
|
43781
|
+
refId: ctx.id,
|
|
43782
|
+
refType: ctx.entityName,
|
|
43783
|
+
type: 'user'
|
|
43784
|
+
});
|
|
43785
|
+
if (userLockInfo) {
|
|
43786
|
+
// Check if user lock has expired
|
|
43787
|
+
let isExpired = false;
|
|
43788
|
+
if (userLockInfo.expireAt) {
|
|
43789
|
+
const now = new Date();
|
|
43790
|
+
const expireDate = new Date(userLockInfo.expireAt);
|
|
43791
|
+
isExpired = now > expireDate;
|
|
43792
|
+
}
|
|
43793
|
+
// If user lock exists and hasn't expired, check if current user is the one who locked it
|
|
43794
|
+
if (!isExpired) {
|
|
43795
|
+
// If current user is not the one who locked it, prevent the operation
|
|
43796
|
+
if (session.user && userLockInfo.lockedBy.id !== session.user.id) {
|
|
43797
|
+
throw new AXPMiddlewareAbortError('This record is locked by another user and cannot be edited or deleted.', {
|
|
43798
|
+
status: 409,
|
|
43799
|
+
code: 'RECORD_USER_LOCKED',
|
|
43800
|
+
details: {
|
|
43801
|
+
entity: ctx.entityName,
|
|
43802
|
+
id: ctx.id,
|
|
43803
|
+
lockedBy: userLockInfo.lockedBy,
|
|
43804
|
+
lockType: userLockInfo.type,
|
|
43805
|
+
operation: ctx.op,
|
|
43806
|
+
},
|
|
43807
|
+
});
|
|
43808
|
+
}
|
|
43809
|
+
// If current user is the one who locked it, allow the operation (continue to next())
|
|
43810
|
+
}
|
|
43811
|
+
}
|
|
43812
|
+
}
|
|
43813
|
+
catch (error) {
|
|
43814
|
+
// If getInfo throws an error (e.g., lock not found), continue
|
|
43815
|
+
if (error instanceof AXPMiddlewareAbortError) {
|
|
43816
|
+
throw error;
|
|
43817
|
+
}
|
|
43818
|
+
// Otherwise, ignore and continue
|
|
43819
|
+
}
|
|
43820
|
+
}
|
|
43821
|
+
}
|
|
43822
|
+
catch (error) {
|
|
43823
|
+
// If it's already an AXPMiddlewareAbortError, re-throw it
|
|
43824
|
+
if (error instanceof AXPMiddlewareAbortError) {
|
|
43825
|
+
throw error;
|
|
43826
|
+
}
|
|
43827
|
+
// Otherwise, continue
|
|
43828
|
+
}
|
|
43829
|
+
// If no blocking locks found, proceed with the operation
|
|
43830
|
+
await next();
|
|
43831
|
+
},
|
|
43832
|
+
};
|
|
43833
|
+
//#endregion
|
|
43834
|
+
|
|
42351
43835
|
class AXCMiddlewaresModule {
|
|
42352
43836
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCMiddlewaresModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
42353
43837
|
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.10", ngImport: i0, type: AXCMiddlewaresModule }); }
|
|
@@ -42366,6 +43850,7 @@ class AXCMiddlewaresModule {
|
|
|
42366
43850
|
{ provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: primaryMiddleware },
|
|
42367
43851
|
{ provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: historyLoggerMiddleware },
|
|
42368
43852
|
{ provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: signatureLoaderMiddleware },
|
|
43853
|
+
{ provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: lockGuardMiddleware },
|
|
42369
43854
|
// Sample entity event listener to show logs for all entity.* events
|
|
42370
43855
|
//{ provide: AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, multi: true, useValue: AXCMockEntityLogListener },
|
|
42371
43856
|
] }); }
|
|
@@ -42391,6 +43876,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
|
|
|
42391
43876
|
{ provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: primaryMiddleware },
|
|
42392
43877
|
{ provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: historyLoggerMiddleware },
|
|
42393
43878
|
{ provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: signatureLoaderMiddleware },
|
|
43879
|
+
{ provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: lockGuardMiddleware },
|
|
42394
43880
|
// Sample entity event listener to show logs for all entity.* events
|
|
42395
43881
|
//{ provide: AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, multi: true, useValue: AXCMockEntityLogListener },
|
|
42396
43882
|
],
|
|
@@ -42670,5 +44156,5 @@ const AXCMockEntityLogListener = {
|
|
|
42670
44156
|
* Generated bundle index. Do not edit.
|
|
42671
44157
|
*/
|
|
42672
44158
|
|
|
42673
|
-
export { APPLICATIONS, AXCAppTermDataSeeder, AXCAppVersionDataSeeder, AXCApplicationDataSeeder, AXCApplicationManagementMockModule, AXCAssessmentManagementMockModule, AXCAuthMockModule, AXCCalendarDataSeeder, AXCCalendarEventDataSeeder, AXCCalendarManagementMockModule, AXCCommonMockModule, AXCContactManagementMockModule, AXCContentManagementMockModule, AXCConversationMockModule, AXCCustomerManagementMockModule, AXCDashboardManagementMockModule, AXCDataManagementMockModule, AXCDexieEntityStorageService, AXCDocumentManagementMockModule, AXCEditionDataSeeder, AXCFeatureDataSeeder, AXCFileStorageService, AXCFormTemplateManagementMockModule, AXCGlobalVariablesDataSeeder, AXCGoogleStrategyMock, AXCHelpDeskMockModule, AXCHumanCapitalManagementMockModule, AXCIdentifierManagementMockModule, AXCJsaSeeder, AXCLocaleManagementMockModule, AXCLocationManagementMockModule, AXCLockService, AXCLogManagementMockModule, AXCLogReportCategoryProvider, AXCLogReportDefinitionProvider, AXCMeetingManagementMockModule, AXCMetaDataDefinitionDataSeeder, AXCMiddlewaresModule, AXCMockEntityLogListener, AXCMockModule, AXCModuleDataSeeder, AXCNotificationManagementMockModule, AXCOrganizationManagementMockModule, AXCPartyManagementMockModule, AXCPlatformManagementMockModule, AXCProjectManagementMockModule, AXCQueryCategoryMetadataInheritanceQuery, AXCReportManagementMockModule, AXCSecurityManagementMockModule, AXCTaskManagementMockModule, AXCTrainingManagementMockModule, AXCUserPassStrategyMock, AXCVersionDB, AXCWorkflowExecutionDB, AXCWorkflowExecutionService, AXCWorkflowManagementMockModule, AXC_LOG_REPORT_CATEGORY_PROVIDER, AXC_LOG_REPORT_DEFINITION_PROVIDER, AXMAiResponderService, AXMBusinessUnitDataSeeder, AXMCalendarEventTypeSeeder, AXMCollaboratorDataSeeder, AXMEmployeeDataSeeder, AXMEmployeeSkillDataSeeder, AXMEmployeeSkillsCategoryProvider, AXMEmployeeSkillsReportDefinitionProvider, AXMEmploymentTypeDataSeeder, AXMFormDataSourcesProvider, AXMIndustryDataSeeder, AXMLeaveRequestDataSeeder, AXMMeetingDataSeeder, AXMMeetingFilesDataSeeder, AXMMeetingParticipantDataSeeder, AXMMeetingRoleTypeDataSeeder, AXMMeetingSessionDataSeeder, AXMMeetingTypeDataSeeder, AXMMeetingTypeFileTemplateDataSeeder, AXMPositionAssignmentDataSeeder, AXMPositionDataSeeder, AXMPublicationDataSeeder, AXMQuestionBankItemCategoryDataSeeder, AXMQuestionBankItemDataSeeder, AXMQuestionnaireCategoryDataSeeder, AXMQuestionnaireDataSeeder, AXMReportCategoryDataSeeder, AXMReportDefinitionDataSeeder, AXMReportExecuteCommand, AXMReportMockDataService, AXMResponseEntryDataSeeder, AXMResponseSessionDataSeeder, AXMResponsibilityDataSeeder, AXMRoleDataSeeder, AXMSkillDataSeeder, AXMSkillLevelDataSeeder, AXMTagDataSeeder, AXMTeamDataSeeder, AXM_EMPLOYEE_SKILLS_CATEGORY_PROVIDER, AXM_EMPLOYEE_SKILLS_DEFINITION_PROVIDER, AXPDashboardDataSeeder, AXPIdentifierDB, AXPMessageDataSeeder, AXPMockChecksumProvider, AXPMockClockProvider, AXPMockIdentifierService, AXPMockLookupProvider, AXPMockPolicyProvider, AXPMockSequenceProvider, AXPRoomDataSeeder, AXPSecurityManagementRoleDataSeeder, AXPSecurityManagementUserDataSeeder, AXPTaskBoardPlatformManagementTaskProvider, AXPTaskBoardProjectManagementTaskProvider, AXQEmployeeSkillsLevelPercentagesQuery, AXQEmployeeSkillsLevelsQuery, AXQEmployeeSkillsListQuery, AXQEmployeeSkillsSkillPercentagesQuery, AXQEmployeeSkillsStatsQuery, AXQEmployeeSkillsTrendQuery, AXVChangeType, BUSINESS_UNITS_MOCK, DASHBOARDS, EDITIONS, EMPLOYEES_MOCK, EMPLOYEE_SKILLS_MOCK, EMPLOYMENT_TYPES_MOCK, FEATURES, GLOBAL_VARIABLES, LEAVE_REQUESTS_MOCK, MODULES, POSITIONS_CATEGORY_MOCK, POSITIONS_MOCK, POSITION_ASSIGNMENTS_MOCK, QUESTIONNAIRE_CATEGORY_MOCK, QUESTION_BANK_ITEM_CATEGORY_MOCK, RESPONSIBILITIES_CATEGORY_MOCK, RESPONSIBILITIES_MOCK, ROLES_CATEGORY_MOCK, ROLES_MOCK, SKILLS_CATEGORY_MOCK, SKILLS_MOCK, SKILL_LEVELS_MOCK, TAGS_MOCK, TASKS, TASK_STATUSES, TASK_TEMPLATES, TASK_TYPES, TEAMS_MOCK,
|
|
44159
|
+
export { APPLICATIONS, AXCAppTermDataSeeder, AXCAppVersionDataSeeder, AXCApplicationDataSeeder, AXCApplicationManagementMockModule, AXCAssessmentManagementMockModule, AXCAuthMockModule, AXCCalendarDataSeeder, AXCCalendarEventDataSeeder, AXCCalendarManagementMockModule, AXCCommonMockModule, AXCContactManagementMockModule, AXCContentManagementMockModule, AXCConversationMockModule, AXCCustomerManagementMockModule, AXCDashboardManagementMockModule, AXCDataManagementMockModule, AXCDexieEntityStorageService, AXCDocumentManagementMockModule, AXCEditionDataSeeder, AXCFeatureDataSeeder, AXCFileStorageService, AXCFormTemplateManagementMockModule, AXCGlobalVariablesDataSeeder, AXCGoogleStrategyMock, AXCHelpDeskMockModule, AXCHumanCapitalManagementMockModule, AXCIdentifierManagementMockModule, AXCJsaSeeder, AXCLocaleManagementMockModule, AXCLocationManagementMockModule, AXCLockService, AXCLogManagementMockModule, AXCLogReportCategoryProvider, AXCLogReportDefinitionProvider, AXCMeetingManagementMockModule, AXCMetaDataDefinitionDataSeeder, AXCMiddlewaresModule, AXCMockEntityLogListener, AXCMockModule, AXCModuleDataSeeder, AXCNotificationManagementMockModule, AXCOrganizationManagementMockModule, AXCPartyManagementMockModule, AXCPlatformManagementMockModule, AXCProjectManagementMockModule, AXCQueryCategoryMetadataInheritanceQuery, AXCReportManagementMockModule, AXCSecurityManagementMockModule, AXCTaskManagementMockModule, AXCTrainingManagementMockModule, AXCUserPassStrategyMock, AXCVersionDB, AXCVersioningService, AXCWorkflowDefinitionDataSeeder, AXCWorkflowExecutionDB, AXCWorkflowExecutionService, AXCWorkflowManagementMockModule, AXC_LOG_REPORT_CATEGORY_PROVIDER, AXC_LOG_REPORT_DEFINITION_PROVIDER, AXMAiResponderService, AXMBusinessUnitDataSeeder, AXMCalendarEventTypeSeeder, AXMCollaboratorDataSeeder, AXMEmployeeDataSeeder, AXMEmployeeSkillDataSeeder, AXMEmployeeSkillsCategoryProvider, AXMEmployeeSkillsReportDefinitionProvider, AXMEmploymentTypeDataSeeder, AXMFormDataSourcesProvider, AXMIndustryDataSeeder, AXMLeaveRequestDataSeeder, AXMMeetingDataSeeder, AXMMeetingFilesDataSeeder, AXMMeetingParticipantDataSeeder, AXMMeetingRoleTypeDataSeeder, AXMMeetingSessionDataSeeder, AXMMeetingTypeDataSeeder, AXMMeetingTypeFileTemplateDataSeeder, AXMPositionAssignmentDataSeeder, AXMPositionDataSeeder, AXMPublicationDataSeeder, AXMQuestionBankItemCategoryDataSeeder, AXMQuestionBankItemDataSeeder, AXMQuestionnaireCategoryDataSeeder, AXMQuestionnaireDataSeeder, AXMReportCategoryDataSeeder, AXMReportDefinitionDataSeeder, AXMReportExecuteCommand, AXMReportMockDataService, AXMResponseEntryDataSeeder, AXMResponseSessionDataSeeder, AXMResponsibilityDataSeeder, AXMRoleDataSeeder, AXMSkillDataSeeder, AXMSkillLevelDataSeeder, AXMTagDataSeeder, AXMTeamDataSeeder, AXM_EMPLOYEE_SKILLS_CATEGORY_PROVIDER, AXM_EMPLOYEE_SKILLS_DEFINITION_PROVIDER, AXPDashboardDataSeeder, AXPIdentifierDB, AXPMessageDataSeeder, AXPMockChecksumProvider, AXPMockClockProvider, AXPMockIdentifierService, AXPMockLookupProvider, AXPMockPolicyProvider, AXPMockSequenceProvider, AXPRoomDataSeeder, AXPSecurityManagementRoleDataSeeder, AXPSecurityManagementUserDataSeeder, AXPTaskBoardPlatformManagementTaskProvider, AXPTaskBoardProjectManagementTaskProvider, AXQEmployeeSkillsLevelPercentagesQuery, AXQEmployeeSkillsLevelsQuery, AXQEmployeeSkillsListQuery, AXQEmployeeSkillsSkillPercentagesQuery, AXQEmployeeSkillsStatsQuery, AXQEmployeeSkillsTrendQuery, AXVChangeType, BUSINESS_UNITS_MOCK, CheckPermissionActivity, DASHBOARDS, EDITIONS, EMPLOYEES_MOCK, EMPLOYEE_SKILLS_MOCK, EMPLOYMENT_TYPES_MOCK, ExecuteCommandActivity, ExecuteQueryActivity, FEATURES, GLOBAL_VARIABLES, LEAVE_REQUESTS_MOCK, MODULES, POSITIONS_CATEGORY_MOCK, POSITIONS_MOCK, POSITION_ASSIGNMENTS_MOCK, QUESTIONNAIRE_CATEGORY_MOCK, QUESTION_BANK_ITEM_CATEGORY_MOCK, RESPONSIBILITIES_CATEGORY_MOCK, RESPONSIBILITIES_MOCK, ROLES_CATEGORY_MOCK, ROLES_MOCK, SKILLS_CATEGORY_MOCK, SKILLS_MOCK, SKILL_LEVELS_MOCK, TAGS_MOCK, TASKS, TASK_STATUSES, TASK_TEMPLATES, TASK_TYPES, TEAMS_MOCK, applications, auditLoggerMiddleware, axVersionDB, axWorkflowExecutionDB, calendarEventMock, calendarEventTypeMockData, calendarMock, childCountMiddleware, collaboratorMock, computeDiff, createAndSaveDashboardForUser, createDashboardForUser, createFileCastMiddleware, findContactMethod, findEmployeeById, findPartyById, generateUserDashboard, historyLoggerMiddleware, identifierCommitMiddleware, lockGuardMiddleware, lookupResolverMiddleware, meetingFilesMock, meetingIds, meetingMock, meetingParticipantMock, meetingRoleTypeMock, meetingSessionMock, meetingTimeSlotMock, meetingTypeFileTemplateMock, meetingTypeMock, mergeDetailRelationMiddleware, mockRoleDefinitions, mockUsers, normalizeAnyFileArrayForView, normalizeSnapshotFileFieldsForView, participantIds, primaryMiddleware, provideWorkflowActivities, publicationMock, questionBankItemMock, questionnaireMock, responseEntryMock, responseSessionMock, signatureLoaderMiddleware, tenantsMock, toUiRows, workflowDefinitionEntityMock, workflowDefinitionIds, workflowDefinitionMock };
|
|
42674
44160
|
//# sourceMappingURL=acorex-connectivity-mock.mjs.map
|