@brggroup/share-lib 0.0.38 → 0.0.40
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.
|
@@ -2751,10 +2751,12 @@ class WF_TemplateStage {
|
|
|
2751
2751
|
LimitValue;
|
|
2752
2752
|
IsRequireUser;
|
|
2753
2753
|
// #endregion properties
|
|
2754
|
+
OrgImplCode;
|
|
2754
2755
|
constructor(obj) {
|
|
2755
2756
|
obj = obj || {};
|
|
2756
2757
|
this.WF_TemplateStage_Id = obj.WF_TemplateStage_Id || null;
|
|
2757
2758
|
this.App_Org_Id = obj.App_Org_Id || '';
|
|
2759
|
+
this.OrgImplCode = obj.OrgImplCode || '';
|
|
2758
2760
|
this.CreatedDate = obj.CreatedDate || null;
|
|
2759
2761
|
this.CreatedUser = obj.CreatedUser || '';
|
|
2760
2762
|
this.UpdatedDate = obj.UpdatedDate || null;
|
|
@@ -2823,20 +2825,27 @@ class Workflow extends WF_Template {
|
|
|
2823
2825
|
* STAGE
|
|
2824
2826
|
*/
|
|
2825
2827
|
class WorkflowStage extends WF_TemplateStage {
|
|
2828
|
+
lstAction;
|
|
2829
|
+
editorOption = new WorkflowStageEditorOption();
|
|
2830
|
+
constructor(obj) {
|
|
2831
|
+
obj = obj || {};
|
|
2832
|
+
super(obj);
|
|
2833
|
+
this.lstAction = obj.lstAction;
|
|
2834
|
+
this.editorOption = obj.editorOption || new WorkflowStageEditorOption();
|
|
2835
|
+
}
|
|
2836
|
+
}
|
|
2837
|
+
class WorkflowStageEditorOption {
|
|
2826
2838
|
x = 0;
|
|
2827
2839
|
y = 0;
|
|
2828
2840
|
isReverse;
|
|
2829
2841
|
isReverseLabel;
|
|
2830
|
-
lstAction;
|
|
2831
2842
|
drawerPosition;
|
|
2832
2843
|
constructor(obj) {
|
|
2833
2844
|
obj = obj || {};
|
|
2834
|
-
super(obj);
|
|
2835
2845
|
this.x = obj.x;
|
|
2836
2846
|
this.y = obj.y;
|
|
2837
2847
|
this.isReverse = obj.isReverse;
|
|
2838
2848
|
this.isReverseLabel = obj.isReverseLabel;
|
|
2839
|
-
this.lstAction = obj.lstAction;
|
|
2840
2849
|
this.drawerPosition = obj.drawerPosition;
|
|
2841
2850
|
}
|
|
2842
2851
|
}
|
|
@@ -2851,8 +2860,12 @@ class WorkflowAction extends WF_TemplateStageAction {
|
|
|
2851
2860
|
ToSide;
|
|
2852
2861
|
allowBack; // true = 2 đầu, false/undefined = 1 đầu
|
|
2853
2862
|
labelBack;
|
|
2854
|
-
points;
|
|
2855
2863
|
isBackAction;
|
|
2864
|
+
editorOption = new WorkflowActionEditorOption();
|
|
2865
|
+
}
|
|
2866
|
+
class WorkflowActionEditorOption {
|
|
2867
|
+
points;
|
|
2868
|
+
drawerPosition;
|
|
2856
2869
|
}
|
|
2857
2870
|
class WorkflowEditorComponent extends BaseComponent {
|
|
2858
2871
|
//#region NGHIỆP VỤ
|
|
@@ -2875,7 +2888,7 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
2875
2888
|
hoverStage;
|
|
2876
2889
|
selectedAction;
|
|
2877
2890
|
selectedBackAction;
|
|
2878
|
-
|
|
2891
|
+
hoverAction;
|
|
2879
2892
|
// vẽ đường liên kết mới
|
|
2880
2893
|
connectingFrom;
|
|
2881
2894
|
connectingPoints = [];
|
|
@@ -2918,11 +2931,11 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
2918
2931
|
canvasRef;
|
|
2919
2932
|
svgRef;
|
|
2920
2933
|
get normalEdges() {
|
|
2921
|
-
return this.lstAction.filter((e) => e !== this.
|
|
2934
|
+
return this.lstAction.filter((e) => e !== this.hoverAction && !e.isBackAction);
|
|
2922
2935
|
}
|
|
2923
2936
|
get hoverEdges() {
|
|
2924
|
-
if (this.
|
|
2925
|
-
return [this.
|
|
2937
|
+
if (this.hoverAction && !this.hoverAction.isBackAction) {
|
|
2938
|
+
return [this.hoverAction];
|
|
2926
2939
|
}
|
|
2927
2940
|
if (this.selectedAction && !this.selectedAction.isBackAction) {
|
|
2928
2941
|
return [this.selectedAction];
|
|
@@ -2973,10 +2986,24 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
2973
2986
|
}
|
|
2974
2987
|
}
|
|
2975
2988
|
ngOnInit() {
|
|
2976
|
-
console.log('ngOnInit'
|
|
2989
|
+
console.log('ngOnInit');
|
|
2977
2990
|
console.log('template', this.template);
|
|
2978
2991
|
console.log('lstStage', this.lstStage);
|
|
2979
2992
|
console.log('lstAction', this.lstAction);
|
|
2993
|
+
if (!this.lstStage || !this.lstStage.length) {
|
|
2994
|
+
this.lstStage = [
|
|
2995
|
+
{ Code: 'start', Name: 'Start', x: 5000 + -35, y: 5000 + 120, StageType: 'START', SeqValue: 1 },
|
|
2996
|
+
{
|
|
2997
|
+
Code: 'end',
|
|
2998
|
+
Name: 'End',
|
|
2999
|
+
x: 5000 + 120,
|
|
3000
|
+
y: 5000 + 380,
|
|
3001
|
+
StageType: 'END',
|
|
3002
|
+
isReverseLabel: true,
|
|
3003
|
+
SeqValue: 999,
|
|
3004
|
+
},
|
|
3005
|
+
];
|
|
3006
|
+
}
|
|
2980
3007
|
this.lstStage.forEach((x) => {
|
|
2981
3008
|
x.lstAction = this.lstAction.filter((y) => y.FromStage == x.Code);
|
|
2982
3009
|
});
|
|
@@ -2995,8 +3022,8 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
2995
3022
|
for (const n of this.lstStage) {
|
|
2996
3023
|
if (!this.lstSelectedStageCode.has(n.Code))
|
|
2997
3024
|
continue;
|
|
2998
|
-
n.x = this.clamp(n.x + dx, 0, this.CANVAS_WIDTH - this.NODE_WIDTH);
|
|
2999
|
-
n.y = this.clamp(n.y + dy, 0, this.CANVAS_HEIGHT - this.NODE_HEIGHT);
|
|
3025
|
+
n.editorOption.x = this.clamp(n.editorOption.x + dx, 0, this.CANVAS_WIDTH - this.NODE_WIDTH);
|
|
3026
|
+
n.editorOption.y = this.clamp(n.editorOption.y + dy, 0, this.CANVAS_HEIGHT - this.NODE_HEIGHT);
|
|
3000
3027
|
}
|
|
3001
3028
|
}
|
|
3002
3029
|
save() {
|
|
@@ -3006,8 +3033,8 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3006
3033
|
console.log('addStage');
|
|
3007
3034
|
const code = 'New_Stage_' + Math.round(Math.random() * 1000);
|
|
3008
3035
|
// tìm vị trí trống (đơn giản & hiệu quả)
|
|
3009
|
-
const baseX = 200;
|
|
3010
|
-
const baseY = 120;
|
|
3036
|
+
const baseX = 200 - this.panX;
|
|
3037
|
+
const baseY = 120 - this.panY;
|
|
3011
3038
|
const GAP_X = 200;
|
|
3012
3039
|
const GAP_Y = 120;
|
|
3013
3040
|
let x = baseX;
|
|
@@ -3018,8 +3045,8 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3018
3045
|
const stage = new WorkflowStage();
|
|
3019
3046
|
stage.Code = code;
|
|
3020
3047
|
stage.Name = 'New Stage';
|
|
3021
|
-
stage.x = x;
|
|
3022
|
-
stage.y = y;
|
|
3048
|
+
stage.editorOption.x = x;
|
|
3049
|
+
stage.editorOption.y = y;
|
|
3023
3050
|
stage.StageType = 'NODE';
|
|
3024
3051
|
stage.SeqValue = 10;
|
|
3025
3052
|
this.lstStage.push(stage);
|
|
@@ -3141,6 +3168,8 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3141
3168
|
return;
|
|
3142
3169
|
stage.lstAction = stage.lstAction?.filter((x) => x != action);
|
|
3143
3170
|
this.lstAction = this.lstAction.filter((x) => x != action);
|
|
3171
|
+
this.selectedAction = undefined;
|
|
3172
|
+
this.hoverAction = undefined;
|
|
3144
3173
|
}
|
|
3145
3174
|
//#endregion
|
|
3146
3175
|
//#region Action type
|
|
@@ -3165,11 +3194,10 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3165
3194
|
}, 10);
|
|
3166
3195
|
}
|
|
3167
3196
|
handleInputStageStatusConfirm() {
|
|
3168
|
-
if (this.inputStageStatusCode && !this.template.lstStageStatus
|
|
3169
|
-
this.template.lstStageStatus =
|
|
3170
|
-
...this.template.lstStageStatus,
|
|
3171
|
-
{ Code: this.inputStageStatusCode, Name: this.inputStageStatusName }
|
|
3172
|
-
];
|
|
3197
|
+
if (this.inputStageStatusCode && !this.template.lstStageStatus?.find((x) => x.Code === this.inputValue)) {
|
|
3198
|
+
this.template.lstStageStatus = this.template.lstStageStatus
|
|
3199
|
+
? [...this.template.lstStageStatus, { Code: this.inputStageStatusCode, Name: this.inputStageStatusName }]
|
|
3200
|
+
: [{ Code: this.inputStageStatusCode, Name: this.inputStageStatusName }];
|
|
3173
3201
|
}
|
|
3174
3202
|
this.inputStageStatusCode = '';
|
|
3175
3203
|
this.inputStageStatusName = '';
|
|
@@ -3203,11 +3231,10 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3203
3231
|
}, 10);
|
|
3204
3232
|
}
|
|
3205
3233
|
handleInputActionTypeConfirm() {
|
|
3206
|
-
if (this.inputActionTypeCode && !this.template.lstActionType
|
|
3207
|
-
this.template.lstActionType =
|
|
3208
|
-
...this.template.lstActionType,
|
|
3209
|
-
{ Code: this.inputActionTypeCode, Name: this.inputActionTypeName }
|
|
3210
|
-
];
|
|
3234
|
+
if (this.inputActionTypeCode && !this.template.lstActionType?.find((x) => x.Code === this.inputValue)) {
|
|
3235
|
+
this.template.lstActionType = this.template.lstActionType
|
|
3236
|
+
? [...this.template.lstActionType, { Code: this.inputActionTypeCode, Name: this.inputActionTypeName }]
|
|
3237
|
+
: [{ Code: this.inputActionTypeCode, Name: this.inputActionTypeName }];
|
|
3211
3238
|
}
|
|
3212
3239
|
this.inputActionTypeCode = '';
|
|
3213
3240
|
this.inputActionTypeName = '';
|
|
@@ -3235,8 +3262,10 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3235
3262
|
}, 10);
|
|
3236
3263
|
}
|
|
3237
3264
|
handleInputConfirm() {
|
|
3238
|
-
if (this.inputValue && !this.template.lstActionStatus
|
|
3239
|
-
this.template.lstActionStatus =
|
|
3265
|
+
if (this.inputValue && !this.template.lstActionStatus?.find((x) => x.Code === this.inputValue)) {
|
|
3266
|
+
this.template.lstActionStatus = this.template.lstActionStatus
|
|
3267
|
+
? [...this.template.lstActionStatus, { Code: this.inputValue }]
|
|
3268
|
+
: [{ Code: this.inputValue }];
|
|
3240
3269
|
}
|
|
3241
3270
|
this.inputValue = '';
|
|
3242
3271
|
this.inputVisible = false;
|
|
@@ -3341,14 +3370,14 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3341
3370
|
if (!this.lstSelectedStageCode.has(n.Code))
|
|
3342
3371
|
continue;
|
|
3343
3372
|
const start = this.dragStartPositions.get(n.Code);
|
|
3344
|
-
n.x = start.x + clampedDx;
|
|
3345
|
-
n.y = start.y + clampedDy;
|
|
3373
|
+
n.editorOption.x = start.x + clampedDx;
|
|
3374
|
+
n.editorOption.y = start.y + clampedDy;
|
|
3346
3375
|
}
|
|
3347
3376
|
// 🔹 move edge points
|
|
3348
3377
|
for (const [edge, startPoints] of this.dragStartEdgePoints.entries()) {
|
|
3349
|
-
if (!edge.points)
|
|
3378
|
+
if (!edge.editorOption.points)
|
|
3350
3379
|
continue;
|
|
3351
|
-
edge.points.forEach((pt, i) => {
|
|
3380
|
+
edge.editorOption.points.forEach((pt, i) => {
|
|
3352
3381
|
pt.x = startPoints[i].x + dx;
|
|
3353
3382
|
pt.y = startPoints[i].y + dy;
|
|
3354
3383
|
});
|
|
@@ -3372,18 +3401,18 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3372
3401
|
let rawY = p.y - this.offsetY;
|
|
3373
3402
|
// ⭐ khoá trục
|
|
3374
3403
|
if (event.shiftKey && this.axisLock === 'x') {
|
|
3375
|
-
rawY = this.draggingNode.y;
|
|
3404
|
+
rawY = this.draggingNode.editorOption.y;
|
|
3376
3405
|
}
|
|
3377
3406
|
if (event.shiftKey && this.axisLock === 'y') {
|
|
3378
|
-
rawX = this.draggingNode.x;
|
|
3407
|
+
rawX = this.draggingNode.editorOption.x;
|
|
3379
3408
|
}
|
|
3380
3409
|
const snap = this.snapPoint({ x: rawX, y: rawY }, event);
|
|
3381
3410
|
// this.draggingNode.x = snap.x;
|
|
3382
3411
|
// this.draggingNode.y = snap.y;
|
|
3383
3412
|
const nodeW = this.NODE_WIDTH;
|
|
3384
3413
|
const nodeH = this.NODE_HEIGHT;
|
|
3385
|
-
this.draggingNode.x = this.clamp(snap.x, 0, this.CANVAS_WIDTH - nodeW);
|
|
3386
|
-
this.draggingNode.y = this.clamp(snap.y, 0, this.CANVAS_HEIGHT - nodeH);
|
|
3414
|
+
this.draggingNode.editorOption.x = this.clamp(snap.x, 0, this.CANVAS_WIDTH - nodeW);
|
|
3415
|
+
this.draggingNode.editorOption.y = this.clamp(snap.y, 0, this.CANVAS_HEIGHT - nodeH);
|
|
3387
3416
|
return;
|
|
3388
3417
|
}
|
|
3389
3418
|
// 3️⃣ đang kéo waypoint
|
|
@@ -3444,16 +3473,16 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3444
3473
|
this.dragStartPositions.clear();
|
|
3445
3474
|
for (const n of this.lstStage) {
|
|
3446
3475
|
if (this.lstSelectedStageCode.has(n.Code)) {
|
|
3447
|
-
this.dragStartPositions.set(n.Code, { x: n.x, y: n.y });
|
|
3476
|
+
this.dragStartPositions.set(n.Code, { x: n.editorOption.x, y: n.editorOption.y });
|
|
3448
3477
|
}
|
|
3449
3478
|
}
|
|
3450
3479
|
// 🔹 snapshot edge points
|
|
3451
3480
|
this.dragStartEdgePoints = new Map();
|
|
3452
3481
|
for (const e of this.lstAction) {
|
|
3453
|
-
if (!e.points?.length)
|
|
3482
|
+
if (!e.editorOption.points?.length)
|
|
3454
3483
|
continue;
|
|
3455
3484
|
if (this.lstSelectedStageCode.has(e.FromStage || '') || this.lstSelectedStageCode.has(e.ToStage || '')) {
|
|
3456
|
-
this.dragStartEdgePoints.set(e, e.points.map((p) => ({ x: p.x, y: p.y })));
|
|
3485
|
+
this.dragStartEdgePoints.set(e, e.editorOption.points.map((p) => ({ x: p.x, y: p.y })));
|
|
3457
3486
|
}
|
|
3458
3487
|
}
|
|
3459
3488
|
return;
|
|
@@ -3471,8 +3500,8 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3471
3500
|
this.draggingNode = node;
|
|
3472
3501
|
this.dragStartX = event.clientX;
|
|
3473
3502
|
this.dragStartY = event.clientY;
|
|
3474
|
-
this.offsetX = event.clientX - node.x;
|
|
3475
|
-
this.offsetY = event.clientY - node.y;
|
|
3503
|
+
this.offsetX = event.clientX - node.editorOption.x;
|
|
3504
|
+
this.offsetY = event.clientY - node.editorOption.y;
|
|
3476
3505
|
this.isDragging = false;
|
|
3477
3506
|
}
|
|
3478
3507
|
onClickStage(node) {
|
|
@@ -3491,7 +3520,7 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3491
3520
|
newAction.ToSide = 'left';
|
|
3492
3521
|
// ⭐ NẾU CÓ WAYPOINT → MANUAL ROUTE
|
|
3493
3522
|
if (this.connectingPoints.length > 0) {
|
|
3494
|
-
newAction.points = [...this.connectingPoints];
|
|
3523
|
+
newAction.editorOption.points = [...this.connectingPoints];
|
|
3495
3524
|
}
|
|
3496
3525
|
this.lstAction.push(newAction);
|
|
3497
3526
|
const stage = this.lstStage.find((x) => x.Code == newAction.FromStage);
|
|
@@ -3517,14 +3546,14 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3517
3546
|
// console.log('onMouseEnterEdge', e);
|
|
3518
3547
|
if (this.connectingFrom)
|
|
3519
3548
|
return;
|
|
3520
|
-
this.
|
|
3521
|
-
this.connectingPoints = e.points || [];
|
|
3549
|
+
this.hoverAction = e;
|
|
3550
|
+
this.connectingPoints = e.editorOption.points || [];
|
|
3522
3551
|
}
|
|
3523
3552
|
onMouseLeaveEdge(e) {
|
|
3524
3553
|
// console.log('onEdgeLeave', e);
|
|
3525
3554
|
if (this.connectingFrom)
|
|
3526
3555
|
return;
|
|
3527
|
-
this.
|
|
3556
|
+
this.hoverAction = undefined;
|
|
3528
3557
|
this.connectingPoints = [];
|
|
3529
3558
|
}
|
|
3530
3559
|
edgeClickTimer = null;
|
|
@@ -3560,11 +3589,11 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3560
3589
|
event.preventDefault();
|
|
3561
3590
|
const p = this.getSvgPoint(event, true);
|
|
3562
3591
|
// Nếu edge chưa có manual points → convert auto → manual
|
|
3563
|
-
if (!edge.points || edge.points.length === 0) {
|
|
3564
|
-
edge.points = [];
|
|
3592
|
+
if (!edge.editorOption.points || edge.editorOption.points.length === 0) {
|
|
3593
|
+
edge.editorOption.points = [];
|
|
3565
3594
|
}
|
|
3566
3595
|
const insertIndex = this.findInsertIndex(edge, p);
|
|
3567
|
-
edge.points.splice(insertIndex, 0, {
|
|
3596
|
+
edge.editorOption.points.splice(insertIndex, 0, {
|
|
3568
3597
|
x: p.x,
|
|
3569
3598
|
y: p.y,
|
|
3570
3599
|
});
|
|
@@ -3603,7 +3632,7 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3603
3632
|
newAction.ToSide = 'left';
|
|
3604
3633
|
// ⭐ NẾU CÓ WAYPOINT → MANUAL ROUTE
|
|
3605
3634
|
if (this.connectingPoints.length > 0) {
|
|
3606
|
-
newAction.points = [...this.connectingPoints];
|
|
3635
|
+
newAction.editorOption.points = [...this.connectingPoints];
|
|
3607
3636
|
}
|
|
3608
3637
|
this.lstAction.push(newAction);
|
|
3609
3638
|
const stage = this.lstStage.find((x) => x.Code == newAction.FromStage);
|
|
@@ -3634,12 +3663,12 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3634
3663
|
console.log('onRightClickPoint', edge, index);
|
|
3635
3664
|
event.preventDefault();
|
|
3636
3665
|
event.stopPropagation();
|
|
3637
|
-
if (!edge.points)
|
|
3666
|
+
if (!edge.editorOption.points)
|
|
3638
3667
|
return;
|
|
3639
|
-
edge.points.splice(index, 1);
|
|
3668
|
+
edge.editorOption.points.splice(index, 1);
|
|
3640
3669
|
// Nếu xoá hết → quay về auto route
|
|
3641
|
-
if (edge.points.length === 0) {
|
|
3642
|
-
delete edge.points;
|
|
3670
|
+
if (edge.editorOption.points.length === 0) {
|
|
3671
|
+
delete edge.editorOption.points;
|
|
3643
3672
|
}
|
|
3644
3673
|
}
|
|
3645
3674
|
//#endregion
|
|
@@ -3650,7 +3679,7 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3650
3679
|
const map = new Map();
|
|
3651
3680
|
for (const n of this.lstStage) {
|
|
3652
3681
|
if (nodeIds.has(n.Code)) {
|
|
3653
|
-
map.set(n.Code, { x: n.x, y: n.y });
|
|
3682
|
+
map.set(n.Code, { x: n.editorOption.x, y: n.editorOption.y });
|
|
3654
3683
|
}
|
|
3655
3684
|
}
|
|
3656
3685
|
return map;
|
|
@@ -3694,8 +3723,8 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3694
3723
|
action.before.forEach((pos, id) => {
|
|
3695
3724
|
const node = this.lstStage.find((n) => n.Code === id);
|
|
3696
3725
|
if (node) {
|
|
3697
|
-
node.x = pos.x;
|
|
3698
|
-
node.y = pos.y;
|
|
3726
|
+
node.editorOption.x = pos.x;
|
|
3727
|
+
node.editorOption.y = pos.y;
|
|
3699
3728
|
}
|
|
3700
3729
|
});
|
|
3701
3730
|
}
|
|
@@ -3728,8 +3757,8 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3728
3757
|
action.before.forEach((pos, id) => {
|
|
3729
3758
|
const node = this.lstStage.find((n) => n.Code === id);
|
|
3730
3759
|
if (node) {
|
|
3731
|
-
node.x = pos.x;
|
|
3732
|
-
node.y = pos.y;
|
|
3760
|
+
node.editorOption.x = pos.x;
|
|
3761
|
+
node.editorOption.y = pos.y;
|
|
3733
3762
|
}
|
|
3734
3763
|
});
|
|
3735
3764
|
}
|
|
@@ -3749,18 +3778,18 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3749
3778
|
return;
|
|
3750
3779
|
this.pushAlignUndo();
|
|
3751
3780
|
const nodes = this.getSelectedNodes();
|
|
3752
|
-
const minX = Math.min(...nodes.map((n) => n.x));
|
|
3753
|
-
nodes.forEach((n) => (n.x = minX));
|
|
3781
|
+
const minX = Math.min(...nodes.map((n) => n.editorOption.x));
|
|
3782
|
+
nodes.forEach((n) => (n.editorOption.x = minX));
|
|
3754
3783
|
}
|
|
3755
3784
|
alignCenter() {
|
|
3756
3785
|
if (this.lstSelectedStageCode.size < 2)
|
|
3757
3786
|
return;
|
|
3758
3787
|
this.pushAlignUndo();
|
|
3759
3788
|
const nodes = this.getSelectedNodes();
|
|
3760
|
-
const centers = nodes.map((n) => n.x + this.NODE_WIDTH / 2);
|
|
3789
|
+
const centers = nodes.map((n) => n.editorOption.x + this.NODE_WIDTH / 2);
|
|
3761
3790
|
const centerX = centers.reduce((a, b) => a + b) / centers.length;
|
|
3762
3791
|
nodes.forEach((n) => {
|
|
3763
|
-
n.x = centerX - this.NODE_WIDTH / 2;
|
|
3792
|
+
n.editorOption.x = centerX - this.NODE_WIDTH / 2;
|
|
3764
3793
|
});
|
|
3765
3794
|
}
|
|
3766
3795
|
alignRight() {
|
|
@@ -3768,26 +3797,26 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3768
3797
|
return;
|
|
3769
3798
|
this.pushAlignUndo();
|
|
3770
3799
|
const nodes = this.getSelectedNodes();
|
|
3771
|
-
const maxX = Math.max(...nodes.map((n) => n.x + this.NODE_WIDTH));
|
|
3772
|
-
nodes.forEach((n) => (n.x = maxX - this.NODE_WIDTH));
|
|
3800
|
+
const maxX = Math.max(...nodes.map((n) => n.editorOption.x + this.NODE_WIDTH));
|
|
3801
|
+
nodes.forEach((n) => (n.editorOption.x = maxX - this.NODE_WIDTH));
|
|
3773
3802
|
}
|
|
3774
3803
|
alignTop() {
|
|
3775
3804
|
if (this.lstSelectedStageCode.size < 2)
|
|
3776
3805
|
return;
|
|
3777
3806
|
this.pushAlignUndo();
|
|
3778
3807
|
const nodes = this.getSelectedNodes();
|
|
3779
|
-
const minY = Math.min(...nodes.map((n) => n.y));
|
|
3780
|
-
nodes.forEach((n) => (n.y = minY));
|
|
3808
|
+
const minY = Math.min(...nodes.map((n) => n.editorOption.y));
|
|
3809
|
+
nodes.forEach((n) => (n.editorOption.y = minY));
|
|
3781
3810
|
}
|
|
3782
3811
|
alignMiddle() {
|
|
3783
3812
|
if (this.lstSelectedStageCode.size < 2)
|
|
3784
3813
|
return;
|
|
3785
3814
|
this.pushAlignUndo();
|
|
3786
3815
|
const nodes = this.getSelectedNodes();
|
|
3787
|
-
const centers = nodes.map((n) => n.y + this.NODE_HEIGHT / 2);
|
|
3816
|
+
const centers = nodes.map((n) => n.editorOption.y + this.NODE_HEIGHT / 2);
|
|
3788
3817
|
const centerY = centers.reduce((a, b) => a + b) / centers.length;
|
|
3789
3818
|
nodes.forEach((n) => {
|
|
3790
|
-
n.y = centerY - this.NODE_HEIGHT / 2;
|
|
3819
|
+
n.editorOption.y = centerY - this.NODE_HEIGHT / 2;
|
|
3791
3820
|
});
|
|
3792
3821
|
}
|
|
3793
3822
|
alignBottom() {
|
|
@@ -3795,25 +3824,25 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3795
3824
|
return;
|
|
3796
3825
|
this.pushAlignUndo();
|
|
3797
3826
|
const nodes = this.getSelectedNodes();
|
|
3798
|
-
const maxY = Math.max(...nodes.map((n) => n.y + this.NODE_HEIGHT));
|
|
3799
|
-
nodes.forEach((n) => (n.y = maxY - this.NODE_HEIGHT));
|
|
3827
|
+
const maxY = Math.max(...nodes.map((n) => n.editorOption.y + this.NODE_HEIGHT));
|
|
3828
|
+
nodes.forEach((n) => (n.editorOption.y = maxY - this.NODE_HEIGHT));
|
|
3800
3829
|
}
|
|
3801
3830
|
distributeHorizontal() {
|
|
3802
3831
|
if (this.lstSelectedStageCode.size < 3)
|
|
3803
3832
|
return;
|
|
3804
3833
|
this.pushAlignUndo();
|
|
3805
|
-
const nodes = this.getSelectedNodes().sort((a, b) => a.x - b.x);
|
|
3834
|
+
const nodes = this.getSelectedNodes().sort((a, b) => a.editorOption.x - b.editorOption.x);
|
|
3806
3835
|
const first = nodes[0];
|
|
3807
3836
|
const last = nodes[nodes.length - 1];
|
|
3808
3837
|
const totalWidth = nodes.reduce((s, n) => s + this.NODE_WIDTH, 0);
|
|
3809
|
-
const space = (last.x - first.x - totalWidth + this.NODE_WIDTH) / (nodes.length - 1);
|
|
3810
|
-
let x = first.x;
|
|
3838
|
+
const space = (last.editorOption.x - first.editorOption.x - totalWidth + this.NODE_WIDTH) / (nodes.length - 1);
|
|
3839
|
+
let x = first.editorOption.x;
|
|
3811
3840
|
nodes.forEach((n, i) => {
|
|
3812
3841
|
if (i === 0 || i === nodes.length - 1) {
|
|
3813
|
-
x = n.x + this.NODE_WIDTH + space;
|
|
3842
|
+
x = n.editorOption.x + this.NODE_WIDTH + space;
|
|
3814
3843
|
return;
|
|
3815
3844
|
}
|
|
3816
|
-
n.x = x;
|
|
3845
|
+
n.editorOption.x = x;
|
|
3817
3846
|
x += this.NODE_WIDTH + space;
|
|
3818
3847
|
});
|
|
3819
3848
|
}
|
|
@@ -3821,18 +3850,18 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3821
3850
|
if (this.lstSelectedStageCode.size < 3)
|
|
3822
3851
|
return;
|
|
3823
3852
|
this.pushAlignUndo();
|
|
3824
|
-
const nodes = this.getSelectedNodes().sort((a, b) => a.y - b.y);
|
|
3853
|
+
const nodes = this.getSelectedNodes().sort((a, b) => a.editorOption.y - b.editorOption.y);
|
|
3825
3854
|
const first = nodes[0];
|
|
3826
3855
|
const last = nodes[nodes.length - 1];
|
|
3827
3856
|
const totalHeight = nodes.reduce((s, n) => s + this.NODE_HEIGHT, 0);
|
|
3828
|
-
const space = (last.y - first.y - totalHeight + this.NODE_HEIGHT) / (nodes.length - 1);
|
|
3829
|
-
let y = first.y;
|
|
3857
|
+
const space = (last.editorOption.y - first.editorOption.y - totalHeight + this.NODE_HEIGHT) / (nodes.length - 1);
|
|
3858
|
+
let y = first.editorOption.y;
|
|
3830
3859
|
nodes.forEach((n, i) => {
|
|
3831
3860
|
if (i === 0 || i === nodes.length - 1) {
|
|
3832
|
-
y = n.y + this.NODE_HEIGHT + space;
|
|
3861
|
+
y = n.editorOption.y + this.NODE_HEIGHT + space;
|
|
3833
3862
|
return;
|
|
3834
3863
|
}
|
|
3835
|
-
n.y = y;
|
|
3864
|
+
n.editorOption.y = y;
|
|
3836
3865
|
y += this.NODE_HEIGHT + space;
|
|
3837
3866
|
});
|
|
3838
3867
|
}
|
|
@@ -3866,8 +3895,8 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3866
3895
|
}
|
|
3867
3896
|
getEdgeLabelPosition(edge) {
|
|
3868
3897
|
// Ưu tiên waypoint giữa nếu có
|
|
3869
|
-
if (edge.points && edge.points.length > 0) {
|
|
3870
|
-
const mid = edge.points[Math.floor(edge.points.length / 2)];
|
|
3898
|
+
if (edge.editorOption.points && edge.editorOption.points.length > 0) {
|
|
3899
|
+
const mid = edge.editorOption.points[Math.floor(edge.editorOption.points.length / 2)];
|
|
3871
3900
|
return { x: mid.x, y: mid.y };
|
|
3872
3901
|
}
|
|
3873
3902
|
// fallback: giữa from → to
|
|
@@ -3886,23 +3915,23 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3886
3915
|
switch (side) {
|
|
3887
3916
|
case 'left':
|
|
3888
3917
|
return {
|
|
3889
|
-
x: node.x,
|
|
3890
|
-
y: node.y + height / 2,
|
|
3918
|
+
x: node.editorOption.x,
|
|
3919
|
+
y: node.editorOption.y + height / 2,
|
|
3891
3920
|
};
|
|
3892
3921
|
case 'right':
|
|
3893
3922
|
return {
|
|
3894
|
-
x: node.x + width,
|
|
3895
|
-
y: node.y + height / 2,
|
|
3923
|
+
x: node.editorOption.x + width,
|
|
3924
|
+
y: node.editorOption.y + height / 2,
|
|
3896
3925
|
};
|
|
3897
3926
|
case 'top':
|
|
3898
3927
|
return {
|
|
3899
|
-
x: node.x + width / 2,
|
|
3900
|
-
y: node.y,
|
|
3928
|
+
x: node.editorOption.x + width / 2,
|
|
3929
|
+
y: node.editorOption.y,
|
|
3901
3930
|
};
|
|
3902
3931
|
case 'bottom':
|
|
3903
3932
|
return {
|
|
3904
|
-
x: node.x + width / 2,
|
|
3905
|
-
y: node.y + height,
|
|
3933
|
+
x: node.editorOption.x + width / 2,
|
|
3934
|
+
y: node.editorOption.y + height,
|
|
3906
3935
|
};
|
|
3907
3936
|
}
|
|
3908
3937
|
}
|
|
@@ -3935,7 +3964,11 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3935
3964
|
return null;
|
|
3936
3965
|
const from = this.getNode(edge.FromStage);
|
|
3937
3966
|
const to = this.getNode(edge.ToStage);
|
|
3938
|
-
return [
|
|
3967
|
+
return [
|
|
3968
|
+
{ x: from.editorOption.x + 160, y: from.editorOption.y + 40 },
|
|
3969
|
+
...(edge.editorOption.points || []),
|
|
3970
|
+
{ x: to.editorOption.x, y: to.editorOption.y + 40 },
|
|
3971
|
+
];
|
|
3939
3972
|
}
|
|
3940
3973
|
pointToSegmentDistance(p, a, b) {
|
|
3941
3974
|
const dx = b.x - a.x;
|
|
@@ -3952,20 +3985,20 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3952
3985
|
return Math.hypot(p.x - proj.x, p.y - proj.y);
|
|
3953
3986
|
}
|
|
3954
3987
|
isPositionOccupied(x, y) {
|
|
3955
|
-
return this.lstStage.some((n) => Math.abs(n.x - x) < 160 && Math.abs(n.y - y) < 80);
|
|
3988
|
+
return this.lstStage.some((n) => Math.abs(n.editorOption.x - x) < 160 && Math.abs(n.editorOption.y - y) < 80);
|
|
3956
3989
|
}
|
|
3957
3990
|
getCanvasWidth() {
|
|
3958
3991
|
// return 3000;
|
|
3959
3992
|
const PADDING = 200;
|
|
3960
3993
|
const MIN_WIDTH = 800;
|
|
3961
|
-
const maxX = Math.max(...this.lstStage.map((n) => (n.StageType == 'END' ? n.x : n.x + 160)), // 160 = node width
|
|
3994
|
+
const maxX = Math.max(...this.lstStage.map((n) => (n.StageType == 'END' ? n.editorOption.x : n.editorOption.x + 160)), // 160 = node width
|
|
3962
3995
|
MIN_WIDTH);
|
|
3963
3996
|
return maxX + PADDING;
|
|
3964
3997
|
}
|
|
3965
3998
|
getCanvasHeight() {
|
|
3966
3999
|
// return 2000;
|
|
3967
4000
|
const PADDING = 100;
|
|
3968
|
-
const maxY = Math.max(...this.lstStage.map((n) => n.y + 80), 400);
|
|
4001
|
+
const maxY = Math.max(...this.lstStage.map((n) => n.editorOption.y + 80), 400);
|
|
3969
4002
|
return maxY + PADDING;
|
|
3970
4003
|
}
|
|
3971
4004
|
/* =============================
|
|
@@ -3993,10 +4026,10 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
3993
4026
|
const y2 = Math.max(this.selectStart.y, this.selectEnd.y);
|
|
3994
4027
|
this.lstSelectedStageCode.clear();
|
|
3995
4028
|
for (const n of this.lstStage) {
|
|
3996
|
-
const nx1 = n.x;
|
|
3997
|
-
const ny1 = n.y;
|
|
3998
|
-
const nx2 = n.x + 160;
|
|
3999
|
-
const ny2 = n.y + 80;
|
|
4029
|
+
const nx1 = n.editorOption.x;
|
|
4030
|
+
const ny1 = n.editorOption.y;
|
|
4031
|
+
const nx2 = n.editorOption.x + 160;
|
|
4032
|
+
const ny2 = n.editorOption.y + 80;
|
|
4000
4033
|
const intersect = nx2 >= x1 && nx1 <= x2 && ny2 >= y1 && ny1 <= y2;
|
|
4001
4034
|
if (intersect) {
|
|
4002
4035
|
this.lstSelectedStageCode.add(n.Code);
|
|
@@ -4027,15 +4060,15 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
4027
4060
|
const from = this.getNode(edge.FromStage);
|
|
4028
4061
|
const to = this.getNode(edge.ToStage);
|
|
4029
4062
|
const start = {
|
|
4030
|
-
x: from.x + (from.isReverse ? 0 : 160),
|
|
4031
|
-
y: from.y + 40,
|
|
4063
|
+
x: from.editorOption.x + (from.editorOption.isReverse ? 0 : 160),
|
|
4064
|
+
y: from.editorOption.y + 40,
|
|
4032
4065
|
};
|
|
4033
4066
|
const end = {
|
|
4034
|
-
x: to.x + (to.isReverse ? 160 : 0),
|
|
4035
|
-
y: to.y + 40,
|
|
4067
|
+
x: to.editorOption.x + (to.editorOption.isReverse ? 160 : 0),
|
|
4068
|
+
y: to.editorOption.y + 40,
|
|
4036
4069
|
};
|
|
4037
|
-
if (edge.points && edge.points.length) {
|
|
4038
|
-
return this.buildPathThroughPoints([start, ...edge.points, end]);
|
|
4070
|
+
if (edge.editorOption.points && edge.editorOption.points.length) {
|
|
4071
|
+
return this.buildPathThroughPoints([start, ...edge.editorOption.points, end]);
|
|
4039
4072
|
}
|
|
4040
4073
|
// return this.buildRoutedPath({ node: from, side: edge.fromSide }, to.x, to.y + 40);
|
|
4041
4074
|
return this.buildStragePath(start.x, start.y, end.x, end.y);
|
|
@@ -4044,8 +4077,8 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
4044
4077
|
if (!this.connectingFrom)
|
|
4045
4078
|
return '';
|
|
4046
4079
|
const start = {
|
|
4047
|
-
x: this.connectingFrom.node.x + (this.connectingFrom.node.isReverse ? 0 : 160),
|
|
4048
|
-
y: this.connectingFrom.node.y + 40,
|
|
4080
|
+
x: this.connectingFrom.node.editorOption.x + (this.connectingFrom.node.editorOption.isReverse ? 0 : 160),
|
|
4081
|
+
y: this.connectingFrom.node.editorOption.y + 40,
|
|
4049
4082
|
};
|
|
4050
4083
|
const end = {
|
|
4051
4084
|
x: this.previewX,
|
|
@@ -4086,8 +4119,8 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
4086
4119
|
`;
|
|
4087
4120
|
}
|
|
4088
4121
|
buildRoutedPath(from, toX, toY, ARROW_GAP = 12) {
|
|
4089
|
-
const x1 = from.node.isReverse ? from.node.x : from.node.x + 160;
|
|
4090
|
-
const y1 = from.node.y + 40;
|
|
4122
|
+
const x1 = from.node.editorOption.isReverse ? from.node.editorOption.x : from.node.editorOption.x + 160;
|
|
4123
|
+
const y1 = from.node.editorOption.y + 40;
|
|
4091
4124
|
const x2 = toX;
|
|
4092
4125
|
const y2 = toY;
|
|
4093
4126
|
// const ARROW_GAP = 12;
|
|
@@ -4188,8 +4221,8 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
4188
4221
|
};
|
|
4189
4222
|
}
|
|
4190
4223
|
isBlockedPoint(from, x2, y2) {
|
|
4191
|
-
const x1 = from.node.isReverse ? from.node.x + 160 : from.node.x;
|
|
4192
|
-
const y1 = from.node.y + 40;
|
|
4224
|
+
const x1 = from.node.editorOption.isReverse ? from.node.editorOption.x + 160 : from.node.editorOption.x;
|
|
4225
|
+
const y1 = from.node.editorOption.y + 40;
|
|
4193
4226
|
return this.lstStage.some((n) => {
|
|
4194
4227
|
if (n.Code === from.node.Code)
|
|
4195
4228
|
return false;
|
|
@@ -4201,7 +4234,7 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
4201
4234
|
});
|
|
4202
4235
|
}
|
|
4203
4236
|
findBestRouteY(from, toX, toY) {
|
|
4204
|
-
const baseY = from.node.y + 40;
|
|
4237
|
+
const baseY = from.node.editorOption.y + 40;
|
|
4205
4238
|
const OFFSETS = [0, 80, -80, 160, -160, 240, -240];
|
|
4206
4239
|
for (const offset of OFFSETS) {
|
|
4207
4240
|
const routeY = baseY + offset;
|
|
@@ -4213,20 +4246,20 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
4213
4246
|
return baseY + OFFSETS[OFFSETS.length - 1];
|
|
4214
4247
|
}
|
|
4215
4248
|
isNodeBetweenX(fromX, toX, node) {
|
|
4216
|
-
const nx1 = node.x;
|
|
4217
|
-
const nx2 = node.x + 160;
|
|
4249
|
+
const nx1 = node.editorOption.x;
|
|
4250
|
+
const nx2 = node.editorOption.x + 160;
|
|
4218
4251
|
const minX = Math.min(fromX, toX);
|
|
4219
4252
|
const maxX = Math.max(fromX, toX);
|
|
4220
4253
|
return nx2 > minX && nx1 < maxX;
|
|
4221
4254
|
}
|
|
4222
4255
|
doesLineCrossNodeY(y, node, tolerance = 6) {
|
|
4223
|
-
const top = node.y;
|
|
4224
|
-
const bottom = node.y + 80;
|
|
4256
|
+
const top = node.editorOption.y;
|
|
4257
|
+
const bottom = node.editorOption.y + 80;
|
|
4225
4258
|
return y > top + tolerance && y < bottom - tolerance;
|
|
4226
4259
|
}
|
|
4227
4260
|
isLaneClear(from, toX, routeY) {
|
|
4228
|
-
const x1 = from.node.x;
|
|
4229
|
-
const y1 = from.node.y + 40;
|
|
4261
|
+
const x1 = from.node.editorOption.x;
|
|
4262
|
+
const y1 = from.node.editorOption.y + 40;
|
|
4230
4263
|
const x2 = toX;
|
|
4231
4264
|
const y2 = routeY;
|
|
4232
4265
|
return !this.lstStage.some((n) => {
|
|
@@ -4240,7 +4273,7 @@ class WorkflowEditorComponent extends BaseComponent {
|
|
|
4240
4273
|
});
|
|
4241
4274
|
}
|
|
4242
4275
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.7", ngImport: i0, type: WorkflowEditorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
4243
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.7", type: WorkflowEditorComponent, isStandalone: true, selector: "app-workflow-editor", inputs: { lstOrg: "lstOrg", lstTemplateType: "lstTemplateType", lstTemplatePrint: "lstTemplatePrint", template: "template", lstStage: "lstStage", lstAction: "lstAction" }, outputs: { onSave: "onSave" }, host: { listeners: { "window:keydown": "onKeyDown($event)" } }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["canvas"], descendants: true, static: true }, { propertyName: "svgRef", first: true, predicate: ["svg"], descendants: true, static: true }, { propertyName: "inputStageStatusElement", first: true, predicate: ["inputStageStatusElement"], descendants: true }, { propertyName: "inputActionTypeElement", first: true, predicate: ["inputActionTypeElement"], descendants: true }, { propertyName: "inputElement", first: true, predicate: ["inputElement"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div\n #canvasRef\n class=\"workflow-canvas\"\n [class.connecting]=\"!!connectingFrom\"\n [class.dragging-point]=\"!!draggingPoint\"\n [style.width.px]=\"CANVAS_WIDTH\"\n [style.height.px]=\"CANVAS_HEIGHT\"\n (mousedown)=\"onMouseDownCanvas($event)\"\n (mousemove)=\"onMouseMoveCanvas($event)\"\n (mouseup)=\"onMouseUpCanvas($event)\"\n (click)=\"onClickCanvas($event)\"\n>\n <!-- \n\n [style.width.px]=\"getCanvasWidth()\"\n [style.height.px]=\"getCanvasHeight()\" \n\n style=\"width: 100%; height: calc(100vh - 120px)\"\n \n -->\n\n <div class=\"toolbar\" (mousedown)=\"$event.stopPropagation()\" (click)=\"$event.stopPropagation()\">\n <button nz-button nzSize=\"small\" nz-tooltip=\"Editor setting\" (click)=\"settingVisible = true\">\n <nz-icon nzType=\"setting\"></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <button nz-button nzSize=\"small\" nz-tooltip=\"Template setting\" (click)=\"drawTemplateVisibel = true\">\n <nz-icon nzType=\"setting\"></nz-icon> T\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <button nz-button nzSize=\"small\" nzDanger nz-tooltip=\"Save\" (click)=\"save()\">\n <nz-icon nzType=\"save\"></nz-icon>\n </button>\n <button nz-button nzSize=\"small\" nz-tooltip=\"Add stage\" (click)=\"addStage()\">\n <nz-icon nzType=\"plus\" class=\"color-primary\"></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <button\n nz-button\n nzSize=\"small\"\n [nzType]=\"isMoveMode ? 'primary' : 'default'\"\n nz-tooltip=\"Move mode\"\n (click)=\"isMoveMode = true\"\n >\n <nz-icon><img src=\"/assets/icon/hand-palm.png\" width=\"19\" height=\"19\" /></nz-icon>\n </button>\n <button\n nz-button\n nzSize=\"small\"\n [nzType]=\"!isMoveMode ? 'primary' : 'default'\"\n nz-tooltip=\"Select mode\"\n (click)=\"isMoveMode = false\"\n >\n <nz-icon><img src=\"/assets/icon/cursor.png\" width=\"19\" height=\"19\" /></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <!-- UNDO / REDO -->\n <button\n nz-button\n nzSize=\"small\"\n nzType=\"default\"\n [disabled]=\"undoStack.length === 0\"\n nz-tooltip=\"Undo\"\n (click)=\"undo()\"\n >\n <nz-icon nzType=\"undo\"></nz-icon>\n </button>\n\n <button\n nz-button\n nzSize=\"small\"\n nzType=\"default\"\n [disabled]=\"redoStack.length === 0\"\n nz-tooltip=\"Redo\"\n (click)=\"redo()\"\n >\n <nz-icon nzType=\"redo\"></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <!-- ALIGN -->\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignLeft()\">\u27F8</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignCenter()\">\u2261</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignRight()\">\u27F9</button>\n\n <span class=\"divider\"></span>\n\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignTop()\">\u21D1</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignMiddle()\">\u2550</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignBottom()\">\u21D3</button>\n\n <span class=\"divider\"></span>\n\n <!-- DISTRIBUTE -->\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 3\" (click)=\"distributeHorizontal()\">\n \u21C4\n </button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 3\" (click)=\"distributeVertical()\">\n \u21C5\n </button>\n </div>\n\n <div\n class=\"canvas-content\"\n [class.panning]=\"isMoveMode\"\n [style.transform]=\"'translate(' + panX + 'px,' + panY + 'px)'\"\n >\n <!-- GRID -->\n <div *ngIf=\"wfcSetting.ShowGrid\" class=\"grid-layer\"></div>\n\n <!-- <div class=\"zoom-toolbar\">\n <button nz-button nzSize=\"small\" (click)=\"zoomOut()\">\u2212</button>\n <span>{{ zoom * 100 | number: \"1.0-0\" }}%</span>\n <button nz-button nzSize=\"small\" (click)=\"zoomIn()\">+</button>\n </div> -->\n\n <!-- SVG EDGES -->\n <svg #svg class=\"edges-layer\" width=\"100%\" height=\"100%\" preserveAspectRatio=\"none\">\n <g [attr.transform]=\"svgTransform\">\n <!-- DEFS -->\n <defs>\n <!-- glow effect -->\n <filter id=\"edge-glow\" x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\">\n <feGaussianBlur stdDeviation=\"2\" result=\"blur\" />\n <feMerge>\n <feMergeNode in=\"blur\" />\n <feMergeNode in=\"SourceGraphic\" />\n </feMerge>\n </filter>\n\n <!-- arrow markers -->\n <marker\n id=\"arrow-blue\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n refX=\"10\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"blue\" d=\"M0,0 L10,5 L0,10\"></path>\n </marker>\n\n <marker\n id=\"arrow-red\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n refX=\"10\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"red\" d=\"M0,0 L10,5 L0,10\"></path>\n </marker>\n\n <marker\n id=\"arrow-blue-start\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n viewBox=\"0 0 10 10\"\n refX=\"0\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"blue\" d=\"M10,0 L0,5 L10,10\"></path>\n </marker>\n\n <marker\n id=\"arrow-red-start\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n viewBox=\"0 0 10 10\"\n refX=\"0\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"red\" d=\"M10,0 L0,5 L10,10\"></path>\n </marker>\n </defs>\n\n <!-- EDGES B\u00CCNH TH\u01AF\u1EDCNG -->\n <ng-container *ngFor=\"let e of normalEdges; let i = index\">\n <path\n class=\"edge-hit\"\n [attr.d]=\"buildPath(e)\"\n (mouseenter)=\"onMouseEnterEdge(e)\"\n (mouseleave)=\"onMouseLeaveEdge(e)\"\n (click)=\"onClickEdge(e, $event)\"\n ></path>\n\n <path\n class=\"edge\"\n [attr.id]=\"'edge-path-' + i\"\n [attr.d]=\"buildPath(e)\"\n marker-end=\"url(#arrow-blue)\"\n [attr.marker-start]=\"e.allowBack ? 'url(#arrow-blue-start)' : ''\"\n ></path>\n\n <!-- LABEL -->\n <!-- text b\u00E1m theo line -->\n <!-- \n <text *ngIf=\"e.ActionText\" class=\"edge-label\" dy=\"-6\">\n <textPath [attr.href]=\"'#edge-path-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.ActionText }}\n </textPath>\n </text> \n \n <text *ngIf=\"e.allowBack && e.labelBack\" class=\"edge-label\" dy=\"14\">\n <textPath [attr.href]=\"'#edge-path-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.labelBack }}\n </textPath>\n </text>\n -->\n\n <!-- text th\u1EB3ng n\u1EB1m ngang -->\n <text\n *ngIf=\"e.ActionText\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y - 8\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.ActionText }}\n </text>\n\n <text\n *ngIf=\"e.allowBack && e.labelBack\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y + 14\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.labelBack }}\n </text>\n </ng-container>\n\n <!-- EDGE \u0110ANG HOVER (LU\u00D4N TR\u00CAN C\u00D9NG) -->\n <ng-container *ngFor=\"let e of hoverEdges; let i = index\">\n <path\n class=\"edge-hit\"\n [attr.d]=\"buildPath(e)\"\n (mouseleave)=\"onMouseLeaveEdge(e)\"\n (click)=\"onClickEdge(e, $event)\"\n ></path>\n\n <path\n class=\"edge red\"\n [attr.id]=\"'edge-path-hover-' + i\"\n [attr.d]=\"buildPath(e)\"\n marker-end=\"url(#arrow-red)\"\n [attr.marker-start]=\"e.allowBack ? 'url(#arrow-red-start)' : ''\"\n ></path>\n\n <!-- LABEL -->\n <!-- <text *ngIf=\"e.ActionText\" class=\"edge-label\" dy=\"-6\">\n <textPath [attr.href]=\"'#edge-path-hover-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.ActionText }}\n </textPath>\n </text>\n\n <text *ngIf=\"e.allowBack && e.labelBack\" class=\"edge-label\" dy=\"14\">\n <textPath [attr.href]=\"'#edge-path-hover-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.labelBack }}\n </textPath>\n </text> -->\n\n <text\n *ngIf=\"e.ActionText\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y - 8\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.ActionText }}\n </text>\n\n <text\n *ngIf=\"e.allowBack && e.labelBack\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y + 14\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.labelBack }}\n </text>\n </ng-container>\n\n <!-- preview -->\n <path\n *ngIf=\"connectingFrom\"\n class=\"edge\"\n [attr.d]=\"buildPreviewPath()\"\n stroke-dasharray=\"5,5\"\n marker-end=\"url(#arrow-blue)\"\n ></path>\n </g>\n </svg>\n\n <div\n *ngIf=\"isSelecting && selectStart && selectEnd\"\n class=\"selection-box\"\n [style.left.px]=\"Math.min(selectStart.x, selectEnd.x)\"\n [style.top.px]=\"Math.min(selectStart.y, selectEnd.y)\"\n [style.width.px]=\"Math.abs(selectEnd.x - selectStart.x)\"\n [style.height.px]=\"Math.abs(selectEnd.y - selectStart.y)\"\n ></div>\n\n <!-- lstStage -->\n @for (n of lstStage; track $index) {\n @if (n.StageType == \"NODE\") {\n <nz-card\n #nodeEl\n class=\"workflow-node\"\n [attr.data-id]=\"n.Code\"\n [class.selected]=\"n == selectedStage || n == hoverStage || lstSelectedStageCode.has(n.Code)\"\n [style.left.px]=\"n.x\"\n [style.top.px]=\"n.y\"\n [class.connecting-source]=\"isConnectingFrom(n) || isDraggingFrom(n) || isSelectedNode(n)\"\n nzSize=\"small\"\n (mousedown)=\"onMouseDownNode($event, n)\"\n (click)=\"$event.stopPropagation(); onClickStage(n)\"\n >\n <div class=\"title\">{{ n.Code }}</div>\n\n <div>{{ n.Name }}</div>\n\n @if (!n.isReverse) {\n <!-- connector RIGHT: output -->\n <div class=\"connector connector-right\" (click)=\"onClickConnector($event, n, 'right')\"></div>\n\n <!-- connector LEFT: input -->\n <div class=\"connector connector-left\" (click)=\"onClickConnector($event, n, 'left')\"></div>\n } @else {\n <div class=\"connector connector-right reverse\" (click)=\"onClickConnector($event, n, 'right')\"></div>\n <div class=\"connector connector-left reverse\" (click)=\"onClickConnector($event, n, 'left')\"></div>\n }\n </nz-card>\n }\n <!-- START NODE -->\n @else if (n.StageType === \"START\") {\n <nz-card\n class=\"workflow-node workflow-node-start\"\n style=\"border: unset\"\n [style.left.px]=\"n.x\"\n [style.top.px]=\"n.y\"\n nzSize=\"small\"\n (mousedown)=\"onMouseDownNode($event, n)\"\n (click)=\"$event.stopPropagation(); onClickStage(n)\"\n >\n <div class=\"title\"> </div>\n\n <nz-tag\n [class.selected]=\"n == selectedStage || lstSelectedStageCode.has(n.Code)\"\n style=\"position: relative; top: -13px\"\n [style.right.px]=\"n.isReverseLabel ? -83 : 1\"\n [nzColor]=\"'green'\"\n >\n {{ n.StageType }}\n </nz-tag>\n\n <!-- connector RIGHT: output -->\n <div class=\"connector connector-right connector-start\" (click)=\"onClickConnector($event, n, 'right')\"></div>\n </nz-card>\n }\n\n <!-- END NODE -->\n @else if (n.StageType === \"END\") {\n <nz-card\n class=\"workflow-node workflow-node-end\"\n style=\"border: unset\"\n [style.left.px]=\"n.x\"\n [style.top.px]=\"n.y\"\n [class.connecting-source]=\"isConnectingFrom(n)\"\n nzSize=\"small\"\n (mousedown)=\"onMouseDownNode($event, n)\"\n (click)=\"$event.stopPropagation(); onClickStage(n)\"\n >\n <div class=\"title\"> </div>\n\n <nz-tag\n [class.selected]=\"n == selectedStage || lstSelectedStageCode.has(n.Code)\"\n style=\"position: relative; top: -13px\"\n [style.right.px]=\"n.isReverseLabel ? 65 : -5\"\n [nzColor]=\"'red'\"\n >\n {{ n.StageType }}\n </nz-tag>\n\n <!-- connector LEFT: input -->\n <div class=\"connector connector-end\" (click)=\"onClickConnector($event, n, 'left')\"></div>\n </nz-card>\n }\n }\n\n <!-- POINTS -->\n @for (p of connectingPoints; track $index) {\n @if (p != draggingPoint) {\n <div\n class=\"waypoint\"\n [style.left.px]=\"p.x\"\n [style.top.px]=\"p.y\"\n (mousedown)=\"onmousedownPoint($event, p)\"\n (contextmenu)=\"onRightClickPoint($event, hoverEdge!, $index)\"\n ></div>\n } @else {\n <div\n class=\"waypoint dragging\"\n [style.left.px]=\"p.x\"\n [style.top.px]=\"p.y\"\n (mousedown)=\"onmousedownPoint($event, p)\"\n ></div>\n }\n }\n </div>\n</div>\n\n<!-- TEMPLATE -->\n<nz-drawer\n [nzTitle]=\"drawTemplateTitle\"\n nzPlacement=\"right\"\n [nzWidth]=\"500\"\n [nzClosable]=\"false\"\n [nzVisible]=\"drawTemplateVisibel\"\n [nzFooter]=\"footerTplTemplate\"\n (nzOnClose)=\"drawTemplateVisibel = false\"\n>\n <ng-template #drawTemplateTitle> <nz-icon nzType=\"setting\"></nz-icon> Template </ng-template>\n <ng-container *nzDrawerContent>\n <extend-input [label]=\"'Code'\" [(_ngModel)]=\"template.Code\"></extend-input>\n <extend-input [label]=\"'Name'\" [(_ngModel)]=\"template.Name\"></extend-input>\n <extend-select\n [label]=\"'Type'\"\n [lstItem]=\"lstTemplateType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"template.DocType\"\n ></extend-select>\n <extend-textarea [label]=\"'Desscription'\" [(_ngModel)]=\"template.Description\"></extend-textarea>\n <extend-select\n [label]=\"'Print template'\"\n [lstItem]=\"lstTemplatePrint\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"template.TemplatePrint\"\n ></extend-select>\n <extend-checkbox [label]=\"'Active'\" [(_ngModel)]=\"template.IsActive\"></extend-checkbox>\n\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> Stage status</h3>\n\n @for (tag of template.lstStageStatus; track tag) {\n <nz-tag\n [nzMode]=\"checkRemoveableStageStatus(tag) ? 'closeable' : 'default'\"\n (nzOnClose)=\"handleCloseStageStatus(tag)\"\n >\n {{ sliceTagName(tag.Code + (tag.Name ? \" - \" + tag.Name : \"\")) }}\n </nz-tag>\n }\n\n <br *ngIf=\"template.lstStageStatus && template.lstStageStatus.length\" />\n\n @if (!inputStageStatusVisible) {\n <nz-tag class=\"editable-tag\" nzNoAnimation (click)=\"showInputStageStatus()\">\n <nz-icon nzType=\"plus\" />\n New Action type\n </nz-tag>\n } @else {\n <input\n #inputStageStatusElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Code\"\n [(ngModel)]=\"inputStageStatusCode\"\n (keydown.enter)=\"inputStageStatusNameElement.select()\"\n />\n <input\n #inputStageStatusNameElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Name\"\n [(ngModel)]=\"inputStageStatusName\"\n (blur)=\"handleInputStageStatusConfirm()\"\n (keydown.enter)=\"handleInputStageStatusConfirm()\"\n />\n }\n\n <box [height]=\"16\"></box>\n\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> Action type</h3>\n\n @for (tag of template.lstActionType; track tag) {\n <nz-tag\n [nzMode]=\"checkRemoveableActionType(tag) ? 'closeable' : 'default'\"\n (nzOnClose)=\"handleCloseActionType(tag)\"\n >\n {{ sliceTagName(tag.Code + (tag.Name ? \" - \" + tag.Name : \"\")) }}\n </nz-tag>\n }\n\n <br *ngIf=\"template.lstActionType && template.lstActionType.length\" />\n\n @if (!inputActionTypeVisible) {\n <nz-tag class=\"editable-tag\" nzNoAnimation (click)=\"showInputActionType()\">\n <nz-icon nzType=\"plus\" />\n New Action type\n </nz-tag>\n } @else {\n <input\n #inputActionTypeElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Code\"\n [(ngModel)]=\"inputActionTypeCode\"\n (keydown.enter)=\"inputActionTypeNameElement.select()\"\n />\n <input\n #inputActionTypeNameElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Name\"\n [(ngModel)]=\"inputActionTypeName\"\n (blur)=\"handleInputActionTypeConfirm()\"\n (keydown.enter)=\"handleInputActionTypeConfirm()\"\n />\n }\n\n <box [height]=\"16\"></box>\n\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> Action status</h3>\n\n @for (tag of template.lstActionStatus; track tag) {\n <nz-tag [nzMode]=\"checkRemoveableActionStatus(tag) ? 'closeable' : 'default'\" (nzOnClose)=\"handleClose(tag)\">\n {{ sliceTagName(tag.Code + (tag.Name ? \" - \" + tag.Name : \"\")) }}\n </nz-tag>\n }\n\n <br *ngIf=\"template.lstActionStatus && template.lstActionStatus.length\" />\n\n @if (!inputVisible) {\n <nz-tag class=\"editable-tag\" nzNoAnimation (click)=\"showInput()\">\n <nz-icon nzType=\"plus\" />\n New Action status\n </nz-tag>\n } @else {\n <input\n #inputElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"+ New Action status\"\n [(ngModel)]=\"inputValue\"\n (blur)=\"handleInputConfirm()\"\n (keydown.enter)=\"handleInputConfirm()\"\n />\n }\n </ng-container>\n\n <ng-template #footerTplTemplate>\n <div nz-flex [nzGap]=\"6\">\n <button nz-button (click)=\"drawTemplateVisibel = false\">Close</button>\n <button nz-button nzDanger (click)=\"save()\">Save</button>\n </div>\n </ng-template>\n</nz-drawer>\n\n<!-- STAGE -->\n<nz-drawer\n [nzTitle]=\"drawerTitleStage\"\n [nzPlacement]=\"selectedStage?.drawerPosition ? selectedStage?.drawerPosition : 'right'\"\n [nzVisible]=\"!!selectedStage\"\n [nzWidth]=\"750\"\n [nzClosable]=\"false\"\n [nzFooter]=\"footerTplNode\"\n (nzOnClose)=\"selectedStage = undefined\"\n>\n <ng-template #drawerTitleStage>\n <div nz-row nzJustify=\"space-between\">\n @if (selectedStage) {\n @if (selectedStage.drawerPosition == \"left\") {\n <button nz-button nzSize=\"small\" nz-tooltip=\"To the right\" (click)=\"selectedStage.drawerPosition = 'right'\">\n <nz-icon nzType=\"double-right\"></nz-icon>\n </button>\n STAGE\n } @else {\n STAGE\n <button nz-button nzSize=\"small\" nz-tooltip=\"To the left\" (click)=\"selectedStage.drawerPosition = 'left'\">\n <nz-icon nzType=\"double-left\"></nz-icon>\n </button>\n }\n }\n </div>\n </ng-template>\n <ng-container *nzDrawerContent>\n <ng-container *ngIf=\"selectedStage\">\n <nz-radio-group [(ngModel)]=\"selectedStage.StageType\">\n <label nz-radio nzValue=\"START\" [nzDisabled]=\"true\">START</label>\n <label nz-radio nzValue=\"NODE\" [nzDisabled]=\"true\">NODE</label>\n <label nz-radio nzValue=\"END\" [nzDisabled]=\"true\">END</label>\n </nz-radio-group>\n\n <box [height]=\"16\"></box>\n\n <div nz-row [nzGutter]=\"32\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Code'\"\n [layOutType]=\"'vertical'\"\n [disabled]=\"['START', 'END'].indexOf(selectedStage!.StageType) >= 0\"\n [required]=\"true\"\n [(_ngModel)]=\"selectedStage.Code\"\n ></extend-input>\n\n <extend-textarea\n nz-col\n [nzSpan]=\"16\"\n [label]=\"'Name'\"\n [layOutType]=\"'vertical'\"\n [autoSize]=\"true\"\n [disabled]=\"['START', 'END'].indexOf(selectedStage!.StageType) >= 0\"\n [required]=\"true\"\n [(_ngModel)]=\"selectedStage.Name\"\n ></extend-textarea>\n </div>\n\n <div nz-row [nzGutter]=\"32\">\n <extend-input-number\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Sequence'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"selectedStage.SeqValue\"\n ></extend-input-number>\n\n <extend-select\n nz-col\n [nzSpan]=\"16\"\n [label]=\"'Org implement'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstOrg\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedStage.App_Org_Id\"\n ></extend-select>\n </div>\n\n @if ([\"START\", \"END\"].indexOf(selectedStage.StageType) < 0) {\n <extend-checkbox [label]=\"'Reverse'\" [labelSpan]=\"0\" [(_ngModel)]=\"selectedStage.isReverse\"></extend-checkbox>\n\n <extend-checkbox\n [label]=\"'Require user action'\"\n [labelSpan]=\"0\"\n [(_ngModel)]=\"selectedStage.IsRequireUser\"\n ></extend-checkbox>\n } @else {\n <extend-checkbox\n [label]=\"'Reverse'\"\n [labelSpan]=\"0\"\n [(_ngModel)]=\"selectedStage.isReverseLabel\"\n ></extend-checkbox>\n }\n\n <box [height]=\"16\"></box>\n\n <div nz-row [nzGutter]=\"16\">\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> List Action</h3>\n <div nz-col>\n <button nz-button nzType=\"primary\" nzSize=\"small\" (click)=\"addAction()\">\n <nz-icon nzType=\"plus\"></nz-icon>\n </button>\n </div>\n </div>\n\n <nz-table\n nzSize=\"small\"\n [nzData]=\"selectedStage.lstAction || []\"\n [nzShowPagination]=\"false\"\n [nzNoResult]=\"' '\"\n >\n <thead>\n <tr [hidden]=\"true\">\n <th nzWidth=\"50px\"></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n @for (action of selectedStage.lstAction; track $index) {\n <tr>\n <td>\n <nz-icon\n nzType=\"delete\"\n nzTheme=\"outline\"\n class=\"color-warn cursor-pointer icon-size-16\"\n (click)=\"$event.stopPropagation(); deleteAction(action)\"\n ></nz-icon>\n </td>\n <td (click)=\"hoverEdge = action\">\n <div nz-row [nzGutter]=\"16\" class=\"form-item-no-bottom\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action text'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"action.ActionText\"\n (_ngModelChange)=\"onchangeActionText(action)\"\n ></extend-input>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action type'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.ActionType\"\n ></extend-select>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.ActionStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.StageStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstStage\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.ToStage\"\n (_ngModelChange)=\"onchangeNextStage(action)\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.NextStageStatus\"\n ></extend-select>\n\n <nz-divider\n *ngIf=\"selectedStage.lstAction && $index + 1 < selectedStage.lstAction.length\"\n style=\"margin: 16px 0px 8px 0px; background-color: orange\"\n ></nz-divider>\n </div>\n </td>\n </tr>\n }\n </tbody>\n </nz-table>\n\n <box [height]=\"16\"></box>\n </ng-container>\n </ng-container>\n\n <ng-template #footerTplNode>\n <div nz-flex [nzGap]=\"6\" [nzJustify]=\"selectedStage && selectedStage.drawerPosition == 'left' ? 'end' : 'start'\">\n <button nz-button (click)=\"selectedStage = undefined\">Close</button>\n <button\n *ngIf=\"selectedStage && ['START', 'END'].indexOf(selectedStage.StageType) < 0\"\n nz-button\n nzDanger\n (click)=\"deleteNode()\"\n >\n Delete\n </button>\n </div>\n </ng-template>\n</nz-drawer>\n\n<!-- EDGE -->\n<nz-drawer\n nzTitle=\"ACTION\"\n nzPlacement=\"right\"\n [nzClosable]=\"false\"\n [nzWidth]=\"750\"\n [nzVisible]=\"!!selectedAction\"\n (nzOnClose)=\"selectedAction = undefined\"\n>\n <ng-container *nzDrawerContent>\n <ng-container *ngIf=\"selectedAction\">\n <strong>{{ selectedAction.FromStage }} -> {{ selectedAction.ToStage }}</strong>\n\n <box [height]=\"16\"></box>\n\n <div nz-row [nzGutter]=\"16\" class=\"form-item-no-bottom\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action text'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"selectedAction.ActionText\"\n (_ngModelChange)=\"onchangeActionText(selectedAction)\"\n ></extend-input>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action type'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.ActionType\"\n ></extend-select>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.ActionStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.StageStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstStage\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.ToStage\"\n (_ngModelChange)=\"onchangeNextStage(selectedAction)\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.NextStageStatus\"\n ></extend-select>\n </div>\n\n <!-- <box [height]=\"16\"></box> -->\n <nz-divider></nz-divider>\n\n <extend-checkbox\n [label]=\"'Allow back'\"\n [labelSpan]=\"0\"\n [(_ngModel)]=\"selectedAction.allowBack\"\n (_ngModelChange)=\"onchangeAllowBack(selectedAction)\"\n ></extend-checkbox>\n\n <box [height]=\"16\"></box>\n\n @if (selectedAction.allowBack) {\n <strong>{{ selectedAction.ToStage }} -> {{ selectedAction.FromStage }}</strong>\n\n @if (selectedBackAction) {\n <div nz-row [nzGutter]=\"16\" class=\"form-item-no-bottom\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action text'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"selectedBackAction.ActionText\"\n (_ngModelChange)=\"onchangeActionText(selectedBackAction)\"\n ></extend-input>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action type'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.ActionType\"\n ></extend-select>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.ActionStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.StageStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstStage\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.ToStage\"\n (_ngModelChange)=\"onchangeNextStage(selectedBackAction)\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.NextStageStatus\"\n ></extend-select>\n </div>\n }\n }\n </ng-container>\n </ng-container>\n</nz-drawer>\n\n<!-- setting editor -->\n<nz-drawer\n [nzTitle]=\"drawSettingTitle\"\n nzPlacement=\"right\"\n [nzClosable]=\"false\"\n [nzVisible]=\"settingVisible\"\n (nzOnClose)=\"settingVisible = false\"\n>\n <ng-template #drawSettingTitle> <nz-icon nzType=\"setting\"></nz-icon> Editor </ng-template>\n <ng-container *nzDrawerContent>\n <div class=\"form-item-no-bottom\">\n <extend-checkbox [label]=\"'Show grid'\" [labelSpan]=\"0\" [(_ngModel)]=\"wfcSetting.ShowGrid\"></extend-checkbox>\n\n <box [height]=\"16\"></box>\n\n <extend-input-number [label]=\"'Canvas width'\" [(_ngModel)]=\"CANVAS_WIDTH\"></extend-input-number>\n <box [height]=\"16\"></box>\n <extend-input-number [label]=\"'Canvas height'\" [(_ngModel)]=\"CANVAS_HEIGHT\"></extend-input-number>\n </div>\n </ng-container>\n</nz-drawer>\n", styles: ["@charset \"UTF-8\";.workflow-canvas{position:relative;width:100%;height:600px;background:#f0f2f5;cursor:default;overflow:hidden;outline:1px dashed rgba(0,0,0,.1)}.workflow-canvas .edges-layer{position:absolute;inset:0;width:100%;height:100%;z-index:1}.workflow-canvas .edges-layer path{stroke-width:2;fill:none}.canvas-content{transform-origin:0 0;width:10000px;height:10000px}.canvas-content{outline:1px dashed red}.canvas-content.panning{cursor:grab}.canvas-content.panning:active{cursor:grabbing}.workflow-canvas.panning{cursor:grab}.workflow-canvas.panning:active{cursor:grabbing}.workflow-canvas.connecting,.workflow-canvas.connecting .workflow-node{cursor:crosshair}.workflow-node{position:absolute;width:160px;cursor:grab;-webkit-user-select:none;user-select:none;z-index:2}.workflow-node:active{cursor:grabbing}.workflow-node .title{font-weight:600;margin-bottom:6px}.workflow-node.connecting-source,.workflow-node.selected,.workflow-node:hover:not(.workflow-node-start,.workflow-node-end){outline:2px dashed #1890ff}.workflow-node-start{background-color:unset;display:flex;justify-content:right}.workflow-node-end{background-color:unset;display:flex}.connector{position:absolute;top:39px;width:12px;height:12px;background:#1890ff;border-radius:50%;transform:translateY(-50%);cursor:crosshair;transition:box-shadow .15s ease-out,transform .15s ease-out}.connector:hover{box-shadow:0 0 0 3px #1890ff4d;transform:translateY(-50%) scale(1.15)}.connector-right{right:-8px;background:orange}.connector-right.reverse,.connector-left{left:-8px}.connector-left.reverse{left:unset;right:-8px}.connector-start{width:16px;height:16px;right:-3px;background:green;box-shadow:0 0 0 3px #1890ff4d}.connector-end{width:16px;height:16px;left:-6px;background:#000;box-shadow:0 0 0 3px #1890ff4d}.edge{cursor:pointer;stroke:#1890ff;stroke-linecap:round;stroke-linejoin:round;stroke-width:2;fill:none;transition:stroke .15s ease}.edge-hit{stroke:transparent;stroke-width:18px!important;fill:none;cursor:pointer}.edge-hit:hover+.edge{stroke:#ff4d4f;stroke-width:2}.workflow-canvas.dragging-point .edge-hit{pointer-events:none}.edge:hover+.edge-label{fill:#1890ff;font-weight:500}.edge-label{font-size:12px;fill:#555;pointer-events:none;-webkit-user-select:none;user-select:none}.blue{stroke:#1890ff!important}.red{stroke:#ff4d4f!important;box-shadow:0 0 0 3px #1890ff4d!important}.workflow-svg{background:transparent;overflow:visible}.waypoint{position:absolute;width:10px;height:10px;background:#ff4d4f;border-radius:50%;transform:translate(-50%,-50%) scale(1);cursor:move;z-index:1;transition:transform .12s ease-out,background-color .12s ease-out,box-shadow .12s ease-out}.waypoint:hover{background:#ff7875;transform:translate(-50%,-50%) scale(1.25);box-shadow:0 0 0 4px #ff787559}.waypoint.dragging{transition:none;transform:translate(-50%,-50%) scale(1.15);pointer-events:none}.workflow-canvas.dragging-point svg{cursor:grabbing}.selection-box{position:absolute;border:1px dashed #1890ff;background:#1890ff1a;pointer-events:none}.toolbar{position:absolute;top:8px;left:8px;display:flex;gap:4px;padding:6px;background:#fff;border-radius:6px;box-shadow:0 2px 8px #00000026;z-index:100}.toolbar .divider{width:1px;background:#e5e5e5;margin:0 2px}.zoom-toolbar{position:absolute;top:8px;left:8px;z-index:10;display:flex;align-items:center;gap:6px;background:#fff;padding:4px 6px;border-radius:6px;box-shadow:0 2px 6px #00000026}.zoom-toolbar span{min-width:40px;text-align:center;font-size:12px}nz-tag.selected{outline:2px dashed #1890ff}.grid-layer{position:absolute;inset:0;pointer-events:none;z-index:0;background-image:radial-gradient(rgba(0,0,0,.08) 1px,transparent 1px);background-size:20px 20px}.grid-layer{background-image:linear-gradient(to right,rgba(0,0,0,.06) 1px,transparent 1px),linear-gradient(to bottom,rgba(0,0,0,.06) 1px,transparent 1px);background-size:20px 20px}.editable-tag{background:#fff;border-style:dashed}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: NzCardModule }, { kind: "component", type: i3$1.NzCardComponent, selector: "nz-card", inputs: ["nzBordered", "nzLoading", "nzHoverable", "nzBodyStyle", "nzCover", "nzActions", "nzType", "nzSize", "nzTitle", "nzExtra"], exportAs: ["nzCard"] }, { kind: "ngmodule", type: NzDrawerModule }, { kind: "component", type: i4$1.NzDrawerComponent, selector: "nz-drawer", inputs: ["nzContent", "nzCloseIcon", "nzClosable", "nzMaskClosable", "nzMask", "nzCloseOnNavigation", "nzNoAnimation", "nzKeyboard", "nzTitle", "nzExtra", "nzFooter", "nzPlacement", "nzSize", "nzMaskStyle", "nzBodyStyle", "nzWrapClassName", "nzWidth", "nzHeight", "nzZIndex", "nzOffsetX", "nzOffsetY", "nzVisible"], outputs: ["nzOnViewInit", "nzOnClose", "nzVisibleChange"], exportAs: ["nzDrawer"] }, { kind: "directive", type: i4$1.NzDrawerContentDirective, selector: "[nzDrawerContent]", exportAs: ["nzDrawerContent"] }, { kind: "ngmodule", type: NzTagModule }, { kind: "component", type: i5$2.NzTagComponent, selector: "nz-tag", inputs: ["nzMode", "nzColor", "nzChecked", "nzBordered"], outputs: ["nzOnClose", "nzCheckedChange"], exportAs: ["nzTag"] }, { kind: "ngmodule", type: NzRadioModule }, { kind: "component", type: i6$3.NzRadioComponent, selector: "[nz-radio],[nz-radio-button]", inputs: ["nzValue", "nzDisabled", "nzAutoFocus", "nz-radio-button"], exportAs: ["nzRadio"] }, { kind: "component", type: i6$3.NzRadioGroupComponent, selector: "nz-radio-group", inputs: ["nzDisabled", "nzButtonStyle", "nzSize", "nzName"], exportAs: ["nzRadioGroup"] }, { kind: "ngmodule", type: NzIconModule }, { kind: "directive", type: i2.NzIconDirective, selector: "nz-icon,[nz-icon]", inputs: ["nzSpin", "nzRotate", "nzType", "nzTheme", "nzTwotoneColor", "nzIconfont"], exportAs: ["nzIcon"] }, { kind: "component", type: Box, selector: "box", inputs: ["display", "width", "height"] }, { kind: "ngmodule", type: NzButtonModule }, { kind: "component", type: i8.NzButtonComponent, selector: "button[nz-button], a[nz-button]", inputs: ["nzBlock", "nzGhost", "nzSearch", "nzLoading", "nzDanger", "disabled", "tabIndex", "nzType", "nzShape", "nzSize"], exportAs: ["nzButton"] }, { kind: "directive", type: i9.ɵNzTransitionPatchDirective, selector: "[nz-button], nz-button-group, [nz-icon], nz-icon, [nz-menu-item], [nz-submenu], nz-select-top-control, nz-select-placeholder, nz-input-group", inputs: ["hidden"] }, { kind: "directive", type: i10.NzWaveDirective, selector: "[nz-wave],button[nz-button]:not([nzType=\"link\"]):not([nzType=\"text\"])", inputs: ["nzWaveExtraNode"], exportAs: ["nzWave"] }, { kind: "ngmodule", type: NzToolTipModule }, { kind: "directive", type: i11.NzTooltipDirective, selector: "[nz-tooltip]", inputs: ["nzTooltipTitle", "nzTooltipTitleContext", "nz-tooltip", "nzTooltipTrigger", "nzTooltipPlacement", "nzTooltipOrigin", "nzTooltipVisible", "nzTooltipMouseEnterDelay", "nzTooltipMouseLeaveDelay", "nzTooltipOverlayClassName", "nzTooltipOverlayStyle", "nzTooltipArrowPointAtCenter", "cdkConnectedOverlayPush", "nzTooltipColor"], outputs: ["nzTooltipVisibleChange"], exportAs: ["nzTooltip"] }, { kind: "component", type: ExtendInput, selector: "extend-input", inputs: ["layOutType", "label", "placeHolder", "labelAlign", "inputClass", "labelSpan", "allowClear", "disabled", "readOnly", "required", "noBottom", "selectModeType", "autocomplete", "inputWidth", "inputHeight", "borderBottomOnly", "displayInline", "size", "lstItem", "displayField", "valueField", "formData", "controlName", "_ngModel"], outputs: ["_ngModelChange", "onclickClearIcon", "onenter"] }, { kind: "component", type: ExtendSelectComponent, selector: "extend-select", inputs: ["layOutType", "label", "placeHolder", "labelAlign", "labelSpan", "disabled", "required", "noBottom", "multiple", "showSelectAll", "maxTagCount", "inputWidth", "inputHeight", "borderBottomOnly", "displayInline", "size", "lstItem", "displayField", "displayFields", "valueField", "formData", "controlName", "_ngModel"], outputs: ["_ngModelChange", "itemChange", "onFocus"] }, { kind: "component", type: ExtendCheckbox, selector: "extend-checkbox", inputs: ["label", "labelSpan", "disabled", "formData", "controlName", "valueType", "_ngModel"], outputs: ["_ngModelChange"] }, { kind: "component", type: ExtendTextArea, selector: "extend-textarea", inputs: ["layOutType", "label", "placeHolder", "labelAlign", "labelSpan", "inputSpan", "disabled", "required", "noBottom", "selectModeType", "inputClass", "minRows", "maxRows", "autoSize", "lstItem", "displayField", "valueField", "formData", "controlName", "_ngModel"], outputs: ["_ngModelChange"] }, { kind: "ngmodule", type: NzInputModule }, { kind: "directive", type: i6$1.NzInputDirective, selector: "input[nz-input],textarea[nz-input]", inputs: ["nzBorderless", "nzSize", "nzStepperless", "nzStatus", "disabled"], exportAs: ["nzInput"] }, { kind: "ngmodule", type: NzGridModule }, { kind: "directive", type: i4.NzColDirective, selector: "[nz-col],nz-col,nz-form-control,nz-form-label", inputs: ["nzFlex", "nzSpan", "nzOrder", "nzOffset", "nzPush", "nzPull", "nzXs", "nzSm", "nzMd", "nzLg", "nzXl", "nzXXl"], exportAs: ["nzCol"] }, { kind: "directive", type: i4.NzRowDirective, selector: "[nz-row],nz-row,nz-form-item", inputs: ["nzAlign", "nzJustify", "nzGutter"], exportAs: ["nzRow"] }, { kind: "ngmodule", type: NzFlexModule }, { kind: "directive", type: i14.NzFlexDirective, selector: "[nz-flex],nz-flex", inputs: ["nzVertical", "nzJustify", "nzAlign", "nzGap", "nzWrap", "nzFlex"], exportAs: ["nzFlex"] }, { kind: "component", type: ExtendInputNumber, selector: "extend-input-number", inputs: ["layOutType", "label", "placeHolder", "labelAlign", "labelSpan", "disabled", "required", "noBottom", "size", "min", "max", "precision", "inputWidth", "inputHeight", "borderBottomOnly", "displayInline", "separatorType", "formData", "controlName", "_ngModel"], outputs: ["_ngModelChange"] }, { kind: "ngmodule", type: NzTableModule }, { kind: "component", type: i15.NzTableComponent, selector: "nz-table", inputs: ["nzTableLayout", "nzShowTotal", "nzItemRender", "nzTitle", "nzFooter", "nzNoResult", "nzPageSizeOptions", "nzVirtualItemSize", "nzVirtualMaxBufferPx", "nzVirtualMinBufferPx", "nzVirtualForTrackBy", "nzLoadingDelay", "nzPageIndex", "nzPageSize", "nzTotal", "nzWidthConfig", "nzData", "nzCustomColumn", "nzPaginationPosition", "nzScroll", "noDataVirtualHeight", "nzPaginationType", "nzFrontPagination", "nzTemplateMode", "nzShowPagination", "nzLoading", "nzOuterBordered", "nzLoadingIndicator", "nzBordered", "nzSize", "nzShowSizeChanger", "nzHideOnSinglePage", "nzShowQuickJumper", "nzSimple"], outputs: ["nzPageSizeChange", "nzPageIndexChange", "nzQueryParams", "nzCurrentPageDataChange", "nzCustomColumnChange"], exportAs: ["nzTable"] }, { kind: "directive", type: i15.NzTableCellDirective, selector: "th:not(.nz-disable-th):not([mat-cell]), td:not(.nz-disable-td):not([mat-cell])" }, { kind: "directive", type: i15.NzThMeasureDirective, selector: "th", inputs: ["nzWidth", "colspan", "colSpan", "rowspan", "rowSpan"] }, { kind: "component", type: i15.NzTheadComponent, selector: "thead:not(.ant-table-thead)", outputs: ["nzSortOrderChange"] }, { kind: "component", type: i15.NzTbodyComponent, selector: "tbody" }, { kind: "directive", type: i15.NzTrDirective, selector: "tr:not([mat-row]):not([mat-header-row]):not([nz-table-measure-row]):not([nzExpand]):not([nz-table-fixed-row])" }, { kind: "ngmodule", type: NzDividerModule }, { kind: "component", type: i16.NzDividerComponent, selector: "nz-divider", inputs: ["nzText", "nzType", "nzOrientation", "nzVariant", "nzDashed", "nzPlain"], exportAs: ["nzDivider"] }] });
|
|
4276
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.7", type: WorkflowEditorComponent, isStandalone: true, selector: "app-workflow-editor", inputs: { lstOrg: "lstOrg", lstTemplateType: "lstTemplateType", lstTemplatePrint: "lstTemplatePrint", template: "template", lstStage: "lstStage", lstAction: "lstAction" }, outputs: { onSave: "onSave" }, host: { listeners: { "window:keydown": "onKeyDown($event)" } }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["canvas"], descendants: true, static: true }, { propertyName: "svgRef", first: true, predicate: ["svg"], descendants: true, static: true }, { propertyName: "inputStageStatusElement", first: true, predicate: ["inputStageStatusElement"], descendants: true }, { propertyName: "inputActionTypeElement", first: true, predicate: ["inputActionTypeElement"], descendants: true }, { propertyName: "inputElement", first: true, predicate: ["inputElement"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div\n #canvasRef\n class=\"workflow-canvas\"\n [class.connecting]=\"!!connectingFrom\"\n [class.dragging-point]=\"!!draggingPoint\"\n [style.width.px]=\"CANVAS_WIDTH\"\n [style.height.px]=\"CANVAS_HEIGHT\"\n (mousedown)=\"onMouseDownCanvas($event)\"\n (mousemove)=\"onMouseMoveCanvas($event)\"\n (mouseup)=\"onMouseUpCanvas($event)\"\n (click)=\"onClickCanvas($event)\"\n>\n <!-- \n\n [style.width.px]=\"getCanvasWidth()\"\n [style.height.px]=\"getCanvasHeight()\" \n\n style=\"width: 100%; height: calc(100vh - 120px)\"\n \n -->\n\n <div class=\"toolbar\" (mousedown)=\"$event.stopPropagation()\" (click)=\"$event.stopPropagation()\">\n <button nz-button nzSize=\"small\" nz-tooltip=\"Editor setting\" (click)=\"settingVisible = true\">\n <nz-icon nzType=\"setting\"></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <button nz-button nzSize=\"small\" nz-tooltip=\"Template setting\" (click)=\"drawTemplateVisibel = true\">\n <nz-icon nzType=\"setting\"></nz-icon> T\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <button nz-button nzSize=\"small\" nzDanger nz-tooltip=\"Save\" (click)=\"save()\">\n <nz-icon nzType=\"save\"></nz-icon>\n </button>\n <button nz-button nzSize=\"small\" nz-tooltip=\"Add stage\" (click)=\"addStage()\">\n <nz-icon nzType=\"plus\" class=\"color-primary\"></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <button\n nz-button\n nzSize=\"small\"\n [nzType]=\"isMoveMode ? 'primary' : 'default'\"\n nz-tooltip=\"Move mode\"\n (click)=\"isMoveMode = true\"\n >\n <nz-icon><img src=\"/assets/icon/hand-palm.png\" width=\"19\" height=\"19\" /></nz-icon>\n </button>\n <button\n nz-button\n nzSize=\"small\"\n [nzType]=\"!isMoveMode ? 'primary' : 'default'\"\n nz-tooltip=\"Select mode\"\n (click)=\"isMoveMode = false\"\n >\n <nz-icon><img src=\"/assets/icon/cursor.png\" width=\"19\" height=\"19\" /></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <!-- UNDO / REDO -->\n <button\n nz-button\n nzSize=\"small\"\n nzType=\"default\"\n [disabled]=\"undoStack.length === 0\"\n nz-tooltip=\"Undo\"\n (click)=\"undo()\"\n >\n <nz-icon nzType=\"undo\"></nz-icon>\n </button>\n\n <button\n nz-button\n nzSize=\"small\"\n nzType=\"default\"\n [disabled]=\"redoStack.length === 0\"\n nz-tooltip=\"Redo\"\n (click)=\"redo()\"\n >\n <nz-icon nzType=\"redo\"></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <!-- ALIGN -->\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignLeft()\">\u27F8</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignCenter()\">\u2261</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignRight()\">\u27F9</button>\n\n <span class=\"divider\"></span>\n\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignTop()\">\u21D1</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignMiddle()\">\u2550</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignBottom()\">\u21D3</button>\n\n <span class=\"divider\"></span>\n\n <!-- DISTRIBUTE -->\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 3\" (click)=\"distributeHorizontal()\">\n \u21C4\n </button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 3\" (click)=\"distributeVertical()\">\n \u21C5\n </button>\n </div>\n\n <div\n class=\"canvas-content\"\n [class.panning]=\"isMoveMode\"\n [style.transform]=\"'translate(' + panX + 'px,' + panY + 'px)'\"\n >\n <!-- GRID -->\n <div *ngIf=\"wfcSetting.ShowGrid\" class=\"grid-layer\"></div>\n\n <!-- <div class=\"zoom-toolbar\">\n <button nz-button nzSize=\"small\" (click)=\"zoomOut()\">\u2212</button>\n <span>{{ zoom * 100 | number: \"1.0-0\" }}%</span>\n <button nz-button nzSize=\"small\" (click)=\"zoomIn()\">+</button>\n </div> -->\n\n <!-- SVG EDGES -->\n <svg #svg class=\"edges-layer\" width=\"100%\" height=\"100%\" preserveAspectRatio=\"none\">\n <g [attr.transform]=\"svgTransform\">\n <!-- DEFS -->\n <defs>\n <!-- glow effect -->\n <filter id=\"edge-glow\" x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\">\n <feGaussianBlur stdDeviation=\"2\" result=\"blur\" />\n <feMerge>\n <feMergeNode in=\"blur\" />\n <feMergeNode in=\"SourceGraphic\" />\n </feMerge>\n </filter>\n\n <!-- arrow markers -->\n <marker\n id=\"arrow-blue\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n refX=\"10\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"blue\" d=\"M0,0 L10,5 L0,10\"></path>\n </marker>\n\n <marker\n id=\"arrow-red\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n refX=\"10\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"red\" d=\"M0,0 L10,5 L0,10\"></path>\n </marker>\n\n <marker\n id=\"arrow-blue-start\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n viewBox=\"0 0 10 10\"\n refX=\"0\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"blue\" d=\"M10,0 L0,5 L10,10\"></path>\n </marker>\n\n <marker\n id=\"arrow-red-start\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n viewBox=\"0 0 10 10\"\n refX=\"0\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"red\" d=\"M10,0 L0,5 L10,10\"></path>\n </marker>\n </defs>\n\n <!-- EDGES B\u00CCNH TH\u01AF\u1EDCNG -->\n <ng-container *ngFor=\"let e of normalEdges; let i = index\">\n <path\n class=\"edge-hit\"\n [attr.d]=\"buildPath(e)\"\n (mouseenter)=\"onMouseEnterEdge(e)\"\n (mouseleave)=\"onMouseLeaveEdge(e)\"\n (click)=\"onClickEdge(e, $event)\"\n ></path>\n\n <path\n class=\"edge\"\n [attr.id]=\"'edge-path-' + i\"\n [attr.d]=\"buildPath(e)\"\n marker-end=\"url(#arrow-blue)\"\n [attr.marker-start]=\"e.allowBack ? 'url(#arrow-blue-start)' : ''\"\n ></path>\n\n <!-- LABEL -->\n <!-- text b\u00E1m theo line -->\n <!-- \n <text *ngIf=\"e.ActionText\" class=\"edge-label\" dy=\"-6\">\n <textPath [attr.href]=\"'#edge-path-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.ActionText }}\n </textPath>\n </text> \n \n <text *ngIf=\"e.allowBack && e.labelBack\" class=\"edge-label\" dy=\"14\">\n <textPath [attr.href]=\"'#edge-path-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.labelBack }}\n </textPath>\n </text>\n -->\n\n <!-- text th\u1EB3ng n\u1EB1m ngang -->\n <text\n *ngIf=\"e.ActionText\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y - 8\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.ActionText }}\n </text>\n\n <text\n *ngIf=\"e.allowBack && e.labelBack\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y + 14\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.labelBack }}\n </text>\n </ng-container>\n\n <!-- EDGE \u0110ANG HOVER (LU\u00D4N TR\u00CAN C\u00D9NG) -->\n <ng-container *ngFor=\"let e of hoverEdges; let i = index\">\n <path\n class=\"edge-hit\"\n [attr.d]=\"buildPath(e)\"\n (mouseleave)=\"onMouseLeaveEdge(e)\"\n (click)=\"onClickEdge(e, $event)\"\n ></path>\n\n <path\n class=\"edge red\"\n [attr.id]=\"'edge-path-hover-' + i\"\n [attr.d]=\"buildPath(e)\"\n marker-end=\"url(#arrow-red)\"\n [attr.marker-start]=\"e.allowBack ? 'url(#arrow-red-start)' : ''\"\n ></path>\n\n <!-- LABEL -->\n <!-- <text *ngIf=\"e.ActionText\" class=\"edge-label\" dy=\"-6\">\n <textPath [attr.href]=\"'#edge-path-hover-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.ActionText }}\n </textPath>\n </text>\n\n <text *ngIf=\"e.allowBack && e.labelBack\" class=\"edge-label\" dy=\"14\">\n <textPath [attr.href]=\"'#edge-path-hover-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.labelBack }}\n </textPath>\n </text> -->\n\n <text\n *ngIf=\"e.ActionText\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y - 8\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.ActionText }}\n </text>\n\n <text\n *ngIf=\"e.allowBack && e.labelBack\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y + 14\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.labelBack }}\n </text>\n </ng-container>\n\n <!-- preview -->\n <path\n *ngIf=\"connectingFrom\"\n class=\"edge\"\n [attr.d]=\"buildPreviewPath()\"\n stroke-dasharray=\"5,5\"\n marker-end=\"url(#arrow-blue)\"\n ></path>\n </g>\n </svg>\n\n <div\n *ngIf=\"isSelecting && selectStart && selectEnd\"\n class=\"selection-box\"\n [style.left.px]=\"Math.min(selectStart.x, selectEnd.x)\"\n [style.top.px]=\"Math.min(selectStart.y, selectEnd.y)\"\n [style.width.px]=\"Math.abs(selectEnd.x - selectStart.x)\"\n [style.height.px]=\"Math.abs(selectEnd.y - selectStart.y)\"\n ></div>\n\n <!-- lstStage -->\n @for (n of lstStage; track $index) {\n @if (n.StageType == \"NODE\") {\n <nz-card\n #nodeEl\n class=\"workflow-node\"\n [attr.data-id]=\"n.Code\"\n [class.selected]=\"n == selectedStage || n == hoverStage || lstSelectedStageCode.has(n.Code)\"\n [style.left.px]=\"n.editorOption.x\"\n [style.top.px]=\"n.editorOption.y\"\n [class.connecting-source]=\"isConnectingFrom(n) || isDraggingFrom(n) || isSelectedNode(n)\"\n nzSize=\"small\"\n (mousedown)=\"onMouseDownNode($event, n)\"\n (click)=\"$event.stopPropagation(); onClickStage(n)\"\n >\n <div class=\"title\">{{ n.Code }}</div>\n\n <div>{{ n.Name }}</div>\n\n @if (!n.editorOption.isReverse) {\n <!-- connector RIGHT: output -->\n <div class=\"connector connector-right\" (click)=\"onClickConnector($event, n, 'right')\"></div>\n\n <!-- connector LEFT: input -->\n <div class=\"connector connector-left\" (click)=\"onClickConnector($event, n, 'left')\"></div>\n } @else {\n <div class=\"connector connector-right reverse\" (click)=\"onClickConnector($event, n, 'right')\"></div>\n <div class=\"connector connector-left reverse\" (click)=\"onClickConnector($event, n, 'left')\"></div>\n }\n </nz-card>\n }\n <!-- START NODE -->\n @else if (n.StageType === \"START\") {\n <nz-card\n class=\"workflow-node workflow-node-start\"\n style=\"border: unset\"\n [style.left.px]=\"n.editorOption.x\"\n [style.top.px]=\"n.editorOption.y\"\n nzSize=\"small\"\n (mousedown)=\"onMouseDownNode($event, n)\"\n (click)=\"$event.stopPropagation(); onClickStage(n)\"\n >\n <div class=\"title\"> </div>\n\n <nz-tag\n [class.selected]=\"n == selectedStage || lstSelectedStageCode.has(n.Code)\"\n style=\"position: relative; top: -13px\"\n [style.right.px]=\"n.editorOption.isReverseLabel ? -83 : 1\"\n [nzColor]=\"'green'\"\n >\n {{ n.StageType }}\n </nz-tag>\n\n <!-- connector RIGHT: output -->\n <div class=\"connector connector-right connector-start\" (click)=\"onClickConnector($event, n, 'right')\"></div>\n </nz-card>\n }\n\n <!-- END NODE -->\n @else if (n.StageType === \"END\") {\n <nz-card\n class=\"workflow-node workflow-node-end\"\n style=\"border: unset\"\n [style.left.px]=\"n.editorOption.x\"\n [style.top.px]=\"n.editorOption.y\"\n [class.connecting-source]=\"isConnectingFrom(n)\"\n nzSize=\"small\"\n (mousedown)=\"onMouseDownNode($event, n)\"\n (click)=\"$event.stopPropagation(); onClickStage(n)\"\n >\n <div class=\"title\"> </div>\n\n <nz-tag\n [class.selected]=\"n == selectedStage || lstSelectedStageCode.has(n.Code)\"\n style=\"position: relative; top: -13px\"\n [style.right.px]=\"n.editorOption.isReverseLabel ? 65 : -5\"\n [nzColor]=\"'red'\"\n >\n {{ n.StageType }}\n </nz-tag>\n\n <!-- connector LEFT: input -->\n <div class=\"connector connector-end\" (click)=\"onClickConnector($event, n, 'left')\"></div>\n </nz-card>\n }\n }\n\n <!-- POINTS -->\n @for (p of connectingPoints; track $index) {\n @if (p != draggingPoint) {\n <div\n class=\"waypoint\"\n [style.left.px]=\"p.x\"\n [style.top.px]=\"p.y\"\n (mousedown)=\"onmousedownPoint($event, p)\"\n (contextmenu)=\"onRightClickPoint($event, hoverAction!, $index)\"\n ></div>\n } @else {\n <div\n class=\"waypoint dragging\"\n [style.left.px]=\"p.x\"\n [style.top.px]=\"p.y\"\n (mousedown)=\"onmousedownPoint($event, p)\"\n ></div>\n }\n }\n </div>\n</div>\n\n<!-- TEMPLATE -->\n<nz-drawer\n [nzTitle]=\"drawTemplateTitle\"\n nzPlacement=\"right\"\n [nzWidth]=\"500\"\n [nzClosable]=\"false\"\n [nzVisible]=\"drawTemplateVisibel\"\n [nzFooter]=\"footerTplTemplate\"\n (nzOnClose)=\"drawTemplateVisibel = false\"\n>\n <ng-template #drawTemplateTitle> <nz-icon nzType=\"setting\"></nz-icon> Template </ng-template>\n <ng-container *nzDrawerContent>\n <extend-input [label]=\"'Code'\" [(_ngModel)]=\"template.Code\"></extend-input>\n <extend-input [label]=\"'Name'\" [(_ngModel)]=\"template.Name\"></extend-input>\n <extend-select\n [label]=\"'Type'\"\n [lstItem]=\"lstTemplateType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"template.DocType\"\n ></extend-select>\n <extend-textarea [label]=\"'Desscription'\" [(_ngModel)]=\"template.Description\"></extend-textarea>\n <extend-select\n [label]=\"'Print template'\"\n [lstItem]=\"lstTemplatePrint\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"template.TemplatePrint\"\n ></extend-select>\n <extend-checkbox [label]=\"'Active'\" [(_ngModel)]=\"template.IsActive\"></extend-checkbox>\n\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> Stage status</h3>\n\n @for (tag of template.lstStageStatus; track tag) {\n <nz-tag\n [nzMode]=\"checkRemoveableStageStatus(tag) ? 'closeable' : 'default'\"\n (nzOnClose)=\"handleCloseStageStatus(tag)\"\n >\n {{ sliceTagName(tag.Code + (tag.Name ? \" - \" + tag.Name : \"\")) }}\n </nz-tag>\n }\n\n <br *ngIf=\"template.lstStageStatus && template.lstStageStatus.length\" />\n\n @if (!inputStageStatusVisible) {\n <nz-tag class=\"editable-tag\" nzNoAnimation (click)=\"showInputStageStatus()\">\n <nz-icon nzType=\"plus\" />\n New Action type\n </nz-tag>\n } @else {\n <input\n #inputStageStatusElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Code\"\n [(ngModel)]=\"inputStageStatusCode\"\n (keydown.enter)=\"inputStageStatusNameElement.select()\"\n />\n <input\n #inputStageStatusNameElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Name\"\n [(ngModel)]=\"inputStageStatusName\"\n (blur)=\"handleInputStageStatusConfirm()\"\n (keydown.enter)=\"handleInputStageStatusConfirm()\"\n />\n }\n\n <box [height]=\"16\"></box>\n\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> Action type</h3>\n\n @for (tag of template.lstActionType; track tag) {\n <nz-tag\n [nzMode]=\"checkRemoveableActionType(tag) ? 'closeable' : 'default'\"\n (nzOnClose)=\"handleCloseActionType(tag)\"\n >\n {{ sliceTagName(tag.Code + (tag.Name ? \" - \" + tag.Name : \"\")) }}\n </nz-tag>\n }\n\n <br *ngIf=\"template.lstActionType && template.lstActionType.length\" />\n\n @if (!inputActionTypeVisible) {\n <nz-tag class=\"editable-tag\" nzNoAnimation (click)=\"showInputActionType()\">\n <nz-icon nzType=\"plus\" />\n New Action type\n </nz-tag>\n } @else {\n <input\n #inputActionTypeElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Code\"\n [(ngModel)]=\"inputActionTypeCode\"\n (keydown.enter)=\"inputActionTypeNameElement.select()\"\n />\n <input\n #inputActionTypeNameElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Name\"\n [(ngModel)]=\"inputActionTypeName\"\n (blur)=\"handleInputActionTypeConfirm()\"\n (keydown.enter)=\"handleInputActionTypeConfirm()\"\n />\n }\n\n <box [height]=\"16\"></box>\n\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> Action status</h3>\n\n @for (tag of template.lstActionStatus; track tag) {\n <nz-tag [nzMode]=\"checkRemoveableActionStatus(tag) ? 'closeable' : 'default'\" (nzOnClose)=\"handleClose(tag)\">\n {{ sliceTagName(tag.Code + (tag.Name ? \" - \" + tag.Name : \"\")) }}\n </nz-tag>\n }\n\n <br *ngIf=\"template.lstActionStatus && template.lstActionStatus.length\" />\n\n @if (!inputVisible) {\n <nz-tag class=\"editable-tag\" nzNoAnimation (click)=\"showInput()\">\n <nz-icon nzType=\"plus\" />\n New Action status\n </nz-tag>\n } @else {\n <input\n #inputElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"+ New Action status\"\n [(ngModel)]=\"inputValue\"\n (blur)=\"handleInputConfirm()\"\n (keydown.enter)=\"handleInputConfirm()\"\n />\n }\n </ng-container>\n\n <ng-template #footerTplTemplate>\n <div nz-flex [nzGap]=\"6\">\n <button nz-button (click)=\"drawTemplateVisibel = false\">Close</button>\n <button nz-button nzDanger (click)=\"save()\">Save</button>\n </div>\n </ng-template>\n</nz-drawer>\n\n<!-- STAGE -->\n<nz-drawer\n [nzTitle]=\"drawerTitleStage\"\n [nzPlacement]=\"selectedStage?.editorOption?.drawerPosition ? selectedStage?.editorOption?.drawerPosition : 'right'\"\n [nzVisible]=\"!!selectedStage\"\n [nzWidth]=\"750\"\n [nzClosable]=\"false\"\n [nzFooter]=\"footerTplNode\"\n (nzOnClose)=\"selectedStage = undefined\"\n>\n <ng-template #drawerTitleStage>\n <div nz-row nzJustify=\"space-between\">\n @if (selectedStage) {\n @if (selectedStage.editorOption.drawerPosition == \"left\") {\n <button\n nz-button\n nzSize=\"small\"\n nz-tooltip=\"To the right\"\n (click)=\"selectedStage.editorOption.drawerPosition = 'right'\"\n >\n <nz-icon nzType=\"double-right\"></nz-icon>\n </button>\n STAGE\n } @else {\n STAGE\n <button\n nz-button\n nzSize=\"small\"\n nz-tooltip=\"To the left\"\n (click)=\"selectedStage.editorOption.drawerPosition = 'left'\"\n >\n <nz-icon nzType=\"double-left\"></nz-icon>\n </button>\n }\n }\n </div>\n </ng-template>\n <ng-container *nzDrawerContent>\n <ng-container *ngIf=\"selectedStage\">\n <nz-radio-group [(ngModel)]=\"selectedStage.StageType\">\n <label nz-radio nzValue=\"START\" [nzDisabled]=\"selectedStage.StageType != 'START'\">START</label>\n <label nz-radio nzValue=\"NODE\" [nzDisabled]=\"selectedStage.StageType != 'NODE'\">NODE</label>\n <label nz-radio nzValue=\"END\" [nzDisabled]=\"selectedStage.StageType != 'END'\">END</label>\n </nz-radio-group>\n\n <box [height]=\"16\"></box>\n\n <div nz-row [nzGutter]=\"32\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Code'\"\n [layOutType]=\"'vertical'\"\n [disabled]=\"['START', 'END'].indexOf(selectedStage!.StageType) >= 0\"\n [required]=\"true\"\n [(_ngModel)]=\"selectedStage.Code\"\n ></extend-input>\n\n <extend-textarea\n nz-col\n [nzSpan]=\"16\"\n [label]=\"'Name'\"\n [layOutType]=\"'vertical'\"\n [autoSize]=\"true\"\n [disabled]=\"['START', 'END'].indexOf(selectedStage!.StageType) >= 0\"\n [required]=\"true\"\n [(_ngModel)]=\"selectedStage.Name\"\n ></extend-textarea>\n </div>\n\n <div nz-row [nzGutter]=\"32\">\n <extend-input-number\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Sequence'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"selectedStage.SeqValue\"\n ></extend-input-number>\n\n <extend-select\n nz-col\n [nzSpan]=\"16\"\n [label]=\"'Org implement'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstOrg\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedStage.OrgImplCode\"\n ></extend-select>\n </div>\n\n @if ([\"START\", \"END\"].indexOf(selectedStage.StageType) < 0) {\n <extend-checkbox\n [label]=\"'Reverse'\"\n [labelSpan]=\"0\"\n [(_ngModel)]=\"selectedStage.editorOption.isReverse\"\n ></extend-checkbox>\n\n <extend-checkbox\n [label]=\"'Require user action'\"\n [labelSpan]=\"0\"\n [(_ngModel)]=\"selectedStage.IsRequireUser\"\n ></extend-checkbox>\n } @else {\n <extend-checkbox\n [label]=\"'Reverse'\"\n [labelSpan]=\"0\"\n [(_ngModel)]=\"selectedStage.editorOption.isReverseLabel\"\n ></extend-checkbox>\n }\n\n <box [height]=\"16\"></box>\n\n <div nz-row [nzGutter]=\"16\">\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> List Action</h3>\n <div nz-col>\n <button nz-button nzType=\"primary\" nzSize=\"small\" (click)=\"addAction()\">\n <nz-icon nzType=\"plus\"></nz-icon>\n </button>\n </div>\n </div>\n\n <nz-table\n nzSize=\"small\"\n [nzData]=\"selectedStage.lstAction || []\"\n [nzShowPagination]=\"false\"\n [nzNoResult]=\"' '\"\n >\n <thead>\n <tr [hidden]=\"true\">\n <th nzWidth=\"50px\"></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n @for (action of selectedStage.lstAction; track $index) {\n <tr>\n <td>\n <nz-icon\n nzType=\"delete\"\n nzTheme=\"outline\"\n class=\"color-warn cursor-pointer icon-size-16\"\n (click)=\"$event.stopPropagation(); deleteAction(action)\"\n ></nz-icon>\n </td>\n <td (click)=\"hoverAction = action\">\n <div nz-row [nzGutter]=\"16\" class=\"form-item-no-bottom\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action text'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"action.ActionText\"\n (_ngModelChange)=\"onchangeActionText(action)\"\n ></extend-input>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action type'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.ActionType\"\n ></extend-select>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.ActionStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.StageStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstStage\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.ToStage\"\n (_ngModelChange)=\"onchangeNextStage(action)\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.NextStageStatus\"\n ></extend-select>\n </div>\n </td>\n </tr>\n }\n </tbody>\n </nz-table>\n\n <box [height]=\"16\"></box>\n </ng-container>\n </ng-container>\n\n <ng-template #footerTplNode>\n <div\n nz-flex\n [nzGap]=\"6\"\n [nzJustify]=\"selectedStage && selectedStage.editorOption.drawerPosition == 'left' ? 'end' : 'start'\"\n >\n <button nz-button (click)=\"selectedStage = undefined\">Close</button>\n <button\n *ngIf=\"selectedStage && ['START', 'END'].indexOf(selectedStage.StageType) < 0\"\n nz-button\n nzDanger\n (click)=\"deleteNode()\"\n >\n Delete\n </button>\n </div>\n </ng-template>\n</nz-drawer>\n\n<!-- EDGE -->\n<nz-drawer\n [nzTitle]=\"drawerTitleAction\"\n nzTitle=\"ACTION\"\n [nzPlacement]=\"selectedAction?.editorOption?.drawerPosition ? selectedAction?.editorOption?.drawerPosition : 'right'\"\n [nzClosable]=\"false\"\n [nzWidth]=\"750\"\n [nzVisible]=\"!!selectedAction\"\n [nzFooter]=\"footerTplAction\"\n (nzOnClose)=\"selectedAction = undefined\"\n>\n <ng-template #drawerTitleAction>\n <div nz-row nzJustify=\"space-between\">\n @if (selectedAction) {\n @if (selectedAction.editorOption.drawerPosition == \"left\") {\n <button\n nz-button\n nzSize=\"small\"\n nz-tooltip=\"To the right\"\n (click)=\"selectedAction.editorOption.drawerPosition = 'right'\"\n >\n <nz-icon nzType=\"double-right\"></nz-icon>\n </button>\n ACTION\n } @else {\n ACTION\n <button\n nz-button\n nzSize=\"small\"\n nz-tooltip=\"To the left\"\n (click)=\"selectedAction.editorOption.drawerPosition = 'left'\"\n >\n <nz-icon nzType=\"double-left\"></nz-icon>\n </button>\n }\n }\n </div>\n </ng-template>\n <ng-container *nzDrawerContent>\n <ng-container *ngIf=\"selectedAction\">\n <strong>{{ selectedAction.FromStage }} -> {{ selectedAction.ToStage }}</strong>\n\n <box [height]=\"16\"></box>\n\n <div nz-row [nzGutter]=\"16\" class=\"form-item-no-bottom\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action text'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"selectedAction.ActionText\"\n (_ngModelChange)=\"onchangeActionText(selectedAction)\"\n ></extend-input>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action type'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.ActionType\"\n ></extend-select>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.ActionStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.StageStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstStage\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.ToStage\"\n (_ngModelChange)=\"onchangeNextStage(selectedAction)\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.NextStageStatus\"\n ></extend-select>\n </div>\n\n <!-- <box [height]=\"16\"></box> -->\n <nz-divider></nz-divider>\n\n <extend-checkbox\n [label]=\"'Allow back'\"\n [labelSpan]=\"0\"\n [(_ngModel)]=\"selectedAction.allowBack\"\n (_ngModelChange)=\"onchangeAllowBack(selectedAction)\"\n ></extend-checkbox>\n\n <box [height]=\"16\"></box>\n\n @if (selectedAction.allowBack) {\n <strong>{{ selectedAction.ToStage }} -> {{ selectedAction.FromStage }}</strong>\n\n @if (selectedBackAction) {\n <div nz-row [nzGutter]=\"16\" class=\"form-item-no-bottom\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action text'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"selectedBackAction.ActionText\"\n (_ngModelChange)=\"onchangeActionText(selectedBackAction)\"\n ></extend-input>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action type'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.ActionType\"\n ></extend-select>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.ActionStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.StageStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstStage\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.ToStage\"\n (_ngModelChange)=\"onchangeNextStage(selectedBackAction)\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.NextStageStatus\"\n ></extend-select>\n </div>\n }\n }\n </ng-container>\n </ng-container>\n <ng-template #footerTplAction>\n <div\n nz-flex\n [nzGap]=\"6\"\n [nzJustify]=\"selectedAction && selectedAction.editorOption.drawerPosition == 'left' ? 'end' : 'start'\"\n >\n <button nz-button (click)=\"selectedAction = undefined\">Close</button>\n <button nz-button nzDanger (click)=\"deleteAction(selectedAction!)\">Delete</button>\n </div>\n </ng-template>\n</nz-drawer>\n\n<!-- setting editor -->\n<nz-drawer\n [nzTitle]=\"drawSettingTitle\"\n nzPlacement=\"right\"\n [nzClosable]=\"false\"\n [nzVisible]=\"settingVisible\"\n (nzOnClose)=\"settingVisible = false\"\n>\n <ng-template #drawSettingTitle> <nz-icon nzType=\"setting\"></nz-icon> Editor </ng-template>\n <ng-container *nzDrawerContent>\n <div class=\"form-item-no-bottom\">\n <extend-checkbox [label]=\"'Show grid'\" [labelSpan]=\"0\" [(_ngModel)]=\"wfcSetting.ShowGrid\"></extend-checkbox>\n\n <box [height]=\"16\"></box>\n </div>\n </ng-container>\n</nz-drawer>\n", styles: ["@charset \"UTF-8\";.workflow-canvas{position:relative;width:100%;height:600px;background:#f0f2f5;cursor:default;overflow:hidden;outline:1px dashed rgba(0,0,0,.1)}.workflow-canvas .edges-layer{position:absolute;inset:0;width:100%;height:100%;z-index:1}.workflow-canvas .edges-layer path{stroke-width:2;fill:none}.canvas-content{transform-origin:0 0;width:10000px;height:10000px}.canvas-content{outline:1px dashed red}.canvas-content.panning{cursor:grab}.canvas-content.panning:active{cursor:grabbing}.workflow-canvas.panning{cursor:grab}.workflow-canvas.panning:active{cursor:grabbing}.workflow-canvas.connecting,.workflow-canvas.connecting .workflow-node{cursor:crosshair}.workflow-node{position:absolute;width:160px;cursor:grab;-webkit-user-select:none;user-select:none;z-index:2}.workflow-node:active{cursor:grabbing}.workflow-node .title{font-weight:600;margin-bottom:6px}.workflow-node.connecting-source,.workflow-node.selected,.workflow-node:hover:not(.workflow-node-start,.workflow-node-end){outline:2px dashed #1890ff}.workflow-node-start{background-color:unset;display:flex;justify-content:right}.workflow-node-end{background-color:unset;display:flex}.connector{position:absolute;top:39px;width:12px;height:12px;background:#1890ff;border-radius:50%;transform:translateY(-50%);cursor:crosshair;transition:box-shadow .15s ease-out,transform .15s ease-out}.connector:hover{box-shadow:0 0 0 3px #1890ff4d;transform:translateY(-50%) scale(1.15)}.connector-right{right:-8px;background:orange}.connector-right.reverse,.connector-left{left:-8px}.connector-left.reverse{left:unset;right:-8px}.connector-start{width:16px;height:16px;right:-3px;background:green;box-shadow:0 0 0 3px #1890ff4d}.connector-end{width:16px;height:16px;left:-6px;background:#000;box-shadow:0 0 0 3px #1890ff4d}.edge{cursor:pointer;stroke:#1890ff;stroke-linecap:round;stroke-linejoin:round;stroke-width:2;fill:none;transition:stroke .15s ease}.edge-hit{stroke:transparent;stroke-width:18px!important;fill:none;cursor:pointer}.edge-hit:hover+.edge{stroke:#ff4d4f;stroke-width:2}.workflow-canvas.dragging-point .edge-hit{pointer-events:none}.edge:hover+.edge-label{fill:#1890ff;font-weight:500}.edge-label{font-size:12px;fill:#555;pointer-events:none;-webkit-user-select:none;user-select:none}.blue{stroke:#1890ff!important}.red{stroke:#ff4d4f!important;box-shadow:0 0 0 3px #1890ff4d!important}.workflow-svg{background:transparent;overflow:visible}.waypoint{position:absolute;width:10px;height:10px;background:#ff4d4f;border-radius:50%;transform:translate(-50%,-50%) scale(1);cursor:move;z-index:1;transition:transform .12s ease-out,background-color .12s ease-out,box-shadow .12s ease-out}.waypoint:hover{background:#ff7875;transform:translate(-50%,-50%) scale(1.25);box-shadow:0 0 0 4px #ff787559}.waypoint.dragging{transition:none;transform:translate(-50%,-50%) scale(1.15);pointer-events:none}.workflow-canvas.dragging-point svg{cursor:grabbing}.selection-box{position:absolute;border:1px dashed #1890ff;background:#1890ff1a;pointer-events:none}.toolbar{position:absolute;top:8px;left:8px;display:flex;gap:4px;padding:6px;background:#fff;border-radius:6px;box-shadow:0 2px 8px #00000026;z-index:100}.toolbar .divider{width:1px;background:#e5e5e5;margin:0 2px}.zoom-toolbar{position:absolute;top:8px;left:8px;z-index:10;display:flex;align-items:center;gap:6px;background:#fff;padding:4px 6px;border-radius:6px;box-shadow:0 2px 6px #00000026}.zoom-toolbar span{min-width:40px;text-align:center;font-size:12px}nz-tag.selected{outline:2px dashed #1890ff}.grid-layer{position:absolute;inset:0;pointer-events:none;z-index:0;background-image:radial-gradient(rgba(0,0,0,.08) 1px,transparent 1px);background-size:20px 20px}.grid-layer{background-image:linear-gradient(to right,rgba(0,0,0,.06) 1px,transparent 1px),linear-gradient(to bottom,rgba(0,0,0,.06) 1px,transparent 1px);background-size:20px 20px}.editable-tag{background:#fff;border-style:dashed}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: NzCardModule }, { kind: "component", type: i3$1.NzCardComponent, selector: "nz-card", inputs: ["nzBordered", "nzLoading", "nzHoverable", "nzBodyStyle", "nzCover", "nzActions", "nzType", "nzSize", "nzTitle", "nzExtra"], exportAs: ["nzCard"] }, { kind: "ngmodule", type: NzDrawerModule }, { kind: "component", type: i4$1.NzDrawerComponent, selector: "nz-drawer", inputs: ["nzContent", "nzCloseIcon", "nzClosable", "nzMaskClosable", "nzMask", "nzCloseOnNavigation", "nzNoAnimation", "nzKeyboard", "nzTitle", "nzExtra", "nzFooter", "nzPlacement", "nzSize", "nzMaskStyle", "nzBodyStyle", "nzWrapClassName", "nzWidth", "nzHeight", "nzZIndex", "nzOffsetX", "nzOffsetY", "nzVisible"], outputs: ["nzOnViewInit", "nzOnClose", "nzVisibleChange"], exportAs: ["nzDrawer"] }, { kind: "directive", type: i4$1.NzDrawerContentDirective, selector: "[nzDrawerContent]", exportAs: ["nzDrawerContent"] }, { kind: "ngmodule", type: NzTagModule }, { kind: "component", type: i5$2.NzTagComponent, selector: "nz-tag", inputs: ["nzMode", "nzColor", "nzChecked", "nzBordered"], outputs: ["nzOnClose", "nzCheckedChange"], exportAs: ["nzTag"] }, { kind: "ngmodule", type: NzRadioModule }, { kind: "component", type: i6$3.NzRadioComponent, selector: "[nz-radio],[nz-radio-button]", inputs: ["nzValue", "nzDisabled", "nzAutoFocus", "nz-radio-button"], exportAs: ["nzRadio"] }, { kind: "component", type: i6$3.NzRadioGroupComponent, selector: "nz-radio-group", inputs: ["nzDisabled", "nzButtonStyle", "nzSize", "nzName"], exportAs: ["nzRadioGroup"] }, { kind: "ngmodule", type: NzIconModule }, { kind: "directive", type: i2.NzIconDirective, selector: "nz-icon,[nz-icon]", inputs: ["nzSpin", "nzRotate", "nzType", "nzTheme", "nzTwotoneColor", "nzIconfont"], exportAs: ["nzIcon"] }, { kind: "component", type: Box, selector: "box", inputs: ["display", "width", "height"] }, { kind: "ngmodule", type: NzButtonModule }, { kind: "component", type: i8.NzButtonComponent, selector: "button[nz-button], a[nz-button]", inputs: ["nzBlock", "nzGhost", "nzSearch", "nzLoading", "nzDanger", "disabled", "tabIndex", "nzType", "nzShape", "nzSize"], exportAs: ["nzButton"] }, { kind: "directive", type: i9.ɵNzTransitionPatchDirective, selector: "[nz-button], nz-button-group, [nz-icon], nz-icon, [nz-menu-item], [nz-submenu], nz-select-top-control, nz-select-placeholder, nz-input-group", inputs: ["hidden"] }, { kind: "directive", type: i10.NzWaveDirective, selector: "[nz-wave],button[nz-button]:not([nzType=\"link\"]):not([nzType=\"text\"])", inputs: ["nzWaveExtraNode"], exportAs: ["nzWave"] }, { kind: "ngmodule", type: NzToolTipModule }, { kind: "directive", type: i11.NzTooltipDirective, selector: "[nz-tooltip]", inputs: ["nzTooltipTitle", "nzTooltipTitleContext", "nz-tooltip", "nzTooltipTrigger", "nzTooltipPlacement", "nzTooltipOrigin", "nzTooltipVisible", "nzTooltipMouseEnterDelay", "nzTooltipMouseLeaveDelay", "nzTooltipOverlayClassName", "nzTooltipOverlayStyle", "nzTooltipArrowPointAtCenter", "cdkConnectedOverlayPush", "nzTooltipColor"], outputs: ["nzTooltipVisibleChange"], exportAs: ["nzTooltip"] }, { kind: "component", type: ExtendInput, selector: "extend-input", inputs: ["layOutType", "label", "placeHolder", "labelAlign", "inputClass", "labelSpan", "allowClear", "disabled", "readOnly", "required", "noBottom", "selectModeType", "autocomplete", "inputWidth", "inputHeight", "borderBottomOnly", "displayInline", "size", "lstItem", "displayField", "valueField", "formData", "controlName", "_ngModel"], outputs: ["_ngModelChange", "onclickClearIcon", "onenter"] }, { kind: "component", type: ExtendSelectComponent, selector: "extend-select", inputs: ["layOutType", "label", "placeHolder", "labelAlign", "labelSpan", "disabled", "required", "noBottom", "multiple", "showSelectAll", "maxTagCount", "inputWidth", "inputHeight", "borderBottomOnly", "displayInline", "size", "lstItem", "displayField", "displayFields", "valueField", "formData", "controlName", "_ngModel"], outputs: ["_ngModelChange", "itemChange", "onFocus"] }, { kind: "component", type: ExtendCheckbox, selector: "extend-checkbox", inputs: ["label", "labelSpan", "disabled", "formData", "controlName", "valueType", "_ngModel"], outputs: ["_ngModelChange"] }, { kind: "component", type: ExtendTextArea, selector: "extend-textarea", inputs: ["layOutType", "label", "placeHolder", "labelAlign", "labelSpan", "inputSpan", "disabled", "required", "noBottom", "selectModeType", "inputClass", "minRows", "maxRows", "autoSize", "lstItem", "displayField", "valueField", "formData", "controlName", "_ngModel"], outputs: ["_ngModelChange"] }, { kind: "ngmodule", type: NzInputModule }, { kind: "directive", type: i6$1.NzInputDirective, selector: "input[nz-input],textarea[nz-input]", inputs: ["nzBorderless", "nzSize", "nzStepperless", "nzStatus", "disabled"], exportAs: ["nzInput"] }, { kind: "ngmodule", type: NzGridModule }, { kind: "directive", type: i4.NzColDirective, selector: "[nz-col],nz-col,nz-form-control,nz-form-label", inputs: ["nzFlex", "nzSpan", "nzOrder", "nzOffset", "nzPush", "nzPull", "nzXs", "nzSm", "nzMd", "nzLg", "nzXl", "nzXXl"], exportAs: ["nzCol"] }, { kind: "directive", type: i4.NzRowDirective, selector: "[nz-row],nz-row,nz-form-item", inputs: ["nzAlign", "nzJustify", "nzGutter"], exportAs: ["nzRow"] }, { kind: "ngmodule", type: NzFlexModule }, { kind: "directive", type: i14.NzFlexDirective, selector: "[nz-flex],nz-flex", inputs: ["nzVertical", "nzJustify", "nzAlign", "nzGap", "nzWrap", "nzFlex"], exportAs: ["nzFlex"] }, { kind: "component", type: ExtendInputNumber, selector: "extend-input-number", inputs: ["layOutType", "label", "placeHolder", "labelAlign", "labelSpan", "disabled", "required", "noBottom", "size", "min", "max", "precision", "inputWidth", "inputHeight", "borderBottomOnly", "displayInline", "separatorType", "formData", "controlName", "_ngModel"], outputs: ["_ngModelChange"] }, { kind: "ngmodule", type: NzTableModule }, { kind: "component", type: i15.NzTableComponent, selector: "nz-table", inputs: ["nzTableLayout", "nzShowTotal", "nzItemRender", "nzTitle", "nzFooter", "nzNoResult", "nzPageSizeOptions", "nzVirtualItemSize", "nzVirtualMaxBufferPx", "nzVirtualMinBufferPx", "nzVirtualForTrackBy", "nzLoadingDelay", "nzPageIndex", "nzPageSize", "nzTotal", "nzWidthConfig", "nzData", "nzCustomColumn", "nzPaginationPosition", "nzScroll", "noDataVirtualHeight", "nzPaginationType", "nzFrontPagination", "nzTemplateMode", "nzShowPagination", "nzLoading", "nzOuterBordered", "nzLoadingIndicator", "nzBordered", "nzSize", "nzShowSizeChanger", "nzHideOnSinglePage", "nzShowQuickJumper", "nzSimple"], outputs: ["nzPageSizeChange", "nzPageIndexChange", "nzQueryParams", "nzCurrentPageDataChange", "nzCustomColumnChange"], exportAs: ["nzTable"] }, { kind: "directive", type: i15.NzTableCellDirective, selector: "th:not(.nz-disable-th):not([mat-cell]), td:not(.nz-disable-td):not([mat-cell])" }, { kind: "directive", type: i15.NzThMeasureDirective, selector: "th", inputs: ["nzWidth", "colspan", "colSpan", "rowspan", "rowSpan"] }, { kind: "component", type: i15.NzTheadComponent, selector: "thead:not(.ant-table-thead)", outputs: ["nzSortOrderChange"] }, { kind: "component", type: i15.NzTbodyComponent, selector: "tbody" }, { kind: "directive", type: i15.NzTrDirective, selector: "tr:not([mat-row]):not([mat-header-row]):not([nz-table-measure-row]):not([nzExpand]):not([nz-table-fixed-row])" }, { kind: "ngmodule", type: NzDividerModule }, { kind: "component", type: i16.NzDividerComponent, selector: "nz-divider", inputs: ["nzText", "nzType", "nzOrientation", "nzVariant", "nzDashed", "nzPlain"], exportAs: ["nzDivider"] }] });
|
|
4244
4277
|
}
|
|
4245
4278
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.7", ngImport: i0, type: WorkflowEditorComponent, decorators: [{
|
|
4246
4279
|
type: Component,
|
|
@@ -4265,7 +4298,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.7", ngImpor
|
|
|
4265
4298
|
ExtendInputNumber,
|
|
4266
4299
|
NzTableModule,
|
|
4267
4300
|
NzDividerModule,
|
|
4268
|
-
], template: "<div\n #canvasRef\n class=\"workflow-canvas\"\n [class.connecting]=\"!!connectingFrom\"\n [class.dragging-point]=\"!!draggingPoint\"\n [style.width.px]=\"CANVAS_WIDTH\"\n [style.height.px]=\"CANVAS_HEIGHT\"\n (mousedown)=\"onMouseDownCanvas($event)\"\n (mousemove)=\"onMouseMoveCanvas($event)\"\n (mouseup)=\"onMouseUpCanvas($event)\"\n (click)=\"onClickCanvas($event)\"\n>\n <!-- \n\n [style.width.px]=\"getCanvasWidth()\"\n [style.height.px]=\"getCanvasHeight()\" \n\n style=\"width: 100%; height: calc(100vh - 120px)\"\n \n -->\n\n <div class=\"toolbar\" (mousedown)=\"$event.stopPropagation()\" (click)=\"$event.stopPropagation()\">\n <button nz-button nzSize=\"small\" nz-tooltip=\"Editor setting\" (click)=\"settingVisible = true\">\n <nz-icon nzType=\"setting\"></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <button nz-button nzSize=\"small\" nz-tooltip=\"Template setting\" (click)=\"drawTemplateVisibel = true\">\n <nz-icon nzType=\"setting\"></nz-icon> T\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <button nz-button nzSize=\"small\" nzDanger nz-tooltip=\"Save\" (click)=\"save()\">\n <nz-icon nzType=\"save\"></nz-icon>\n </button>\n <button nz-button nzSize=\"small\" nz-tooltip=\"Add stage\" (click)=\"addStage()\">\n <nz-icon nzType=\"plus\" class=\"color-primary\"></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <button\n nz-button\n nzSize=\"small\"\n [nzType]=\"isMoveMode ? 'primary' : 'default'\"\n nz-tooltip=\"Move mode\"\n (click)=\"isMoveMode = true\"\n >\n <nz-icon><img src=\"/assets/icon/hand-palm.png\" width=\"19\" height=\"19\" /></nz-icon>\n </button>\n <button\n nz-button\n nzSize=\"small\"\n [nzType]=\"!isMoveMode ? 'primary' : 'default'\"\n nz-tooltip=\"Select mode\"\n (click)=\"isMoveMode = false\"\n >\n <nz-icon><img src=\"/assets/icon/cursor.png\" width=\"19\" height=\"19\" /></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <!-- UNDO / REDO -->\n <button\n nz-button\n nzSize=\"small\"\n nzType=\"default\"\n [disabled]=\"undoStack.length === 0\"\n nz-tooltip=\"Undo\"\n (click)=\"undo()\"\n >\n <nz-icon nzType=\"undo\"></nz-icon>\n </button>\n\n <button\n nz-button\n nzSize=\"small\"\n nzType=\"default\"\n [disabled]=\"redoStack.length === 0\"\n nz-tooltip=\"Redo\"\n (click)=\"redo()\"\n >\n <nz-icon nzType=\"redo\"></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <!-- ALIGN -->\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignLeft()\">\u27F8</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignCenter()\">\u2261</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignRight()\">\u27F9</button>\n\n <span class=\"divider\"></span>\n\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignTop()\">\u21D1</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignMiddle()\">\u2550</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignBottom()\">\u21D3</button>\n\n <span class=\"divider\"></span>\n\n <!-- DISTRIBUTE -->\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 3\" (click)=\"distributeHorizontal()\">\n \u21C4\n </button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 3\" (click)=\"distributeVertical()\">\n \u21C5\n </button>\n </div>\n\n <div\n class=\"canvas-content\"\n [class.panning]=\"isMoveMode\"\n [style.transform]=\"'translate(' + panX + 'px,' + panY + 'px)'\"\n >\n <!-- GRID -->\n <div *ngIf=\"wfcSetting.ShowGrid\" class=\"grid-layer\"></div>\n\n <!-- <div class=\"zoom-toolbar\">\n <button nz-button nzSize=\"small\" (click)=\"zoomOut()\">\u2212</button>\n <span>{{ zoom * 100 | number: \"1.0-0\" }}%</span>\n <button nz-button nzSize=\"small\" (click)=\"zoomIn()\">+</button>\n </div> -->\n\n <!-- SVG EDGES -->\n <svg #svg class=\"edges-layer\" width=\"100%\" height=\"100%\" preserveAspectRatio=\"none\">\n <g [attr.transform]=\"svgTransform\">\n <!-- DEFS -->\n <defs>\n <!-- glow effect -->\n <filter id=\"edge-glow\" x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\">\n <feGaussianBlur stdDeviation=\"2\" result=\"blur\" />\n <feMerge>\n <feMergeNode in=\"blur\" />\n <feMergeNode in=\"SourceGraphic\" />\n </feMerge>\n </filter>\n\n <!-- arrow markers -->\n <marker\n id=\"arrow-blue\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n refX=\"10\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"blue\" d=\"M0,0 L10,5 L0,10\"></path>\n </marker>\n\n <marker\n id=\"arrow-red\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n refX=\"10\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"red\" d=\"M0,0 L10,5 L0,10\"></path>\n </marker>\n\n <marker\n id=\"arrow-blue-start\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n viewBox=\"0 0 10 10\"\n refX=\"0\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"blue\" d=\"M10,0 L0,5 L10,10\"></path>\n </marker>\n\n <marker\n id=\"arrow-red-start\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n viewBox=\"0 0 10 10\"\n refX=\"0\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"red\" d=\"M10,0 L0,5 L10,10\"></path>\n </marker>\n </defs>\n\n <!-- EDGES B\u00CCNH TH\u01AF\u1EDCNG -->\n <ng-container *ngFor=\"let e of normalEdges; let i = index\">\n <path\n class=\"edge-hit\"\n [attr.d]=\"buildPath(e)\"\n (mouseenter)=\"onMouseEnterEdge(e)\"\n (mouseleave)=\"onMouseLeaveEdge(e)\"\n (click)=\"onClickEdge(e, $event)\"\n ></path>\n\n <path\n class=\"edge\"\n [attr.id]=\"'edge-path-' + i\"\n [attr.d]=\"buildPath(e)\"\n marker-end=\"url(#arrow-blue)\"\n [attr.marker-start]=\"e.allowBack ? 'url(#arrow-blue-start)' : ''\"\n ></path>\n\n <!-- LABEL -->\n <!-- text b\u00E1m theo line -->\n <!-- \n <text *ngIf=\"e.ActionText\" class=\"edge-label\" dy=\"-6\">\n <textPath [attr.href]=\"'#edge-path-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.ActionText }}\n </textPath>\n </text> \n \n <text *ngIf=\"e.allowBack && e.labelBack\" class=\"edge-label\" dy=\"14\">\n <textPath [attr.href]=\"'#edge-path-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.labelBack }}\n </textPath>\n </text>\n -->\n\n <!-- text th\u1EB3ng n\u1EB1m ngang -->\n <text\n *ngIf=\"e.ActionText\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y - 8\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.ActionText }}\n </text>\n\n <text\n *ngIf=\"e.allowBack && e.labelBack\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y + 14\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.labelBack }}\n </text>\n </ng-container>\n\n <!-- EDGE \u0110ANG HOVER (LU\u00D4N TR\u00CAN C\u00D9NG) -->\n <ng-container *ngFor=\"let e of hoverEdges; let i = index\">\n <path\n class=\"edge-hit\"\n [attr.d]=\"buildPath(e)\"\n (mouseleave)=\"onMouseLeaveEdge(e)\"\n (click)=\"onClickEdge(e, $event)\"\n ></path>\n\n <path\n class=\"edge red\"\n [attr.id]=\"'edge-path-hover-' + i\"\n [attr.d]=\"buildPath(e)\"\n marker-end=\"url(#arrow-red)\"\n [attr.marker-start]=\"e.allowBack ? 'url(#arrow-red-start)' : ''\"\n ></path>\n\n <!-- LABEL -->\n <!-- <text *ngIf=\"e.ActionText\" class=\"edge-label\" dy=\"-6\">\n <textPath [attr.href]=\"'#edge-path-hover-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.ActionText }}\n </textPath>\n </text>\n\n <text *ngIf=\"e.allowBack && e.labelBack\" class=\"edge-label\" dy=\"14\">\n <textPath [attr.href]=\"'#edge-path-hover-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.labelBack }}\n </textPath>\n </text> -->\n\n <text\n *ngIf=\"e.ActionText\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y - 8\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.ActionText }}\n </text>\n\n <text\n *ngIf=\"e.allowBack && e.labelBack\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y + 14\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.labelBack }}\n </text>\n </ng-container>\n\n <!-- preview -->\n <path\n *ngIf=\"connectingFrom\"\n class=\"edge\"\n [attr.d]=\"buildPreviewPath()\"\n stroke-dasharray=\"5,5\"\n marker-end=\"url(#arrow-blue)\"\n ></path>\n </g>\n </svg>\n\n <div\n *ngIf=\"isSelecting && selectStart && selectEnd\"\n class=\"selection-box\"\n [style.left.px]=\"Math.min(selectStart.x, selectEnd.x)\"\n [style.top.px]=\"Math.min(selectStart.y, selectEnd.y)\"\n [style.width.px]=\"Math.abs(selectEnd.x - selectStart.x)\"\n [style.height.px]=\"Math.abs(selectEnd.y - selectStart.y)\"\n ></div>\n\n <!-- lstStage -->\n @for (n of lstStage; track $index) {\n @if (n.StageType == \"NODE\") {\n <nz-card\n #nodeEl\n class=\"workflow-node\"\n [attr.data-id]=\"n.Code\"\n [class.selected]=\"n == selectedStage || n == hoverStage || lstSelectedStageCode.has(n.Code)\"\n [style.left.px]=\"n.x\"\n [style.top.px]=\"n.y\"\n [class.connecting-source]=\"isConnectingFrom(n) || isDraggingFrom(n) || isSelectedNode(n)\"\n nzSize=\"small\"\n (mousedown)=\"onMouseDownNode($event, n)\"\n (click)=\"$event.stopPropagation(); onClickStage(n)\"\n >\n <div class=\"title\">{{ n.Code }}</div>\n\n <div>{{ n.Name }}</div>\n\n @if (!n.isReverse) {\n <!-- connector RIGHT: output -->\n <div class=\"connector connector-right\" (click)=\"onClickConnector($event, n, 'right')\"></div>\n\n <!-- connector LEFT: input -->\n <div class=\"connector connector-left\" (click)=\"onClickConnector($event, n, 'left')\"></div>\n } @else {\n <div class=\"connector connector-right reverse\" (click)=\"onClickConnector($event, n, 'right')\"></div>\n <div class=\"connector connector-left reverse\" (click)=\"onClickConnector($event, n, 'left')\"></div>\n }\n </nz-card>\n }\n <!-- START NODE -->\n @else if (n.StageType === \"START\") {\n <nz-card\n class=\"workflow-node workflow-node-start\"\n style=\"border: unset\"\n [style.left.px]=\"n.x\"\n [style.top.px]=\"n.y\"\n nzSize=\"small\"\n (mousedown)=\"onMouseDownNode($event, n)\"\n (click)=\"$event.stopPropagation(); onClickStage(n)\"\n >\n <div class=\"title\"> </div>\n\n <nz-tag\n [class.selected]=\"n == selectedStage || lstSelectedStageCode.has(n.Code)\"\n style=\"position: relative; top: -13px\"\n [style.right.px]=\"n.isReverseLabel ? -83 : 1\"\n [nzColor]=\"'green'\"\n >\n {{ n.StageType }}\n </nz-tag>\n\n <!-- connector RIGHT: output -->\n <div class=\"connector connector-right connector-start\" (click)=\"onClickConnector($event, n, 'right')\"></div>\n </nz-card>\n }\n\n <!-- END NODE -->\n @else if (n.StageType === \"END\") {\n <nz-card\n class=\"workflow-node workflow-node-end\"\n style=\"border: unset\"\n [style.left.px]=\"n.x\"\n [style.top.px]=\"n.y\"\n [class.connecting-source]=\"isConnectingFrom(n)\"\n nzSize=\"small\"\n (mousedown)=\"onMouseDownNode($event, n)\"\n (click)=\"$event.stopPropagation(); onClickStage(n)\"\n >\n <div class=\"title\"> </div>\n\n <nz-tag\n [class.selected]=\"n == selectedStage || lstSelectedStageCode.has(n.Code)\"\n style=\"position: relative; top: -13px\"\n [style.right.px]=\"n.isReverseLabel ? 65 : -5\"\n [nzColor]=\"'red'\"\n >\n {{ n.StageType }}\n </nz-tag>\n\n <!-- connector LEFT: input -->\n <div class=\"connector connector-end\" (click)=\"onClickConnector($event, n, 'left')\"></div>\n </nz-card>\n }\n }\n\n <!-- POINTS -->\n @for (p of connectingPoints; track $index) {\n @if (p != draggingPoint) {\n <div\n class=\"waypoint\"\n [style.left.px]=\"p.x\"\n [style.top.px]=\"p.y\"\n (mousedown)=\"onmousedownPoint($event, p)\"\n (contextmenu)=\"onRightClickPoint($event, hoverEdge!, $index)\"\n ></div>\n } @else {\n <div\n class=\"waypoint dragging\"\n [style.left.px]=\"p.x\"\n [style.top.px]=\"p.y\"\n (mousedown)=\"onmousedownPoint($event, p)\"\n ></div>\n }\n }\n </div>\n</div>\n\n<!-- TEMPLATE -->\n<nz-drawer\n [nzTitle]=\"drawTemplateTitle\"\n nzPlacement=\"right\"\n [nzWidth]=\"500\"\n [nzClosable]=\"false\"\n [nzVisible]=\"drawTemplateVisibel\"\n [nzFooter]=\"footerTplTemplate\"\n (nzOnClose)=\"drawTemplateVisibel = false\"\n>\n <ng-template #drawTemplateTitle> <nz-icon nzType=\"setting\"></nz-icon> Template </ng-template>\n <ng-container *nzDrawerContent>\n <extend-input [label]=\"'Code'\" [(_ngModel)]=\"template.Code\"></extend-input>\n <extend-input [label]=\"'Name'\" [(_ngModel)]=\"template.Name\"></extend-input>\n <extend-select\n [label]=\"'Type'\"\n [lstItem]=\"lstTemplateType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"template.DocType\"\n ></extend-select>\n <extend-textarea [label]=\"'Desscription'\" [(_ngModel)]=\"template.Description\"></extend-textarea>\n <extend-select\n [label]=\"'Print template'\"\n [lstItem]=\"lstTemplatePrint\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"template.TemplatePrint\"\n ></extend-select>\n <extend-checkbox [label]=\"'Active'\" [(_ngModel)]=\"template.IsActive\"></extend-checkbox>\n\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> Stage status</h3>\n\n @for (tag of template.lstStageStatus; track tag) {\n <nz-tag\n [nzMode]=\"checkRemoveableStageStatus(tag) ? 'closeable' : 'default'\"\n (nzOnClose)=\"handleCloseStageStatus(tag)\"\n >\n {{ sliceTagName(tag.Code + (tag.Name ? \" - \" + tag.Name : \"\")) }}\n </nz-tag>\n }\n\n <br *ngIf=\"template.lstStageStatus && template.lstStageStatus.length\" />\n\n @if (!inputStageStatusVisible) {\n <nz-tag class=\"editable-tag\" nzNoAnimation (click)=\"showInputStageStatus()\">\n <nz-icon nzType=\"plus\" />\n New Action type\n </nz-tag>\n } @else {\n <input\n #inputStageStatusElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Code\"\n [(ngModel)]=\"inputStageStatusCode\"\n (keydown.enter)=\"inputStageStatusNameElement.select()\"\n />\n <input\n #inputStageStatusNameElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Name\"\n [(ngModel)]=\"inputStageStatusName\"\n (blur)=\"handleInputStageStatusConfirm()\"\n (keydown.enter)=\"handleInputStageStatusConfirm()\"\n />\n }\n\n <box [height]=\"16\"></box>\n\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> Action type</h3>\n\n @for (tag of template.lstActionType; track tag) {\n <nz-tag\n [nzMode]=\"checkRemoveableActionType(tag) ? 'closeable' : 'default'\"\n (nzOnClose)=\"handleCloseActionType(tag)\"\n >\n {{ sliceTagName(tag.Code + (tag.Name ? \" - \" + tag.Name : \"\")) }}\n </nz-tag>\n }\n\n <br *ngIf=\"template.lstActionType && template.lstActionType.length\" />\n\n @if (!inputActionTypeVisible) {\n <nz-tag class=\"editable-tag\" nzNoAnimation (click)=\"showInputActionType()\">\n <nz-icon nzType=\"plus\" />\n New Action type\n </nz-tag>\n } @else {\n <input\n #inputActionTypeElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Code\"\n [(ngModel)]=\"inputActionTypeCode\"\n (keydown.enter)=\"inputActionTypeNameElement.select()\"\n />\n <input\n #inputActionTypeNameElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Name\"\n [(ngModel)]=\"inputActionTypeName\"\n (blur)=\"handleInputActionTypeConfirm()\"\n (keydown.enter)=\"handleInputActionTypeConfirm()\"\n />\n }\n\n <box [height]=\"16\"></box>\n\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> Action status</h3>\n\n @for (tag of template.lstActionStatus; track tag) {\n <nz-tag [nzMode]=\"checkRemoveableActionStatus(tag) ? 'closeable' : 'default'\" (nzOnClose)=\"handleClose(tag)\">\n {{ sliceTagName(tag.Code + (tag.Name ? \" - \" + tag.Name : \"\")) }}\n </nz-tag>\n }\n\n <br *ngIf=\"template.lstActionStatus && template.lstActionStatus.length\" />\n\n @if (!inputVisible) {\n <nz-tag class=\"editable-tag\" nzNoAnimation (click)=\"showInput()\">\n <nz-icon nzType=\"plus\" />\n New Action status\n </nz-tag>\n } @else {\n <input\n #inputElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"+ New Action status\"\n [(ngModel)]=\"inputValue\"\n (blur)=\"handleInputConfirm()\"\n (keydown.enter)=\"handleInputConfirm()\"\n />\n }\n </ng-container>\n\n <ng-template #footerTplTemplate>\n <div nz-flex [nzGap]=\"6\">\n <button nz-button (click)=\"drawTemplateVisibel = false\">Close</button>\n <button nz-button nzDanger (click)=\"save()\">Save</button>\n </div>\n </ng-template>\n</nz-drawer>\n\n<!-- STAGE -->\n<nz-drawer\n [nzTitle]=\"drawerTitleStage\"\n [nzPlacement]=\"selectedStage?.drawerPosition ? selectedStage?.drawerPosition : 'right'\"\n [nzVisible]=\"!!selectedStage\"\n [nzWidth]=\"750\"\n [nzClosable]=\"false\"\n [nzFooter]=\"footerTplNode\"\n (nzOnClose)=\"selectedStage = undefined\"\n>\n <ng-template #drawerTitleStage>\n <div nz-row nzJustify=\"space-between\">\n @if (selectedStage) {\n @if (selectedStage.drawerPosition == \"left\") {\n <button nz-button nzSize=\"small\" nz-tooltip=\"To the right\" (click)=\"selectedStage.drawerPosition = 'right'\">\n <nz-icon nzType=\"double-right\"></nz-icon>\n </button>\n STAGE\n } @else {\n STAGE\n <button nz-button nzSize=\"small\" nz-tooltip=\"To the left\" (click)=\"selectedStage.drawerPosition = 'left'\">\n <nz-icon nzType=\"double-left\"></nz-icon>\n </button>\n }\n }\n </div>\n </ng-template>\n <ng-container *nzDrawerContent>\n <ng-container *ngIf=\"selectedStage\">\n <nz-radio-group [(ngModel)]=\"selectedStage.StageType\">\n <label nz-radio nzValue=\"START\" [nzDisabled]=\"true\">START</label>\n <label nz-radio nzValue=\"NODE\" [nzDisabled]=\"true\">NODE</label>\n <label nz-radio nzValue=\"END\" [nzDisabled]=\"true\">END</label>\n </nz-radio-group>\n\n <box [height]=\"16\"></box>\n\n <div nz-row [nzGutter]=\"32\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Code'\"\n [layOutType]=\"'vertical'\"\n [disabled]=\"['START', 'END'].indexOf(selectedStage!.StageType) >= 0\"\n [required]=\"true\"\n [(_ngModel)]=\"selectedStage.Code\"\n ></extend-input>\n\n <extend-textarea\n nz-col\n [nzSpan]=\"16\"\n [label]=\"'Name'\"\n [layOutType]=\"'vertical'\"\n [autoSize]=\"true\"\n [disabled]=\"['START', 'END'].indexOf(selectedStage!.StageType) >= 0\"\n [required]=\"true\"\n [(_ngModel)]=\"selectedStage.Name\"\n ></extend-textarea>\n </div>\n\n <div nz-row [nzGutter]=\"32\">\n <extend-input-number\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Sequence'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"selectedStage.SeqValue\"\n ></extend-input-number>\n\n <extend-select\n nz-col\n [nzSpan]=\"16\"\n [label]=\"'Org implement'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstOrg\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedStage.App_Org_Id\"\n ></extend-select>\n </div>\n\n @if ([\"START\", \"END\"].indexOf(selectedStage.StageType) < 0) {\n <extend-checkbox [label]=\"'Reverse'\" [labelSpan]=\"0\" [(_ngModel)]=\"selectedStage.isReverse\"></extend-checkbox>\n\n <extend-checkbox\n [label]=\"'Require user action'\"\n [labelSpan]=\"0\"\n [(_ngModel)]=\"selectedStage.IsRequireUser\"\n ></extend-checkbox>\n } @else {\n <extend-checkbox\n [label]=\"'Reverse'\"\n [labelSpan]=\"0\"\n [(_ngModel)]=\"selectedStage.isReverseLabel\"\n ></extend-checkbox>\n }\n\n <box [height]=\"16\"></box>\n\n <div nz-row [nzGutter]=\"16\">\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> List Action</h3>\n <div nz-col>\n <button nz-button nzType=\"primary\" nzSize=\"small\" (click)=\"addAction()\">\n <nz-icon nzType=\"plus\"></nz-icon>\n </button>\n </div>\n </div>\n\n <nz-table\n nzSize=\"small\"\n [nzData]=\"selectedStage.lstAction || []\"\n [nzShowPagination]=\"false\"\n [nzNoResult]=\"' '\"\n >\n <thead>\n <tr [hidden]=\"true\">\n <th nzWidth=\"50px\"></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n @for (action of selectedStage.lstAction; track $index) {\n <tr>\n <td>\n <nz-icon\n nzType=\"delete\"\n nzTheme=\"outline\"\n class=\"color-warn cursor-pointer icon-size-16\"\n (click)=\"$event.stopPropagation(); deleteAction(action)\"\n ></nz-icon>\n </td>\n <td (click)=\"hoverEdge = action\">\n <div nz-row [nzGutter]=\"16\" class=\"form-item-no-bottom\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action text'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"action.ActionText\"\n (_ngModelChange)=\"onchangeActionText(action)\"\n ></extend-input>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action type'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.ActionType\"\n ></extend-select>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.ActionStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.StageStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstStage\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.ToStage\"\n (_ngModelChange)=\"onchangeNextStage(action)\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.NextStageStatus\"\n ></extend-select>\n\n <nz-divider\n *ngIf=\"selectedStage.lstAction && $index + 1 < selectedStage.lstAction.length\"\n style=\"margin: 16px 0px 8px 0px; background-color: orange\"\n ></nz-divider>\n </div>\n </td>\n </tr>\n }\n </tbody>\n </nz-table>\n\n <box [height]=\"16\"></box>\n </ng-container>\n </ng-container>\n\n <ng-template #footerTplNode>\n <div nz-flex [nzGap]=\"6\" [nzJustify]=\"selectedStage && selectedStage.drawerPosition == 'left' ? 'end' : 'start'\">\n <button nz-button (click)=\"selectedStage = undefined\">Close</button>\n <button\n *ngIf=\"selectedStage && ['START', 'END'].indexOf(selectedStage.StageType) < 0\"\n nz-button\n nzDanger\n (click)=\"deleteNode()\"\n >\n Delete\n </button>\n </div>\n </ng-template>\n</nz-drawer>\n\n<!-- EDGE -->\n<nz-drawer\n nzTitle=\"ACTION\"\n nzPlacement=\"right\"\n [nzClosable]=\"false\"\n [nzWidth]=\"750\"\n [nzVisible]=\"!!selectedAction\"\n (nzOnClose)=\"selectedAction = undefined\"\n>\n <ng-container *nzDrawerContent>\n <ng-container *ngIf=\"selectedAction\">\n <strong>{{ selectedAction.FromStage }} -> {{ selectedAction.ToStage }}</strong>\n\n <box [height]=\"16\"></box>\n\n <div nz-row [nzGutter]=\"16\" class=\"form-item-no-bottom\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action text'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"selectedAction.ActionText\"\n (_ngModelChange)=\"onchangeActionText(selectedAction)\"\n ></extend-input>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action type'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.ActionType\"\n ></extend-select>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.ActionStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.StageStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstStage\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.ToStage\"\n (_ngModelChange)=\"onchangeNextStage(selectedAction)\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.NextStageStatus\"\n ></extend-select>\n </div>\n\n <!-- <box [height]=\"16\"></box> -->\n <nz-divider></nz-divider>\n\n <extend-checkbox\n [label]=\"'Allow back'\"\n [labelSpan]=\"0\"\n [(_ngModel)]=\"selectedAction.allowBack\"\n (_ngModelChange)=\"onchangeAllowBack(selectedAction)\"\n ></extend-checkbox>\n\n <box [height]=\"16\"></box>\n\n @if (selectedAction.allowBack) {\n <strong>{{ selectedAction.ToStage }} -> {{ selectedAction.FromStage }}</strong>\n\n @if (selectedBackAction) {\n <div nz-row [nzGutter]=\"16\" class=\"form-item-no-bottom\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action text'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"selectedBackAction.ActionText\"\n (_ngModelChange)=\"onchangeActionText(selectedBackAction)\"\n ></extend-input>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action type'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.ActionType\"\n ></extend-select>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.ActionStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.StageStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstStage\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.ToStage\"\n (_ngModelChange)=\"onchangeNextStage(selectedBackAction)\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.NextStageStatus\"\n ></extend-select>\n </div>\n }\n }\n </ng-container>\n </ng-container>\n</nz-drawer>\n\n<!-- setting editor -->\n<nz-drawer\n [nzTitle]=\"drawSettingTitle\"\n nzPlacement=\"right\"\n [nzClosable]=\"false\"\n [nzVisible]=\"settingVisible\"\n (nzOnClose)=\"settingVisible = false\"\n>\n <ng-template #drawSettingTitle> <nz-icon nzType=\"setting\"></nz-icon> Editor </ng-template>\n <ng-container *nzDrawerContent>\n <div class=\"form-item-no-bottom\">\n <extend-checkbox [label]=\"'Show grid'\" [labelSpan]=\"0\" [(_ngModel)]=\"wfcSetting.ShowGrid\"></extend-checkbox>\n\n <box [height]=\"16\"></box>\n\n <extend-input-number [label]=\"'Canvas width'\" [(_ngModel)]=\"CANVAS_WIDTH\"></extend-input-number>\n <box [height]=\"16\"></box>\n <extend-input-number [label]=\"'Canvas height'\" [(_ngModel)]=\"CANVAS_HEIGHT\"></extend-input-number>\n </div>\n </ng-container>\n</nz-drawer>\n", styles: ["@charset \"UTF-8\";.workflow-canvas{position:relative;width:100%;height:600px;background:#f0f2f5;cursor:default;overflow:hidden;outline:1px dashed rgba(0,0,0,.1)}.workflow-canvas .edges-layer{position:absolute;inset:0;width:100%;height:100%;z-index:1}.workflow-canvas .edges-layer path{stroke-width:2;fill:none}.canvas-content{transform-origin:0 0;width:10000px;height:10000px}.canvas-content{outline:1px dashed red}.canvas-content.panning{cursor:grab}.canvas-content.panning:active{cursor:grabbing}.workflow-canvas.panning{cursor:grab}.workflow-canvas.panning:active{cursor:grabbing}.workflow-canvas.connecting,.workflow-canvas.connecting .workflow-node{cursor:crosshair}.workflow-node{position:absolute;width:160px;cursor:grab;-webkit-user-select:none;user-select:none;z-index:2}.workflow-node:active{cursor:grabbing}.workflow-node .title{font-weight:600;margin-bottom:6px}.workflow-node.connecting-source,.workflow-node.selected,.workflow-node:hover:not(.workflow-node-start,.workflow-node-end){outline:2px dashed #1890ff}.workflow-node-start{background-color:unset;display:flex;justify-content:right}.workflow-node-end{background-color:unset;display:flex}.connector{position:absolute;top:39px;width:12px;height:12px;background:#1890ff;border-radius:50%;transform:translateY(-50%);cursor:crosshair;transition:box-shadow .15s ease-out,transform .15s ease-out}.connector:hover{box-shadow:0 0 0 3px #1890ff4d;transform:translateY(-50%) scale(1.15)}.connector-right{right:-8px;background:orange}.connector-right.reverse,.connector-left{left:-8px}.connector-left.reverse{left:unset;right:-8px}.connector-start{width:16px;height:16px;right:-3px;background:green;box-shadow:0 0 0 3px #1890ff4d}.connector-end{width:16px;height:16px;left:-6px;background:#000;box-shadow:0 0 0 3px #1890ff4d}.edge{cursor:pointer;stroke:#1890ff;stroke-linecap:round;stroke-linejoin:round;stroke-width:2;fill:none;transition:stroke .15s ease}.edge-hit{stroke:transparent;stroke-width:18px!important;fill:none;cursor:pointer}.edge-hit:hover+.edge{stroke:#ff4d4f;stroke-width:2}.workflow-canvas.dragging-point .edge-hit{pointer-events:none}.edge:hover+.edge-label{fill:#1890ff;font-weight:500}.edge-label{font-size:12px;fill:#555;pointer-events:none;-webkit-user-select:none;user-select:none}.blue{stroke:#1890ff!important}.red{stroke:#ff4d4f!important;box-shadow:0 0 0 3px #1890ff4d!important}.workflow-svg{background:transparent;overflow:visible}.waypoint{position:absolute;width:10px;height:10px;background:#ff4d4f;border-radius:50%;transform:translate(-50%,-50%) scale(1);cursor:move;z-index:1;transition:transform .12s ease-out,background-color .12s ease-out,box-shadow .12s ease-out}.waypoint:hover{background:#ff7875;transform:translate(-50%,-50%) scale(1.25);box-shadow:0 0 0 4px #ff787559}.waypoint.dragging{transition:none;transform:translate(-50%,-50%) scale(1.15);pointer-events:none}.workflow-canvas.dragging-point svg{cursor:grabbing}.selection-box{position:absolute;border:1px dashed #1890ff;background:#1890ff1a;pointer-events:none}.toolbar{position:absolute;top:8px;left:8px;display:flex;gap:4px;padding:6px;background:#fff;border-radius:6px;box-shadow:0 2px 8px #00000026;z-index:100}.toolbar .divider{width:1px;background:#e5e5e5;margin:0 2px}.zoom-toolbar{position:absolute;top:8px;left:8px;z-index:10;display:flex;align-items:center;gap:6px;background:#fff;padding:4px 6px;border-radius:6px;box-shadow:0 2px 6px #00000026}.zoom-toolbar span{min-width:40px;text-align:center;font-size:12px}nz-tag.selected{outline:2px dashed #1890ff}.grid-layer{position:absolute;inset:0;pointer-events:none;z-index:0;background-image:radial-gradient(rgba(0,0,0,.08) 1px,transparent 1px);background-size:20px 20px}.grid-layer{background-image:linear-gradient(to right,rgba(0,0,0,.06) 1px,transparent 1px),linear-gradient(to bottom,rgba(0,0,0,.06) 1px,transparent 1px);background-size:20px 20px}.editable-tag{background:#fff;border-style:dashed}\n"] }]
|
|
4301
|
+
], template: "<div\n #canvasRef\n class=\"workflow-canvas\"\n [class.connecting]=\"!!connectingFrom\"\n [class.dragging-point]=\"!!draggingPoint\"\n [style.width.px]=\"CANVAS_WIDTH\"\n [style.height.px]=\"CANVAS_HEIGHT\"\n (mousedown)=\"onMouseDownCanvas($event)\"\n (mousemove)=\"onMouseMoveCanvas($event)\"\n (mouseup)=\"onMouseUpCanvas($event)\"\n (click)=\"onClickCanvas($event)\"\n>\n <!-- \n\n [style.width.px]=\"getCanvasWidth()\"\n [style.height.px]=\"getCanvasHeight()\" \n\n style=\"width: 100%; height: calc(100vh - 120px)\"\n \n -->\n\n <div class=\"toolbar\" (mousedown)=\"$event.stopPropagation()\" (click)=\"$event.stopPropagation()\">\n <button nz-button nzSize=\"small\" nz-tooltip=\"Editor setting\" (click)=\"settingVisible = true\">\n <nz-icon nzType=\"setting\"></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <button nz-button nzSize=\"small\" nz-tooltip=\"Template setting\" (click)=\"drawTemplateVisibel = true\">\n <nz-icon nzType=\"setting\"></nz-icon> T\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <button nz-button nzSize=\"small\" nzDanger nz-tooltip=\"Save\" (click)=\"save()\">\n <nz-icon nzType=\"save\"></nz-icon>\n </button>\n <button nz-button nzSize=\"small\" nz-tooltip=\"Add stage\" (click)=\"addStage()\">\n <nz-icon nzType=\"plus\" class=\"color-primary\"></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <button\n nz-button\n nzSize=\"small\"\n [nzType]=\"isMoveMode ? 'primary' : 'default'\"\n nz-tooltip=\"Move mode\"\n (click)=\"isMoveMode = true\"\n >\n <nz-icon><img src=\"/assets/icon/hand-palm.png\" width=\"19\" height=\"19\" /></nz-icon>\n </button>\n <button\n nz-button\n nzSize=\"small\"\n [nzType]=\"!isMoveMode ? 'primary' : 'default'\"\n nz-tooltip=\"Select mode\"\n (click)=\"isMoveMode = false\"\n >\n <nz-icon><img src=\"/assets/icon/cursor.png\" width=\"19\" height=\"19\" /></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <!-- UNDO / REDO -->\n <button\n nz-button\n nzSize=\"small\"\n nzType=\"default\"\n [disabled]=\"undoStack.length === 0\"\n nz-tooltip=\"Undo\"\n (click)=\"undo()\"\n >\n <nz-icon nzType=\"undo\"></nz-icon>\n </button>\n\n <button\n nz-button\n nzSize=\"small\"\n nzType=\"default\"\n [disabled]=\"redoStack.length === 0\"\n nz-tooltip=\"Redo\"\n (click)=\"redo()\"\n >\n <nz-icon nzType=\"redo\"></nz-icon>\n </button>\n\n <box [width]=\"1\"></box>\n <span class=\"divider\"></span>\n <box [width]=\"1\"></box>\n\n <!-- ALIGN -->\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignLeft()\">\u27F8</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignCenter()\">\u2261</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignRight()\">\u27F9</button>\n\n <span class=\"divider\"></span>\n\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignTop()\">\u21D1</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignMiddle()\">\u2550</button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 2\" (click)=\"alignBottom()\">\u21D3</button>\n\n <span class=\"divider\"></span>\n\n <!-- DISTRIBUTE -->\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 3\" (click)=\"distributeHorizontal()\">\n \u21C4\n </button>\n <button nz-button nzSize=\"small\" [disabled]=\"lstSelectedStageCode.size < 3\" (click)=\"distributeVertical()\">\n \u21C5\n </button>\n </div>\n\n <div\n class=\"canvas-content\"\n [class.panning]=\"isMoveMode\"\n [style.transform]=\"'translate(' + panX + 'px,' + panY + 'px)'\"\n >\n <!-- GRID -->\n <div *ngIf=\"wfcSetting.ShowGrid\" class=\"grid-layer\"></div>\n\n <!-- <div class=\"zoom-toolbar\">\n <button nz-button nzSize=\"small\" (click)=\"zoomOut()\">\u2212</button>\n <span>{{ zoom * 100 | number: \"1.0-0\" }}%</span>\n <button nz-button nzSize=\"small\" (click)=\"zoomIn()\">+</button>\n </div> -->\n\n <!-- SVG EDGES -->\n <svg #svg class=\"edges-layer\" width=\"100%\" height=\"100%\" preserveAspectRatio=\"none\">\n <g [attr.transform]=\"svgTransform\">\n <!-- DEFS -->\n <defs>\n <!-- glow effect -->\n <filter id=\"edge-glow\" x=\"-50%\" y=\"-50%\" width=\"200%\" height=\"200%\">\n <feGaussianBlur stdDeviation=\"2\" result=\"blur\" />\n <feMerge>\n <feMergeNode in=\"blur\" />\n <feMergeNode in=\"SourceGraphic\" />\n </feMerge>\n </filter>\n\n <!-- arrow markers -->\n <marker\n id=\"arrow-blue\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n refX=\"10\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"blue\" d=\"M0,0 L10,5 L0,10\"></path>\n </marker>\n\n <marker\n id=\"arrow-red\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n refX=\"10\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"red\" d=\"M0,0 L10,5 L0,10\"></path>\n </marker>\n\n <marker\n id=\"arrow-blue-start\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n viewBox=\"0 0 10 10\"\n refX=\"0\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"blue\" d=\"M10,0 L0,5 L10,10\"></path>\n </marker>\n\n <marker\n id=\"arrow-red-start\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n viewBox=\"0 0 10 10\"\n refX=\"0\"\n refY=\"5\"\n orient=\"auto\"\n markerUnits=\"strokeWidth\"\n >\n <path class=\"red\" d=\"M10,0 L0,5 L10,10\"></path>\n </marker>\n </defs>\n\n <!-- EDGES B\u00CCNH TH\u01AF\u1EDCNG -->\n <ng-container *ngFor=\"let e of normalEdges; let i = index\">\n <path\n class=\"edge-hit\"\n [attr.d]=\"buildPath(e)\"\n (mouseenter)=\"onMouseEnterEdge(e)\"\n (mouseleave)=\"onMouseLeaveEdge(e)\"\n (click)=\"onClickEdge(e, $event)\"\n ></path>\n\n <path\n class=\"edge\"\n [attr.id]=\"'edge-path-' + i\"\n [attr.d]=\"buildPath(e)\"\n marker-end=\"url(#arrow-blue)\"\n [attr.marker-start]=\"e.allowBack ? 'url(#arrow-blue-start)' : ''\"\n ></path>\n\n <!-- LABEL -->\n <!-- text b\u00E1m theo line -->\n <!-- \n <text *ngIf=\"e.ActionText\" class=\"edge-label\" dy=\"-6\">\n <textPath [attr.href]=\"'#edge-path-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.ActionText }}\n </textPath>\n </text> \n \n <text *ngIf=\"e.allowBack && e.labelBack\" class=\"edge-label\" dy=\"14\">\n <textPath [attr.href]=\"'#edge-path-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.labelBack }}\n </textPath>\n </text>\n -->\n\n <!-- text th\u1EB3ng n\u1EB1m ngang -->\n <text\n *ngIf=\"e.ActionText\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y - 8\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.ActionText }}\n </text>\n\n <text\n *ngIf=\"e.allowBack && e.labelBack\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y + 14\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.labelBack }}\n </text>\n </ng-container>\n\n <!-- EDGE \u0110ANG HOVER (LU\u00D4N TR\u00CAN C\u00D9NG) -->\n <ng-container *ngFor=\"let e of hoverEdges; let i = index\">\n <path\n class=\"edge-hit\"\n [attr.d]=\"buildPath(e)\"\n (mouseleave)=\"onMouseLeaveEdge(e)\"\n (click)=\"onClickEdge(e, $event)\"\n ></path>\n\n <path\n class=\"edge red\"\n [attr.id]=\"'edge-path-hover-' + i\"\n [attr.d]=\"buildPath(e)\"\n marker-end=\"url(#arrow-red)\"\n [attr.marker-start]=\"e.allowBack ? 'url(#arrow-red-start)' : ''\"\n ></path>\n\n <!-- LABEL -->\n <!-- <text *ngIf=\"e.ActionText\" class=\"edge-label\" dy=\"-6\">\n <textPath [attr.href]=\"'#edge-path-hover-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.ActionText }}\n </textPath>\n </text>\n\n <text *ngIf=\"e.allowBack && e.labelBack\" class=\"edge-label\" dy=\"14\">\n <textPath [attr.href]=\"'#edge-path-hover-' + i\" startOffset=\"50%\" text-anchor=\"middle\">\n {{ e.labelBack }}\n </textPath>\n </text> -->\n\n <text\n *ngIf=\"e.ActionText\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y - 8\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.ActionText }}\n </text>\n\n <text\n *ngIf=\"e.allowBack && e.labelBack\"\n class=\"edge-label\"\n [attr.x]=\"getEdgeLabelPosition(e).x\"\n [attr.y]=\"getEdgeLabelPosition(e).y + 14\"\n [attr.text-anchor]=\"'middle'\"\n >\n {{ e.labelBack }}\n </text>\n </ng-container>\n\n <!-- preview -->\n <path\n *ngIf=\"connectingFrom\"\n class=\"edge\"\n [attr.d]=\"buildPreviewPath()\"\n stroke-dasharray=\"5,5\"\n marker-end=\"url(#arrow-blue)\"\n ></path>\n </g>\n </svg>\n\n <div\n *ngIf=\"isSelecting && selectStart && selectEnd\"\n class=\"selection-box\"\n [style.left.px]=\"Math.min(selectStart.x, selectEnd.x)\"\n [style.top.px]=\"Math.min(selectStart.y, selectEnd.y)\"\n [style.width.px]=\"Math.abs(selectEnd.x - selectStart.x)\"\n [style.height.px]=\"Math.abs(selectEnd.y - selectStart.y)\"\n ></div>\n\n <!-- lstStage -->\n @for (n of lstStage; track $index) {\n @if (n.StageType == \"NODE\") {\n <nz-card\n #nodeEl\n class=\"workflow-node\"\n [attr.data-id]=\"n.Code\"\n [class.selected]=\"n == selectedStage || n == hoverStage || lstSelectedStageCode.has(n.Code)\"\n [style.left.px]=\"n.editorOption.x\"\n [style.top.px]=\"n.editorOption.y\"\n [class.connecting-source]=\"isConnectingFrom(n) || isDraggingFrom(n) || isSelectedNode(n)\"\n nzSize=\"small\"\n (mousedown)=\"onMouseDownNode($event, n)\"\n (click)=\"$event.stopPropagation(); onClickStage(n)\"\n >\n <div class=\"title\">{{ n.Code }}</div>\n\n <div>{{ n.Name }}</div>\n\n @if (!n.editorOption.isReverse) {\n <!-- connector RIGHT: output -->\n <div class=\"connector connector-right\" (click)=\"onClickConnector($event, n, 'right')\"></div>\n\n <!-- connector LEFT: input -->\n <div class=\"connector connector-left\" (click)=\"onClickConnector($event, n, 'left')\"></div>\n } @else {\n <div class=\"connector connector-right reverse\" (click)=\"onClickConnector($event, n, 'right')\"></div>\n <div class=\"connector connector-left reverse\" (click)=\"onClickConnector($event, n, 'left')\"></div>\n }\n </nz-card>\n }\n <!-- START NODE -->\n @else if (n.StageType === \"START\") {\n <nz-card\n class=\"workflow-node workflow-node-start\"\n style=\"border: unset\"\n [style.left.px]=\"n.editorOption.x\"\n [style.top.px]=\"n.editorOption.y\"\n nzSize=\"small\"\n (mousedown)=\"onMouseDownNode($event, n)\"\n (click)=\"$event.stopPropagation(); onClickStage(n)\"\n >\n <div class=\"title\"> </div>\n\n <nz-tag\n [class.selected]=\"n == selectedStage || lstSelectedStageCode.has(n.Code)\"\n style=\"position: relative; top: -13px\"\n [style.right.px]=\"n.editorOption.isReverseLabel ? -83 : 1\"\n [nzColor]=\"'green'\"\n >\n {{ n.StageType }}\n </nz-tag>\n\n <!-- connector RIGHT: output -->\n <div class=\"connector connector-right connector-start\" (click)=\"onClickConnector($event, n, 'right')\"></div>\n </nz-card>\n }\n\n <!-- END NODE -->\n @else if (n.StageType === \"END\") {\n <nz-card\n class=\"workflow-node workflow-node-end\"\n style=\"border: unset\"\n [style.left.px]=\"n.editorOption.x\"\n [style.top.px]=\"n.editorOption.y\"\n [class.connecting-source]=\"isConnectingFrom(n)\"\n nzSize=\"small\"\n (mousedown)=\"onMouseDownNode($event, n)\"\n (click)=\"$event.stopPropagation(); onClickStage(n)\"\n >\n <div class=\"title\"> </div>\n\n <nz-tag\n [class.selected]=\"n == selectedStage || lstSelectedStageCode.has(n.Code)\"\n style=\"position: relative; top: -13px\"\n [style.right.px]=\"n.editorOption.isReverseLabel ? 65 : -5\"\n [nzColor]=\"'red'\"\n >\n {{ n.StageType }}\n </nz-tag>\n\n <!-- connector LEFT: input -->\n <div class=\"connector connector-end\" (click)=\"onClickConnector($event, n, 'left')\"></div>\n </nz-card>\n }\n }\n\n <!-- POINTS -->\n @for (p of connectingPoints; track $index) {\n @if (p != draggingPoint) {\n <div\n class=\"waypoint\"\n [style.left.px]=\"p.x\"\n [style.top.px]=\"p.y\"\n (mousedown)=\"onmousedownPoint($event, p)\"\n (contextmenu)=\"onRightClickPoint($event, hoverAction!, $index)\"\n ></div>\n } @else {\n <div\n class=\"waypoint dragging\"\n [style.left.px]=\"p.x\"\n [style.top.px]=\"p.y\"\n (mousedown)=\"onmousedownPoint($event, p)\"\n ></div>\n }\n }\n </div>\n</div>\n\n<!-- TEMPLATE -->\n<nz-drawer\n [nzTitle]=\"drawTemplateTitle\"\n nzPlacement=\"right\"\n [nzWidth]=\"500\"\n [nzClosable]=\"false\"\n [nzVisible]=\"drawTemplateVisibel\"\n [nzFooter]=\"footerTplTemplate\"\n (nzOnClose)=\"drawTemplateVisibel = false\"\n>\n <ng-template #drawTemplateTitle> <nz-icon nzType=\"setting\"></nz-icon> Template </ng-template>\n <ng-container *nzDrawerContent>\n <extend-input [label]=\"'Code'\" [(_ngModel)]=\"template.Code\"></extend-input>\n <extend-input [label]=\"'Name'\" [(_ngModel)]=\"template.Name\"></extend-input>\n <extend-select\n [label]=\"'Type'\"\n [lstItem]=\"lstTemplateType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"template.DocType\"\n ></extend-select>\n <extend-textarea [label]=\"'Desscription'\" [(_ngModel)]=\"template.Description\"></extend-textarea>\n <extend-select\n [label]=\"'Print template'\"\n [lstItem]=\"lstTemplatePrint\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"template.TemplatePrint\"\n ></extend-select>\n <extend-checkbox [label]=\"'Active'\" [(_ngModel)]=\"template.IsActive\"></extend-checkbox>\n\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> Stage status</h3>\n\n @for (tag of template.lstStageStatus; track tag) {\n <nz-tag\n [nzMode]=\"checkRemoveableStageStatus(tag) ? 'closeable' : 'default'\"\n (nzOnClose)=\"handleCloseStageStatus(tag)\"\n >\n {{ sliceTagName(tag.Code + (tag.Name ? \" - \" + tag.Name : \"\")) }}\n </nz-tag>\n }\n\n <br *ngIf=\"template.lstStageStatus && template.lstStageStatus.length\" />\n\n @if (!inputStageStatusVisible) {\n <nz-tag class=\"editable-tag\" nzNoAnimation (click)=\"showInputStageStatus()\">\n <nz-icon nzType=\"plus\" />\n New Action type\n </nz-tag>\n } @else {\n <input\n #inputStageStatusElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Code\"\n [(ngModel)]=\"inputStageStatusCode\"\n (keydown.enter)=\"inputStageStatusNameElement.select()\"\n />\n <input\n #inputStageStatusNameElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Name\"\n [(ngModel)]=\"inputStageStatusName\"\n (blur)=\"handleInputStageStatusConfirm()\"\n (keydown.enter)=\"handleInputStageStatusConfirm()\"\n />\n }\n\n <box [height]=\"16\"></box>\n\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> Action type</h3>\n\n @for (tag of template.lstActionType; track tag) {\n <nz-tag\n [nzMode]=\"checkRemoveableActionType(tag) ? 'closeable' : 'default'\"\n (nzOnClose)=\"handleCloseActionType(tag)\"\n >\n {{ sliceTagName(tag.Code + (tag.Name ? \" - \" + tag.Name : \"\")) }}\n </nz-tag>\n }\n\n <br *ngIf=\"template.lstActionType && template.lstActionType.length\" />\n\n @if (!inputActionTypeVisible) {\n <nz-tag class=\"editable-tag\" nzNoAnimation (click)=\"showInputActionType()\">\n <nz-icon nzType=\"plus\" />\n New Action type\n </nz-tag>\n } @else {\n <input\n #inputActionTypeElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Code\"\n [(ngModel)]=\"inputActionTypeCode\"\n (keydown.enter)=\"inputActionTypeNameElement.select()\"\n />\n <input\n #inputActionTypeNameElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"Name\"\n [(ngModel)]=\"inputActionTypeName\"\n (blur)=\"handleInputActionTypeConfirm()\"\n (keydown.enter)=\"handleInputActionTypeConfirm()\"\n />\n }\n\n <box [height]=\"16\"></box>\n\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> Action status</h3>\n\n @for (tag of template.lstActionStatus; track tag) {\n <nz-tag [nzMode]=\"checkRemoveableActionStatus(tag) ? 'closeable' : 'default'\" (nzOnClose)=\"handleClose(tag)\">\n {{ sliceTagName(tag.Code + (tag.Name ? \" - \" + tag.Name : \"\")) }}\n </nz-tag>\n }\n\n <br *ngIf=\"template.lstActionStatus && template.lstActionStatus.length\" />\n\n @if (!inputVisible) {\n <nz-tag class=\"editable-tag\" nzNoAnimation (click)=\"showInput()\">\n <nz-icon nzType=\"plus\" />\n New Action status\n </nz-tag>\n } @else {\n <input\n #inputElement\n nz-input\n nzSize=\"small\"\n type=\"text\"\n style=\"width: 150px\"\n placeholder=\"+ New Action status\"\n [(ngModel)]=\"inputValue\"\n (blur)=\"handleInputConfirm()\"\n (keydown.enter)=\"handleInputConfirm()\"\n />\n }\n </ng-container>\n\n <ng-template #footerTplTemplate>\n <div nz-flex [nzGap]=\"6\">\n <button nz-button (click)=\"drawTemplateVisibel = false\">Close</button>\n <button nz-button nzDanger (click)=\"save()\">Save</button>\n </div>\n </ng-template>\n</nz-drawer>\n\n<!-- STAGE -->\n<nz-drawer\n [nzTitle]=\"drawerTitleStage\"\n [nzPlacement]=\"selectedStage?.editorOption?.drawerPosition ? selectedStage?.editorOption?.drawerPosition : 'right'\"\n [nzVisible]=\"!!selectedStage\"\n [nzWidth]=\"750\"\n [nzClosable]=\"false\"\n [nzFooter]=\"footerTplNode\"\n (nzOnClose)=\"selectedStage = undefined\"\n>\n <ng-template #drawerTitleStage>\n <div nz-row nzJustify=\"space-between\">\n @if (selectedStage) {\n @if (selectedStage.editorOption.drawerPosition == \"left\") {\n <button\n nz-button\n nzSize=\"small\"\n nz-tooltip=\"To the right\"\n (click)=\"selectedStage.editorOption.drawerPosition = 'right'\"\n >\n <nz-icon nzType=\"double-right\"></nz-icon>\n </button>\n STAGE\n } @else {\n STAGE\n <button\n nz-button\n nzSize=\"small\"\n nz-tooltip=\"To the left\"\n (click)=\"selectedStage.editorOption.drawerPosition = 'left'\"\n >\n <nz-icon nzType=\"double-left\"></nz-icon>\n </button>\n }\n }\n </div>\n </ng-template>\n <ng-container *nzDrawerContent>\n <ng-container *ngIf=\"selectedStage\">\n <nz-radio-group [(ngModel)]=\"selectedStage.StageType\">\n <label nz-radio nzValue=\"START\" [nzDisabled]=\"selectedStage.StageType != 'START'\">START</label>\n <label nz-radio nzValue=\"NODE\" [nzDisabled]=\"selectedStage.StageType != 'NODE'\">NODE</label>\n <label nz-radio nzValue=\"END\" [nzDisabled]=\"selectedStage.StageType != 'END'\">END</label>\n </nz-radio-group>\n\n <box [height]=\"16\"></box>\n\n <div nz-row [nzGutter]=\"32\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Code'\"\n [layOutType]=\"'vertical'\"\n [disabled]=\"['START', 'END'].indexOf(selectedStage!.StageType) >= 0\"\n [required]=\"true\"\n [(_ngModel)]=\"selectedStage.Code\"\n ></extend-input>\n\n <extend-textarea\n nz-col\n [nzSpan]=\"16\"\n [label]=\"'Name'\"\n [layOutType]=\"'vertical'\"\n [autoSize]=\"true\"\n [disabled]=\"['START', 'END'].indexOf(selectedStage!.StageType) >= 0\"\n [required]=\"true\"\n [(_ngModel)]=\"selectedStage.Name\"\n ></extend-textarea>\n </div>\n\n <div nz-row [nzGutter]=\"32\">\n <extend-input-number\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Sequence'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"selectedStage.SeqValue\"\n ></extend-input-number>\n\n <extend-select\n nz-col\n [nzSpan]=\"16\"\n [label]=\"'Org implement'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstOrg\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedStage.OrgImplCode\"\n ></extend-select>\n </div>\n\n @if ([\"START\", \"END\"].indexOf(selectedStage.StageType) < 0) {\n <extend-checkbox\n [label]=\"'Reverse'\"\n [labelSpan]=\"0\"\n [(_ngModel)]=\"selectedStage.editorOption.isReverse\"\n ></extend-checkbox>\n\n <extend-checkbox\n [label]=\"'Require user action'\"\n [labelSpan]=\"0\"\n [(_ngModel)]=\"selectedStage.IsRequireUser\"\n ></extend-checkbox>\n } @else {\n <extend-checkbox\n [label]=\"'Reverse'\"\n [labelSpan]=\"0\"\n [(_ngModel)]=\"selectedStage.editorOption.isReverseLabel\"\n ></extend-checkbox>\n }\n\n <box [height]=\"16\"></box>\n\n <div nz-row [nzGutter]=\"16\">\n <h3 nz-col><nz-icon nzType=\"send\" nzTheme=\"outline\" /> List Action</h3>\n <div nz-col>\n <button nz-button nzType=\"primary\" nzSize=\"small\" (click)=\"addAction()\">\n <nz-icon nzType=\"plus\"></nz-icon>\n </button>\n </div>\n </div>\n\n <nz-table\n nzSize=\"small\"\n [nzData]=\"selectedStage.lstAction || []\"\n [nzShowPagination]=\"false\"\n [nzNoResult]=\"' '\"\n >\n <thead>\n <tr [hidden]=\"true\">\n <th nzWidth=\"50px\"></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n @for (action of selectedStage.lstAction; track $index) {\n <tr>\n <td>\n <nz-icon\n nzType=\"delete\"\n nzTheme=\"outline\"\n class=\"color-warn cursor-pointer icon-size-16\"\n (click)=\"$event.stopPropagation(); deleteAction(action)\"\n ></nz-icon>\n </td>\n <td (click)=\"hoverAction = action\">\n <div nz-row [nzGutter]=\"16\" class=\"form-item-no-bottom\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action text'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"action.ActionText\"\n (_ngModelChange)=\"onchangeActionText(action)\"\n ></extend-input>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action type'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.ActionType\"\n ></extend-select>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.ActionStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.StageStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstStage\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.ToStage\"\n (_ngModelChange)=\"onchangeNextStage(action)\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"action.NextStageStatus\"\n ></extend-select>\n </div>\n </td>\n </tr>\n }\n </tbody>\n </nz-table>\n\n <box [height]=\"16\"></box>\n </ng-container>\n </ng-container>\n\n <ng-template #footerTplNode>\n <div\n nz-flex\n [nzGap]=\"6\"\n [nzJustify]=\"selectedStage && selectedStage.editorOption.drawerPosition == 'left' ? 'end' : 'start'\"\n >\n <button nz-button (click)=\"selectedStage = undefined\">Close</button>\n <button\n *ngIf=\"selectedStage && ['START', 'END'].indexOf(selectedStage.StageType) < 0\"\n nz-button\n nzDanger\n (click)=\"deleteNode()\"\n >\n Delete\n </button>\n </div>\n </ng-template>\n</nz-drawer>\n\n<!-- EDGE -->\n<nz-drawer\n [nzTitle]=\"drawerTitleAction\"\n nzTitle=\"ACTION\"\n [nzPlacement]=\"selectedAction?.editorOption?.drawerPosition ? selectedAction?.editorOption?.drawerPosition : 'right'\"\n [nzClosable]=\"false\"\n [nzWidth]=\"750\"\n [nzVisible]=\"!!selectedAction\"\n [nzFooter]=\"footerTplAction\"\n (nzOnClose)=\"selectedAction = undefined\"\n>\n <ng-template #drawerTitleAction>\n <div nz-row nzJustify=\"space-between\">\n @if (selectedAction) {\n @if (selectedAction.editorOption.drawerPosition == \"left\") {\n <button\n nz-button\n nzSize=\"small\"\n nz-tooltip=\"To the right\"\n (click)=\"selectedAction.editorOption.drawerPosition = 'right'\"\n >\n <nz-icon nzType=\"double-right\"></nz-icon>\n </button>\n ACTION\n } @else {\n ACTION\n <button\n nz-button\n nzSize=\"small\"\n nz-tooltip=\"To the left\"\n (click)=\"selectedAction.editorOption.drawerPosition = 'left'\"\n >\n <nz-icon nzType=\"double-left\"></nz-icon>\n </button>\n }\n }\n </div>\n </ng-template>\n <ng-container *nzDrawerContent>\n <ng-container *ngIf=\"selectedAction\">\n <strong>{{ selectedAction.FromStage }} -> {{ selectedAction.ToStage }}</strong>\n\n <box [height]=\"16\"></box>\n\n <div nz-row [nzGutter]=\"16\" class=\"form-item-no-bottom\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action text'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"selectedAction.ActionText\"\n (_ngModelChange)=\"onchangeActionText(selectedAction)\"\n ></extend-input>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action type'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.ActionType\"\n ></extend-select>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.ActionStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.StageStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstStage\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.ToStage\"\n (_ngModelChange)=\"onchangeNextStage(selectedAction)\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedAction.NextStageStatus\"\n ></extend-select>\n </div>\n\n <!-- <box [height]=\"16\"></box> -->\n <nz-divider></nz-divider>\n\n <extend-checkbox\n [label]=\"'Allow back'\"\n [labelSpan]=\"0\"\n [(_ngModel)]=\"selectedAction.allowBack\"\n (_ngModelChange)=\"onchangeAllowBack(selectedAction)\"\n ></extend-checkbox>\n\n <box [height]=\"16\"></box>\n\n @if (selectedAction.allowBack) {\n <strong>{{ selectedAction.ToStage }} -> {{ selectedAction.FromStage }}</strong>\n\n @if (selectedBackAction) {\n <div nz-row [nzGutter]=\"16\" class=\"form-item-no-bottom\">\n <extend-input\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action text'\"\n [layOutType]=\"'vertical'\"\n [(_ngModel)]=\"selectedBackAction.ActionText\"\n (_ngModelChange)=\"onchangeActionText(selectedBackAction)\"\n ></extend-input>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action type'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionType\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.ActionType\"\n ></extend-select>\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Action status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstActionStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.ActionStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.StageStatus\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"lstStage\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.ToStage\"\n (_ngModelChange)=\"onchangeNextStage(selectedBackAction)\"\n ></extend-select>\n\n <extend-select\n nz-col\n [nzSpan]=\"8\"\n [label]=\"'Next stage status'\"\n [layOutType]=\"'vertical'\"\n [lstItem]=\"template.lstStageStatus\"\n [valueField]=\"'Code'\"\n [displayFields]=\"['Code', 'Name']\"\n [(_ngModel)]=\"selectedBackAction.NextStageStatus\"\n ></extend-select>\n </div>\n }\n }\n </ng-container>\n </ng-container>\n <ng-template #footerTplAction>\n <div\n nz-flex\n [nzGap]=\"6\"\n [nzJustify]=\"selectedAction && selectedAction.editorOption.drawerPosition == 'left' ? 'end' : 'start'\"\n >\n <button nz-button (click)=\"selectedAction = undefined\">Close</button>\n <button nz-button nzDanger (click)=\"deleteAction(selectedAction!)\">Delete</button>\n </div>\n </ng-template>\n</nz-drawer>\n\n<!-- setting editor -->\n<nz-drawer\n [nzTitle]=\"drawSettingTitle\"\n nzPlacement=\"right\"\n [nzClosable]=\"false\"\n [nzVisible]=\"settingVisible\"\n (nzOnClose)=\"settingVisible = false\"\n>\n <ng-template #drawSettingTitle> <nz-icon nzType=\"setting\"></nz-icon> Editor </ng-template>\n <ng-container *nzDrawerContent>\n <div class=\"form-item-no-bottom\">\n <extend-checkbox [label]=\"'Show grid'\" [labelSpan]=\"0\" [(_ngModel)]=\"wfcSetting.ShowGrid\"></extend-checkbox>\n\n <box [height]=\"16\"></box>\n </div>\n </ng-container>\n</nz-drawer>\n", styles: ["@charset \"UTF-8\";.workflow-canvas{position:relative;width:100%;height:600px;background:#f0f2f5;cursor:default;overflow:hidden;outline:1px dashed rgba(0,0,0,.1)}.workflow-canvas .edges-layer{position:absolute;inset:0;width:100%;height:100%;z-index:1}.workflow-canvas .edges-layer path{stroke-width:2;fill:none}.canvas-content{transform-origin:0 0;width:10000px;height:10000px}.canvas-content{outline:1px dashed red}.canvas-content.panning{cursor:grab}.canvas-content.panning:active{cursor:grabbing}.workflow-canvas.panning{cursor:grab}.workflow-canvas.panning:active{cursor:grabbing}.workflow-canvas.connecting,.workflow-canvas.connecting .workflow-node{cursor:crosshair}.workflow-node{position:absolute;width:160px;cursor:grab;-webkit-user-select:none;user-select:none;z-index:2}.workflow-node:active{cursor:grabbing}.workflow-node .title{font-weight:600;margin-bottom:6px}.workflow-node.connecting-source,.workflow-node.selected,.workflow-node:hover:not(.workflow-node-start,.workflow-node-end){outline:2px dashed #1890ff}.workflow-node-start{background-color:unset;display:flex;justify-content:right}.workflow-node-end{background-color:unset;display:flex}.connector{position:absolute;top:39px;width:12px;height:12px;background:#1890ff;border-radius:50%;transform:translateY(-50%);cursor:crosshair;transition:box-shadow .15s ease-out,transform .15s ease-out}.connector:hover{box-shadow:0 0 0 3px #1890ff4d;transform:translateY(-50%) scale(1.15)}.connector-right{right:-8px;background:orange}.connector-right.reverse,.connector-left{left:-8px}.connector-left.reverse{left:unset;right:-8px}.connector-start{width:16px;height:16px;right:-3px;background:green;box-shadow:0 0 0 3px #1890ff4d}.connector-end{width:16px;height:16px;left:-6px;background:#000;box-shadow:0 0 0 3px #1890ff4d}.edge{cursor:pointer;stroke:#1890ff;stroke-linecap:round;stroke-linejoin:round;stroke-width:2;fill:none;transition:stroke .15s ease}.edge-hit{stroke:transparent;stroke-width:18px!important;fill:none;cursor:pointer}.edge-hit:hover+.edge{stroke:#ff4d4f;stroke-width:2}.workflow-canvas.dragging-point .edge-hit{pointer-events:none}.edge:hover+.edge-label{fill:#1890ff;font-weight:500}.edge-label{font-size:12px;fill:#555;pointer-events:none;-webkit-user-select:none;user-select:none}.blue{stroke:#1890ff!important}.red{stroke:#ff4d4f!important;box-shadow:0 0 0 3px #1890ff4d!important}.workflow-svg{background:transparent;overflow:visible}.waypoint{position:absolute;width:10px;height:10px;background:#ff4d4f;border-radius:50%;transform:translate(-50%,-50%) scale(1);cursor:move;z-index:1;transition:transform .12s ease-out,background-color .12s ease-out,box-shadow .12s ease-out}.waypoint:hover{background:#ff7875;transform:translate(-50%,-50%) scale(1.25);box-shadow:0 0 0 4px #ff787559}.waypoint.dragging{transition:none;transform:translate(-50%,-50%) scale(1.15);pointer-events:none}.workflow-canvas.dragging-point svg{cursor:grabbing}.selection-box{position:absolute;border:1px dashed #1890ff;background:#1890ff1a;pointer-events:none}.toolbar{position:absolute;top:8px;left:8px;display:flex;gap:4px;padding:6px;background:#fff;border-radius:6px;box-shadow:0 2px 8px #00000026;z-index:100}.toolbar .divider{width:1px;background:#e5e5e5;margin:0 2px}.zoom-toolbar{position:absolute;top:8px;left:8px;z-index:10;display:flex;align-items:center;gap:6px;background:#fff;padding:4px 6px;border-radius:6px;box-shadow:0 2px 6px #00000026}.zoom-toolbar span{min-width:40px;text-align:center;font-size:12px}nz-tag.selected{outline:2px dashed #1890ff}.grid-layer{position:absolute;inset:0;pointer-events:none;z-index:0;background-image:radial-gradient(rgba(0,0,0,.08) 1px,transparent 1px);background-size:20px 20px}.grid-layer{background-image:linear-gradient(to right,rgba(0,0,0,.06) 1px,transparent 1px),linear-gradient(to bottom,rgba(0,0,0,.06) 1px,transparent 1px);background-size:20px 20px}.editable-tag{background:#fff;border-style:dashed}\n"] }]
|
|
4269
4302
|
}], propDecorators: { lstOrg: [{
|
|
4270
4303
|
type: Input
|
|
4271
4304
|
}], lstTemplateType: [{
|
|
@@ -4948,5 +4981,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.7", ngImpor
|
|
|
4948
4981
|
* Generated bundle index. Do not edit.
|
|
4949
4982
|
*/
|
|
4950
4983
|
|
|
4951
|
-
export { AnimatedDigitComponent, AppGlobals, AppStorage, AuthGuard, AutoFocusDirective, BarGraphComponent, BaseComponent, BaseGuardChangeComponent, BaseOverlayComponent, Box, Breadcrumb, CheckModel, CommonService, DashcardComponent, DateInputParserDirective, DateTimeHelper, DoughnutGraphComponent, DownloadHelper, ENUM_ResponseType, ExtendCheckbox, ExtendDatePicker, ExtendDateRangePicker, ExtendInput, ExtendInputNumber, ExtendSelectComponent, ExtendTextArea, GlobalSpinnerComponent, GridFilter, HTTPService, Height, LimitWordsPipe, LineGraphComponent, LoadingService, NoPermission, NotiService, NullIfEmptyDirective, NumberOnlyDirective, OrderOption, PagingData, PagingModel, PdfViewerComponent, RouteMonitorService, TableHeader, ThemeService, TokenStorage, TranslateKey, UnsavedChangesGuard, UpperCaseFirsLetterEachWordDirective, UppercaseDirective, UppercaseFirstLetterDirective, VscService, Width, WorkflowEditorComponent, XLSXHelper, authInterceptor };
|
|
4984
|
+
export { AnimatedDigitComponent, AppGlobals, AppStorage, AuthGuard, AutoFocusDirective, BarGraphComponent, BaseComponent, BaseGuardChangeComponent, BaseOverlayComponent, Box, Breadcrumb, CheckModel, CommonService, DashcardComponent, DateInputParserDirective, DateTimeHelper, DoughnutGraphComponent, DownloadHelper, ENUM_ResponseType, ExtendCheckbox, ExtendDatePicker, ExtendDateRangePicker, ExtendInput, ExtendInputNumber, ExtendSelectComponent, ExtendTextArea, GlobalSpinnerComponent, GridFilter, HTTPService, Height, LimitWordsPipe, LineGraphComponent, LoadingService, NoPermission, NotiService, NullIfEmptyDirective, NumberOnlyDirective, OrderOption, PagingData, PagingModel, PdfViewerComponent, RouteMonitorService, TableHeader, ThemeService, TokenStorage, TranslateKey, UnsavedChangesGuard, UpperCaseFirsLetterEachWordDirective, UppercaseDirective, UppercaseFirstLetterDirective, VscService, Width, Workflow, WorkflowAction, WorkflowActionEditorOption, WorkflowEditorComponent, WorkflowStage, WorkflowStageEditorOption, XLSXHelper, authInterceptor };
|
|
4952
4985
|
//# sourceMappingURL=brggroup-share-lib.mjs.map
|