@libs-ui/services-diagram-draw 0.2.356-37 → 0.2.356-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.
@@ -10,7 +10,7 @@ class MoLibDiagramCalculatorBranchUtil {
10
10
  let Ly = startDraw;
11
11
  Ly += canvasConfigReadonly().ELEMENT_HEIGHT_CURVE; // chiều dài đến element đầu tiên
12
12
  Ly += getDistanceFromBranchToFirstBlock(branch.nodeOtherConfig); // chiều dài đến element đầu tiên
13
- if (!branch.elements || !branch.elements.length) {
13
+ if (!branch.elements?.length) {
14
14
  Ly += maxHeightBranch;
15
15
  Ly += 20; // thêm đoạn nối từ điểm kết thúc nhánh đến hết
16
16
  }
@@ -27,7 +27,7 @@ class MoLibDiagramCalculatorBranchUtil {
27
27
  const waitHeight = getHeightWaitConfig(branch.nodeOtherConfig);
28
28
  const topStartLine2 = endYToWait + waitHeight;
29
29
  delete branch.nodeOtherConfig.attributeSvgD;
30
- if (branch.elements && branch.elements.length) {
30
+ if (branch.elements?.length) {
31
31
  branch.nodeOtherConfig.attributeSvgD = `M ${coord1.mx} ${topStartLine2} L ${coord1.mx} ${coord1.ly}`;
32
32
  }
33
33
  branch.nodeOtherConfig.specific_y = endYToWait;
@@ -35,7 +35,7 @@ class MoLibDiagramCalculatorBranchUtil {
35
35
  }
36
36
  branch.specific_start_branch_y = top + lineFormElementToBranching + canvasConfigReadonly().ELEMENT_HEIGHT_CURVE;
37
37
  branch.specific_start_branch_x = left;
38
- if (!branch.elements || !branch.elements.length) {
38
+ if (!branch.elements?.length) {
39
39
  return;
40
40
  }
41
41
  const heightToElement = canvasConfigReadonly().ELEMENT_HEIGHT_CURVE + getDistanceFromBranchToFirstBlock(branch.nodeOtherConfig); // chiều dài đến element đầu tiên;
@@ -49,7 +49,7 @@ class MoLibDiagramCalculatorBranchUtil {
49
49
  const { coordQL2, isCheckAllElementConnectToExit } = this.drawAboveUnderLine(left, lineFormElementToBranching, top, lineBetweenBranch, branch, maxHeightBranch, 'left', config);
50
50
  branch.specific_start_branch_x = coordQL2.x;
51
51
  branch.specific_start_branch_y = coordQL2.y;
52
- if (!branch.elements || !branch.elements.length) {
52
+ if (!branch.elements?.length) {
53
53
  return;
54
54
  }
55
55
  this.drawElementInBranchLine(branch, coordQL2, config);
@@ -64,7 +64,7 @@ class MoLibDiagramCalculatorBranchUtil {
64
64
  const maxY = (coordQL1.y ?? 0) + 200;
65
65
  const configSvg = config.widthHeightSvgCanvas;
66
66
  configSvg.heightSvg = maxY > configSvg.heightSvg ? maxY : configSvg.heightSvg;
67
- if (!branch.elements || !branch.elements.length) {
67
+ if (!branch.elements?.length) {
68
68
  return;
69
69
  }
70
70
  this.drawElementInBranchLine(branch, coordQL2, config);
@@ -122,7 +122,7 @@ class MoLibDiagramCalculatorBranchUtil {
122
122
  };
123
123
  coordQL2.ly = (coordQL2.y ?? 0) + getDistanceFromBranchToFirstBlock(branch.nodeOtherConfig);
124
124
  coordQL2.lx = coordQL2.x;
125
- if (!branch.elements || !branch.elements.length) {
125
+ if (!branch.elements?.length) {
126
126
  coordQL2.ly = maxHeightBranch + (coordQL2.ly ?? 0); // tổng chiều cao của nhánh + điểm xuất phát
127
127
  }
128
128
  let QL2 = `Q ${coordQL2.x1},${coordQL2.y1} ${coordQL2.x},${coordQL2.y} L ${coordQL2.lx} ${coordQL2.ly}`;
@@ -132,7 +132,7 @@ class MoLibDiagramCalculatorBranchUtil {
132
132
  const topStartLine2 = endYToWait + waitHeight;
133
133
  delete branch.nodeOtherConfig.attributeSvgD;
134
134
  QL2 = `Q ${coordQL2.x1},${coordQL2.y1} ${coordQL2.x},${coordQL2.y} M ${coordQL2.x},${coordQL2.y} L ${coordQL2.x},${endYToWait}`;
135
- if (branch.elements && branch.elements.length) {
135
+ if (branch.elements?.length) {
136
136
  branch.nodeOtherConfig.attributeSvgD = `M ${coordQL2.x} ${topStartLine2} L ${coordQL2.x} ${coordQL2.ly}`;
137
137
  }
138
138
  branch.nodeOtherConfig.specific_y = endYToWait;
@@ -151,7 +151,7 @@ class MoLibDiagramCalculatorBranchUtil {
151
151
  return toExit;
152
152
  }
153
153
  elements.forEach((element) => {
154
- if (!element.branches || !element.branches.length) {
154
+ if (!element.branches?.length) {
155
155
  return;
156
156
  }
157
157
  let branchConnectToExit = 0;
@@ -192,18 +192,18 @@ class MoLibDiagramCalculatorBranchUtil {
192
192
  const buildFlatElement = (elements, flatElementsContainer) => {
193
193
  elements.forEach((element) => {
194
194
  flatElementsContainer.push(element);
195
- if (!element.branches || !element.branches.length) {
195
+ if (!element.branches?.length) {
196
196
  return;
197
197
  }
198
198
  flatElementHasBranch(element, flatElementsContainer);
199
199
  });
200
200
  };
201
201
  const flatElementHasBranch = (element, flatElementsContainer) => {
202
- if (!element.branches || !element.branches.length) {
202
+ if (!element.branches?.length) {
203
203
  return;
204
204
  }
205
205
  element.branches.forEach((branch) => {
206
- if (!branch.elements || !branch.elements.length) {
206
+ if (!branch.elements?.length) {
207
207
  return;
208
208
  }
209
209
  buildFlatElement(branch.elements, flatElementsContainer);
@@ -244,7 +244,7 @@ const applyElementStyle = (el, element) => {
244
244
 
245
245
  class MoLibDiagramCalculatorCoordinatesUtil {
246
246
  static setXYElements(elements, config, positionX) {
247
- if (!elements || !elements.length) {
247
+ if (!elements?.length) {
248
248
  return;
249
249
  }
250
250
  elements.forEach((currentElement, index) => {
@@ -260,7 +260,7 @@ class MoLibDiagramCalculatorCoordinatesUtil {
260
260
  const top = currentElement.specific_y ?? 0;
261
261
  const left = (currentElement.specific_x ?? 0) + (currentElement.specific_width ?? 0) / 2;
262
262
  let lineBetweenElements = (currentElement.specific_height ?? 0) + checkElementGetHeight(currentElement.nodeOtherConfig);
263
- if (currentElement.branches && currentElement.branches.length) {
263
+ if (currentElement.branches?.length) {
264
264
  lineBetweenElements = (currentElement.specific_height ?? 0) + canvasConfigReadonly().ELEMENT_MARGIN_DEFAULT_BRANCH;
265
265
  }
266
266
  const maxY = (currentElement.specific_y ?? 0) + (currentElement.specific_height ?? 0) + 200;
@@ -269,7 +269,7 @@ class MoLibDiagramCalculatorCoordinatesUtil {
269
269
  configSvg.heightSvg = maxY > configSvg.heightSvg ? maxY : configSvg.heightSvg;
270
270
  configSvg.widthSvg = maxXLeft > configSvg.widthSvg ? maxXLeft : configSvg.widthSvg;
271
271
  checkMaxLeft(config, currentElement.specific_x, currentElement.branches?.[0].positionMaxLeft);
272
- if (!currentElement.branches || !currentElement.branches.length) {
272
+ if (!currentElement.branches?.length) {
273
273
  // các element không có nhánh mới vẽ đường thẳng
274
274
  const drawFormToHeightExit = (currentElement.subCodeOfElement || currentElement.code) === canvasConfigReadonly().TYPE_ELEMENT_EXIT ? (currentElement.specific_height ?? 0) / 2 : lineBetweenElements;
275
275
  currentElement.attributeSvgD = `M ${left} ${top} l 0 ${drawFormToHeightExit}`;
@@ -315,12 +315,12 @@ class MoLibDiagramCalculatorCoordinatesUtil {
315
315
  MoLibDiagramCalculatorBranchUtil.drawStraightLine(left, lineFormElementToBranching, top, brachMiddle, maxHeightBranch.height, config);
316
316
  }
317
317
  let hasNextSameParentElementNext = false;
318
- const aboveHalfReverse = aboveHalf.reverse();
318
+ const aboveHalfReverse = aboveHalf.slice().reverse();
319
319
  aboveHalfReverse.forEach((branch, indexBranch) => {
320
320
  if (!hasNextSameParentElementNext) {
321
321
  const flatElementOnBranch = [];
322
322
  buildFlatElement(branch.elements, flatElementOnBranch);
323
- hasNextSameParentElementNext = !flatElementOnBranch || !flatElementOnBranch.length ? true : flatElementOnBranch.find((item) => item.next_id === currentElement.next_id) ? true : false;
323
+ hasNextSameParentElementNext = !flatElementOnBranch?.length || !!flatElementOnBranch.find((item) => item.next_id === currentElement.next_id);
324
324
  }
325
325
  branch.onTheSide = 'above';
326
326
  const maxWidthBranch = { width: 0, aboveWidth: 0, underWidth: 0 }; // tính chiều ngang để cách nhánh trên or dưới
@@ -345,7 +345,7 @@ class MoLibDiagramCalculatorCoordinatesUtil {
345
345
  if (!hasNextSameParentElementNext) {
346
346
  const flatElementOnBranch = [];
347
347
  buildFlatElement(branch.elements, flatElementOnBranch);
348
- hasNextSameParentElementNext = !flatElementOnBranch || !flatElementOnBranch.length ? true : flatElementOnBranch.find((item) => item.next_id === currentElement.next_id) ? true : false;
348
+ hasNextSameParentElementNext = !flatElementOnBranch?.length || !!flatElementOnBranch.find((item) => item.next_id === currentElement.next_id);
349
349
  }
350
350
  branch.onTheSide = 'under';
351
351
  const maxWidthBranch = { width: 0, aboveWidth: 0, underWidth: 0 }; // tính chiều cao để cách nhánh trên or dưới
@@ -394,7 +394,7 @@ class MoLibDiagramCalculatorCoordinatesUtil {
394
394
  branch.nodeOtherConfig.translateY = branch.nodeOtherConfig.specific_y;
395
395
  }
396
396
  // Recursively set positions cho elements trong branch
397
- if (branch.elements && branch.elements.length > 0) {
397
+ if (branch.elements?.length > 0) {
398
398
  this.setTranslatePositions(branch.elements);
399
399
  }
400
400
  });
@@ -402,11 +402,11 @@ class MoLibDiagramCalculatorCoordinatesUtil {
402
402
  });
403
403
  }
404
404
  static calculatorMaxBranchHeight(element, maxHeightBranch) {
405
- if (!element.branches || !element.branches.length) {
405
+ if (!element.branches?.length) {
406
406
  return;
407
407
  }
408
408
  element.branches.forEach((branch) => {
409
- if (!branch.elements || !branch.elements.length) {
409
+ if (!branch.elements?.length) {
410
410
  const lineBranchNoHasElement = canvasConfigReadonly().ELEMENT_WIDTH_DEFAULT_BRANCH_WHEN_NOT_ELEMENT;
411
411
  maxHeightBranch.height = lineBranchNoHasElement > maxHeightBranch.height ? lineBranchNoHasElement : maxHeightBranch.height;
412
412
  return;
@@ -420,9 +420,9 @@ class MoLibDiagramCalculatorCoordinatesUtil {
420
420
  }
421
421
  static plusHeightElementInBranch(elements, total) {
422
422
  elements.forEach((element) => {
423
- const margin = !element.branches || !element.branches.length ? checkElementGetHeight(element.nodeOtherConfig) : canvasConfigReadonly().ELEMENT_MARGIN_DEFAULT_BRANCH;
423
+ const margin = !element.branches?.length ? checkElementGetHeight(element.nodeOtherConfig) : canvasConfigReadonly().ELEMENT_MARGIN_DEFAULT_BRANCH;
424
424
  total.height += (element.specific_height ?? 0) + margin;
425
- if (!element.branches || !element.branches.length) {
425
+ if (!element.branches?.length) {
426
426
  return;
427
427
  }
428
428
  total.height += 64; // từ chiều đường thẳng ngang xuống đến nhánh đầu tiên
@@ -432,7 +432,7 @@ class MoLibDiagramCalculatorCoordinatesUtil {
432
432
  element.branches.forEach((branch) => {
433
433
  const heightInBranch = { height: 0 };
434
434
  heightInBranch.height += canvasConfigReadonly().ELEMENT_MARGIN_DEFAULT_BRANCH_TO_ELEMENT_FIRST + 20; // đường cong kết thúc nhánh + 10px đường cong
435
- if (!branch.elements || !branch.elements.length) {
435
+ if (!branch.elements?.length) {
436
436
  heightInBranch.height += canvasConfigReadonly().ELEMENT_WIDTH_DEFAULT_BRANCH_WHEN_NOT_ELEMENT;
437
437
  if (theMostElementsInBranch.height < heightInBranch.height) {
438
438
  theMostElementsInBranch.height = heightInBranch.height;
@@ -448,7 +448,7 @@ class MoLibDiagramCalculatorCoordinatesUtil {
448
448
  });
449
449
  }
450
450
  static calculatorWidthBranch(elements, maxWidth, log) {
451
- if (!elements || !elements.length) {
451
+ if (!elements?.length) {
452
452
  const width = canvasConfigReadonly().DEFAULT_BRANCH_WHEN_NO_ELEMENT;
453
453
  maxWidth.width = width;
454
454
  maxWidth.aboveWidth = width / 2;
@@ -457,7 +457,7 @@ class MoLibDiagramCalculatorCoordinatesUtil {
457
457
  }
458
458
  const maxWidthInElements = { width: 0, aboveWidth: 0, underWidth: 0 };
459
459
  elements.forEach((element) => {
460
- if (!element.branches || !element.branches.length) {
460
+ if (!element.branches?.length) {
461
461
  // tính chiều cao của từng element 1, vì chiều cao của từng thằng có thể khác nhau
462
462
  if ((element.specific_width ?? 0) < maxWidthInElements.width) {
463
463
  return;
@@ -608,7 +608,7 @@ class MoLibDiagramHorizontalCalculatorBranchUtil {
608
608
  let Lx = startDraw;
609
609
  Lx += canvasConfigReadonly().ELEMENT_HEIGHT_CURVE;
610
610
  Lx += this.getHorizontalDistanceToFirstBlock(branch);
611
- if (!branch.elements || !branch.elements.length) {
611
+ if (!branch.elements?.length) {
612
612
  Lx += maxWidthBranch + 20;
613
613
  }
614
614
  const coord1 = { mx: left, my: top, lx: Lx, ly: top };
@@ -620,7 +620,7 @@ class MoLibDiagramHorizontalCalculatorBranchUtil {
620
620
  const waitWidth = getHeightWaitConfig(branch.nodeOtherConfig);
621
621
  const leftLine2 = endXToWait + waitWidth;
622
622
  delete branch.nodeOtherConfig.attributeSvgD;
623
- if (branch.elements && branch.elements.length) {
623
+ if (branch.elements?.length) {
624
624
  branch.nodeOtherConfig.attributeSvgD = `M ${leftLine2} ${coord1.my} L ${coord1.lx} ${coord1.my}`;
625
625
  }
626
626
  branch.nodeOtherConfig.specific_x = endXToWait;
@@ -635,7 +635,7 @@ class MoLibDiagramHorizontalCalculatorBranchUtil {
635
635
  }
636
636
  branch.specific_start_branch_x = left + lineFormElementToBranching + canvasConfigReadonly().ELEMENT_HEIGHT_CURVE;
637
637
  branch.specific_start_branch_y = top;
638
- if (!branch.elements || !branch.elements.length)
638
+ if (!branch.elements?.length)
639
639
  return;
640
640
  const widthToElement = canvasConfigReadonly().ELEMENT_HEIGHT_CURVE + this.getHorizontalDistanceToFirstBlock(branch);
641
641
  branch.elements.forEach((el) => {
@@ -650,7 +650,7 @@ class MoLibDiagramHorizontalCalculatorBranchUtil {
650
650
  const { coordQL2, isCheckAllElementConnectToExit } = this.drawAboveUnderLine(top, lineFormElementToBranching, left, lineBetweenBranch, branch, maxWidthBranch, 'above', config);
651
651
  branch.specific_start_branch_x = coordQL2.x;
652
652
  branch.specific_start_branch_y = coordQL2.y;
653
- if (!branch.elements || !branch.elements.length)
653
+ if (!branch.elements?.length)
654
654
  return;
655
655
  this.drawElementInBranchLine(branch, coordQL2, config);
656
656
  if (isCheckAllElementConnectToExit)
@@ -666,7 +666,7 @@ class MoLibDiagramHorizontalCalculatorBranchUtil {
666
666
  const maxY = (coordQL1.y ?? 0) + 200;
667
667
  const configSvg = config.widthHeightSvgCanvas;
668
668
  configSvg.heightSvg = maxY > configSvg.heightSvg ? maxY : configSvg.heightSvg;
669
- if (!branch.elements || !branch.elements.length)
669
+ if (!branch.elements?.length)
670
670
  return;
671
671
  this.drawElementInBranchLine(branch, coordQL2, config);
672
672
  if (isCheckAllElementConnectToExit)
@@ -733,7 +733,7 @@ class MoLibDiagramHorizontalCalculatorBranchUtil {
733
733
  };
734
734
  // Đoạn L sau QL2: đi ngang (phải) đến vị trí element đầu tiên trong nhánh
735
735
  const distToFirst = this.getHorizontalDistanceToFirstBlock(branch);
736
- if (!branch.elements || !branch.elements.length) {
736
+ if (!branch.elements?.length) {
737
737
  coordQL2.lx = (coordQL2.x ?? 0) + distToFirst + maxWidthBranch;
738
738
  }
739
739
  else {
@@ -749,7 +749,7 @@ class MoLibDiagramHorizontalCalculatorBranchUtil {
749
749
  const leftLine2 = endXToWait + waitWidth;
750
750
  delete branch.nodeOtherConfig.attributeSvgD;
751
751
  QL2 = `Q ${coordQL2.x1},${coordQL2.y1} ${coordQL2.x},${coordQL2.y} M ${coordQL2.x},${coordQL2.y} L ${endXToWait},${coordQL2.y}`;
752
- if (branch.elements && branch.elements.length) {
752
+ if (branch.elements?.length) {
753
753
  branch.nodeOtherConfig.attributeSvgD = `M ${leftLine2} ${coordQL2.y} L ${coordQL2.lx} ${coordQL2.ly}`;
754
754
  }
755
755
  branch.nodeOtherConfig.specific_x = endXToWait;
@@ -776,7 +776,7 @@ class MoLibDiagramHorizontalCalculatorBranchUtil {
776
776
  return true;
777
777
  }
778
778
  elements.forEach((element) => {
779
- if (!element.branches || !element.branches.length)
779
+ if (!element.branches?.length)
780
780
  return;
781
781
  let branchConnectToExit = 0;
782
782
  element.branches.forEach((branch) => {
@@ -827,7 +827,7 @@ class MoLibDiagramHorizontalCalculatorBranchUtil {
827
827
  */
828
828
  class MoLibDiagramHorizontalCalculatorCoordinatesUtil {
829
829
  static setXYElements(elements, config, positionY) {
830
- if (!elements || !elements.length) {
830
+ if (!elements?.length) {
831
831
  return;
832
832
  }
833
833
  elements.forEach((currentElement, index) => {
@@ -843,9 +843,8 @@ class MoLibDiagramHorizontalCalculatorCoordinatesUtil {
843
843
  }
844
844
  checkMaxTop(config, currentElement.specific_y, currentElement.branches?.[0]?.positionMaxTop);
845
845
  const top = currentElement.specific_y ?? 0;
846
- const left = (currentElement.specific_x ?? 0) + (currentElement.specific_width ?? 0) / 2; // điểm giữa theo X (điểm vẽ SVG)
847
846
  let lineBetweenElements = (currentElement.specific_width ?? 0) + this.checkElementGetMargin(currentElement.nodeOtherConfig);
848
- if (currentElement.branches && currentElement.branches.length) {
847
+ if (currentElement.branches?.length) {
849
848
  lineBetweenElements = (currentElement.specific_width ?? 0) + canvasConfigReadonly().ELEMENT_MARGIN_DEFAULT_BRANCH;
850
849
  }
851
850
  const maxY = (currentElement.specific_y ?? 0) + (currentElement.specific_height ?? 0) + 200;
@@ -853,7 +852,7 @@ class MoLibDiagramHorizontalCalculatorCoordinatesUtil {
853
852
  const configSvg = config.widthHeightSvgCanvas;
854
853
  configSvg.heightSvg = maxY > configSvg.heightSvg ? maxY : configSvg.heightSvg;
855
854
  configSvg.widthSvg = maxXRight > configSvg.widthSvg ? maxXRight : configSvg.widthSvg;
856
- if (!currentElement.branches || !currentElement.branches.length) {
855
+ if (!currentElement.branches?.length) {
857
856
  // Element không có nhánh: vẽ đường thẳng ngang
858
857
  const drawFormToWidthExit = (currentElement.subCodeOfElement || currentElement.code) === canvasConfigReadonly().TYPE_ELEMENT_EXIT ? (currentElement.specific_width ?? 0) / 2 : lineBetweenElements;
859
858
  currentElement.attributeSvgD = `M ${currentElement.specific_x ?? 0} ${top + (currentElement.specific_height ?? 0) / 2} l ${drawFormToWidthExit} 0`;
@@ -909,12 +908,12 @@ class MoLibDiagramHorizontalCalculatorCoordinatesUtil {
909
908
  MoLibDiagramHorizontalCalculatorBranchUtil.drawStraightLine(topMid, lineFormElementToBranching, currentElement.specific_x ?? 0, brachMiddle, maxWidthBranch.width, config);
910
909
  }
911
910
  let hasNextSameParentElementNext = false;
912
- const aboveHalfReverse = aboveHalf.reverse();
913
- aboveHalfReverse.forEach((branch, indexBranch) => {
911
+ aboveHalf.reverse();
912
+ aboveHalf.forEach((branch, indexBranch) => {
914
913
  if (!hasNextSameParentElementNext) {
915
914
  const flatElementOnBranch = [];
916
915
  buildFlatElement(branch.elements, flatElementOnBranch);
917
- hasNextSameParentElementNext = !flatElementOnBranch || !flatElementOnBranch.length ? true : flatElementOnBranch.find((item) => item.next_id === currentElement.next_id) ? true : false;
916
+ hasNextSameParentElementNext = !flatElementOnBranch?.length ? true : !!flatElementOnBranch.find((item) => item.next_id === currentElement.next_id);
918
917
  }
919
918
  branch.onTheSide = 'above';
920
919
  const maxWidthB = { width: 0, aboveWidth: 0, underWidth: 0 };
@@ -924,7 +923,7 @@ class MoLibDiagramHorizontalCalculatorCoordinatesUtil {
924
923
  above: maxWidthB.aboveWidth,
925
924
  under: maxWidthB.underWidth,
926
925
  };
927
- const branchPre = aboveHalfReverse[indexBranch - 1];
926
+ const branchPre = aboveHalf[indexBranch - 1];
928
927
  let lineBetweenBranch = maxWidthB.underWidth + canvasConfigReadonly().ELEMENT_MARGIN_BETWEEN_BRANCH_DEFAULT / 2;
929
928
  if (branchPre) {
930
929
  lineBetweenBranch += (branchPre.widthBranch?.width ?? 0) + canvasConfigReadonly().ELEMENT_MARGIN_BETWEEN_BRANCH_DEFAULT;
@@ -938,7 +937,7 @@ class MoLibDiagramHorizontalCalculatorCoordinatesUtil {
938
937
  if (!hasNextSameParentElementNext) {
939
938
  const flatElementOnBranch = [];
940
939
  buildFlatElement(branch.elements, flatElementOnBranch);
941
- hasNextSameParentElementNext = !flatElementOnBranch || !flatElementOnBranch.length ? true : flatElementOnBranch.find((item) => item.next_id === currentElement.next_id) ? true : false;
940
+ hasNextSameParentElementNext = !flatElementOnBranch?.length ? true : !!flatElementOnBranch.find((item) => item.next_id === currentElement.next_id);
942
941
  }
943
942
  branch.onTheSide = 'under';
944
943
  const maxWidthB = { width: 0, aboveWidth: 0, underWidth: 0 };
@@ -989,11 +988,11 @@ class MoLibDiagramHorizontalCalculatorCoordinatesUtil {
989
988
  }
990
989
  /** Tính chiều rộng tối đa của nhánh (trong horizontal = chiều cao thực của nhánh không có element) */
991
990
  static calculatorMaxBranchWidth(element, maxWidthBranch) {
992
- if (!element.branches || !element.branches.length) {
991
+ if (!element.branches?.length) {
993
992
  return;
994
993
  }
995
994
  element.branches.forEach((branch) => {
996
- if (!branch.elements || !branch.elements.length) {
995
+ if (!branch.elements?.length) {
997
996
  const lineBranchNoHasElement = canvasConfigReadonly().ELEMENT_WIDTH_DEFAULT_BRANCH_WHEN_NOT_ELEMENT;
998
997
  maxWidthBranch.width = lineBranchNoHasElement > maxWidthBranch.width ? lineBranchNoHasElement : maxWidthBranch.width;
999
998
  return;
@@ -1006,9 +1005,9 @@ class MoLibDiagramHorizontalCalculatorCoordinatesUtil {
1006
1005
  /** Tính tổng chiều rộng các elements trong nhánh (dọc theo trục X) */
1007
1006
  static plusWidthElementInBranch(elements, total) {
1008
1007
  elements.forEach((element) => {
1009
- const margin = !element.branches || !element.branches.length ? this.checkElementGetMargin(element.nodeOtherConfig) : canvasConfigReadonly().ELEMENT_MARGIN_DEFAULT_BRANCH;
1008
+ const margin = !element.branches?.length ? this.checkElementGetMargin(element.nodeOtherConfig) : canvasConfigReadonly().ELEMENT_MARGIN_DEFAULT_BRANCH;
1010
1009
  total.height += (element.specific_width ?? 0) + margin;
1011
- if (!element.branches || !element.branches.length) {
1010
+ if (!element.branches?.length) {
1012
1011
  return;
1013
1012
  }
1014
1013
  total.height += 64;
@@ -1016,7 +1015,7 @@ class MoLibDiagramHorizontalCalculatorCoordinatesUtil {
1016
1015
  element.branches.forEach((branch) => {
1017
1016
  const widthInBranch = { height: 0 };
1018
1017
  widthInBranch.height += canvasConfigReadonly().ELEMENT_MARGIN_DEFAULT_BRANCH_TO_ELEMENT_FIRST + 20;
1019
- if (!branch.elements || !branch.elements.length) {
1018
+ if (!branch.elements?.length) {
1020
1019
  widthInBranch.height += canvasConfigReadonly().ELEMENT_WIDTH_DEFAULT_BRANCH_WHEN_NOT_ELEMENT;
1021
1020
  if (theMostElementsInBranch.height < widthInBranch.height) {
1022
1021
  theMostElementsInBranch.height = widthInBranch.height;
@@ -1036,7 +1035,7 @@ class MoLibDiagramHorizontalCalculatorCoordinatesUtil {
1036
1035
  * Trong horizontal context: mỗi nhánh trải dài theo Y (lên/xuống).
1037
1036
  */
1038
1037
  static calculatorHeightBranch(elements, maxWidth) {
1039
- if (!elements || !elements.length) {
1038
+ if (!elements?.length) {
1040
1039
  const w = canvasConfigReadonly().DEFAULT_BRANCH_WHEN_NO_ELEMENT;
1041
1040
  maxWidth.width = w;
1042
1041
  maxWidth.aboveWidth = w / 2;
@@ -1045,7 +1044,7 @@ class MoLibDiagramHorizontalCalculatorCoordinatesUtil {
1045
1044
  }
1046
1045
  const maxWidthInElements = { width: 0, aboveWidth: 0, underWidth: 0 };
1047
1046
  elements.forEach((element) => {
1048
- if (!element.branches || !element.branches.length) {
1047
+ if (!element.branches?.length) {
1049
1048
  // element không nhánh: dùng specific_height làm Y span
1050
1049
  if ((element.specific_height ?? 0) < maxWidthInElements.width) {
1051
1050
  return;
@@ -1124,6 +1123,138 @@ class MoLibDiagramHorizontalCalculatorCoordinatesUtil {
1124
1123
  }
1125
1124
  }
1126
1125
 
1126
+ const DEFAULT_NAVIGATION_LINE_STYLE = {
1127
+ curve: 10,
1128
+ distancePoint: 20,
1129
+ stroke: 'var(--libs-ui-color-light-1, #4e8cf7)',
1130
+ strokeDasharray: '5',
1131
+ strokeWidth: '1',
1132
+ };
1133
+ const DEFAULT_NAVIGATION_ARROW_STYLE = {
1134
+ width: 4,
1135
+ height: 8,
1136
+ fill: 'var(--libs-ui-color-light-1, #4e8cf7)',
1137
+ };
1138
+ const DEFAULT_NAVIGATION_ENDPOINT_GAP = 8;
1139
+
1140
+ class LibsUiDiagramDrawNavigationUtil {
1141
+ /** Rule chọn mode mặc định (copy từ workflows/canvas.component.ts:471). */
1142
+ static defaultModeResolver(start, end) {
1143
+ return start.x < end.x && start.y > end.y ? 'quart-in' : 's-line';
1144
+ }
1145
+ /**
1146
+ * Build dữ liệu navigation line (next_other_id) từ flat elements để render qua draw-line directive.
1147
+ * @param flatElements Danh sách phẳng tất cả elements (sau khi configXYElements đã chạy).
1148
+ * @param orientation Chiều layout của diagram.
1149
+ * @param styleConfig Tuỳ chỉnh style line/arrow + override resolver mode/gap.
1150
+ */
1151
+ static buildNavigationData(flatElements, orientation, styleConfig) {
1152
+ const result = [];
1153
+ flatElements.forEach((item) => {
1154
+ if (item.branches?.length) {
1155
+ item.branches.forEach((branch, index) => {
1156
+ if (!branch.next_other_id?.length || !branch.nodeOtherConfig) {
1157
+ return;
1158
+ }
1159
+ const nodeOtherConfig = branch.nodeOtherConfig;
1160
+ const nextIds = branch.next_other_id;
1161
+ nextIds.forEach((nextId, idx) => {
1162
+ const target = flatElements.find((el) => el.id === nextId);
1163
+ if (!target) {
1164
+ return;
1165
+ }
1166
+ const lineId = nextIds.length > 1 ? `${item.id}_branch_${index}_${idx}` : `${item.id}_branch_${index}`;
1167
+ const lineData = this.buildOneLine(lineId, nodeOtherConfig, target, orientation, styleConfig);
1168
+ if (lineData) {
1169
+ result.push(lineData);
1170
+ }
1171
+ });
1172
+ });
1173
+ return;
1174
+ }
1175
+ if (!item.next_other_id?.length || !item.nodeOtherConfig) {
1176
+ return;
1177
+ }
1178
+ const nodeOtherConfig = item.nodeOtherConfig;
1179
+ const nextIds = item.next_other_id;
1180
+ nextIds.forEach((nextId, idx) => {
1181
+ const target = flatElements.find((el) => el.id === nextId);
1182
+ if (!target) {
1183
+ return;
1184
+ }
1185
+ const lineId = nextIds.length > 1 ? `${item.id ?? ''}_${idx}` : (item.id ?? '');
1186
+ const lineData = this.buildOneLine(lineId, nodeOtherConfig, target, orientation, styleConfig);
1187
+ if (lineData) {
1188
+ result.push(lineData);
1189
+ }
1190
+ });
1191
+ });
1192
+ return result;
1193
+ }
1194
+ static buildOneLine(id, source, target, orientation, styleConfig) {
1195
+ const gap = styleConfig?.endpointGap ?? DEFAULT_NAVIGATION_ENDPOINT_GAP;
1196
+ const points = orientation === 'horizontal' ? this.calcPointsHorizontal(source, target, gap) : this.calcPointsVertical(source, target, gap);
1197
+ if (!points) {
1198
+ return undefined;
1199
+ }
1200
+ const resolver = styleConfig?.modeResolver ?? this.defaultModeResolver;
1201
+ const mode = resolver(points.start, points.end);
1202
+ return {
1203
+ id,
1204
+ points,
1205
+ mode,
1206
+ lineStyle: { ...DEFAULT_NAVIGATION_LINE_STYLE, ...styleConfig?.lineStyle },
1207
+ arrowStyle: { ...DEFAULT_NAVIGATION_ARROW_STYLE, ...styleConfig?.arrowStyle },
1208
+ };
1209
+ }
1210
+ /** VERTICAL: line navigation đi NGANG — kẹp cạnh phải/trái source → cạnh trái/phải target. */
1211
+ static calcPointsVertical(source, target, gap) {
1212
+ const sx = source.specific_x ?? 0;
1213
+ const sy = source.specific_y ?? 0;
1214
+ const sw = source.specific_width ?? 0;
1215
+ const sh = source.specific_height ?? 0;
1216
+ const tx = target.specific_x ?? 0;
1217
+ const ty = target.specific_y ?? 0;
1218
+ const tw = target.specific_width ?? 0;
1219
+ const th = target.specific_height ?? 0;
1220
+ const sMidY = sy + sh / 2;
1221
+ const tMidY = ty + th / 2;
1222
+ // Default: line đi sang PHẢI từ source → cạnh TRÁI target
1223
+ let start = { x: sx + sw, y: sMidY };
1224
+ let end = { x: tx - gap, y: tMidY };
1225
+ // Source nằm BÊN PHẢI target → line đi sang TRÁI: cạnh TRÁI source → cạnh PHẢI target
1226
+ if (sx > tx + tw) {
1227
+ start = { x: sx, y: sMidY };
1228
+ end = { x: tx + tw + gap, y: tMidY };
1229
+ return { start, end };
1230
+ }
1231
+ // Source nằm PHÍA TRÊN target (cùng cột hoặc gần) → đi XUỐNG vào cạnh TRÊN target
1232
+ if (sy < ty && Math.abs(sx + sw / 2 - (tx + tw / 2)) < Math.max(sw, tw)) {
1233
+ start = { x: sx + sw / 2, y: sy + sh };
1234
+ end = { x: tx + tw / 2, y: ty - gap };
1235
+ }
1236
+ return { start, end };
1237
+ }
1238
+ /** HORIZONTAL: line navigation đi DỌC — kẹp cạnh dưới/trên source → cạnh trên/dưới target. */
1239
+ static calcPointsHorizontal(source, target, gap) {
1240
+ const sx = source.specific_x ?? 0;
1241
+ const sy = source.specific_y ?? 0;
1242
+ const sw = source.specific_width ?? 0;
1243
+ const tx = target.specific_x ?? 0;
1244
+ const ty = target.specific_y ?? 0;
1245
+ const tw = target.specific_width ?? 0;
1246
+ const th = target.specific_height ?? 0;
1247
+ // Default: line đi XUỐNG từ source → cạnh TRÊN target
1248
+ const start = { x: sx + sw, y: sy };
1249
+ const end = { x: tx - gap, y: ty + th / 2 };
1250
+ if (sy < ty) {
1251
+ end.x = tx + tw / 2;
1252
+ end.y = ty - gap;
1253
+ }
1254
+ return { start, end };
1255
+ }
1256
+ }
1257
+
1127
1258
  const canvasConfig = signal({
1128
1259
  ELEMENT_WIDTH_DEFAULT_BRANCH_WHEN_NOT_ELEMENT: 60,
1129
1260
  ELEMENT_MARGIN_DEFAULT: 60,
@@ -1236,7 +1367,7 @@ class LibsUiDiagramDrawService {
1236
1367
  if (currentElement.nodeOtherConfig?.attributeSvgD) {
1237
1368
  this.attributeSvgD.update((prev) => `${prev ?? ''} ${currentElement.nodeOtherConfig?.attributeSvgD}`);
1238
1369
  }
1239
- if (!currentElement.branches || !currentElement.branches.length) {
1370
+ if (!currentElement.branches?.length) {
1240
1371
  return;
1241
1372
  }
1242
1373
  currentElement.branches.forEach((branch) => {
@@ -1263,7 +1394,7 @@ class LibsUiDiagramDrawService {
1263
1394
  return;
1264
1395
  }
1265
1396
  this.clearNodes();
1266
- this.renderElementsRecursively(elements, true, undefined);
1397
+ this.renderElementsRecursively(elements, true);
1267
1398
  this.renderBranchLabels(elements);
1268
1399
  }
1269
1400
  extractVirtualElements(elements) {
@@ -1410,7 +1541,7 @@ class LibsUiDiagramDrawService {
1410
1541
  this.createNode(element, branch, shouldShowArrow, false);
1411
1542
  }
1412
1543
  // Render nodeOtherConfig nếu có (nodes phụ) - KHÔNG có arrow
1413
- if (element.nodeOtherConfig && element.nodeOtherConfig.translateX !== undefined && element.nodeOtherConfig.translateY !== undefined) {
1544
+ if (element.nodeOtherConfig?.translateX !== undefined && element.nodeOtherConfig.translateY !== undefined) {
1414
1545
  this.createNode(element.nodeOtherConfig, branch, false, true);
1415
1546
  }
1416
1547
  // Render branches nếu có
@@ -1419,7 +1550,7 @@ class LibsUiDiagramDrawService {
1419
1550
  if (branch.elements && branch.elements.length > 0) {
1420
1551
  this.renderElementsRecursively(branch.elements, false, branch);
1421
1552
  }
1422
- if (branch.nodeOtherConfig && branch.nodeOtherConfig.translateX !== undefined && branch.nodeOtherConfig.translateY !== undefined) {
1553
+ if (branch.nodeOtherConfig?.translateX !== undefined && branch.nodeOtherConfig.translateY !== undefined) {
1423
1554
  this.createNode(branch.nodeOtherConfig, branch, false, true);
1424
1555
  }
1425
1556
  });
@@ -1633,6 +1764,14 @@ class LibsUiDiagramDrawService {
1633
1764
  }
1634
1765
  });
1635
1766
  }
1767
+ /**
1768
+ * Build dữ liệu navigation line (next_other_id) từ flat elements để render qua draw-line directive.
1769
+ * Service tự đọc `orientation()` để chọn pattern endpoint phù hợp.
1770
+ * Caller chỉ cần truyền vào `drawLineFunctionControl.setData(...)`.
1771
+ */
1772
+ buildNavigationData(flatElements, styleConfig) {
1773
+ return LibsUiDiagramDrawNavigationUtil.buildNavigationData(flatElements, this.orientation(), styleConfig);
1774
+ }
1636
1775
  /** Xóa tất cả drop zone "+" khỏi DOM */
1637
1776
  clearDropZones() {
1638
1777
  const container = this.configCanvas()?.nodesContainer?.nativeElement;
@@ -1833,18 +1972,18 @@ class LibsUiDiagramDrawCanvasUtil {
1833
1972
  static buildFlatElement(elements, flatElementsContainer) {
1834
1973
  elements.forEach((element) => {
1835
1974
  flatElementsContainer.push(element);
1836
- if (!element.branches || !element.branches.length) {
1975
+ if (!element.branches?.length) {
1837
1976
  return;
1838
1977
  }
1839
1978
  LibsUiDiagramDrawCanvasUtil.flatElementHasBranch(element, flatElementsContainer);
1840
1979
  });
1841
1980
  }
1842
1981
  static flatElementHasBranch(element, flatElementsContainer) {
1843
- if (!element.branches || !element.branches.length) {
1982
+ if (!element.branches?.length) {
1844
1983
  return;
1845
1984
  }
1846
1985
  element.branches.forEach((branch) => {
1847
- if (!branch.elements || !branch.elements.length) {
1986
+ if (!branch.elements?.length) {
1848
1987
  return;
1849
1988
  }
1850
1989
  LibsUiDiagramDrawCanvasUtil.buildFlatElement(branch.elements, flatElementsContainer);
@@ -1859,11 +1998,11 @@ class LibsUiDiagramDrawCanvasUtil {
1859
1998
  * data.count: số lượng branch có next_id đến idElement
1860
1999
  */
1861
2000
  static getBranchContainerAndCountElementHasNextIdToElement(element, idElement, data, flowFlatElements) {
1862
- if (!element || !element.branches) {
2001
+ if (!element?.branches) {
1863
2002
  return;
1864
2003
  }
1865
2004
  element.branches.forEach((branch) => {
1866
- if (!branch.elements || !branch.elements.length) {
2005
+ if (!branch.elements?.length) {
1867
2006
  data.count++;
1868
2007
  data.branchContainer = branch;
1869
2008
  data.branchEmpty++;
@@ -1873,7 +2012,7 @@ class LibsUiDiagramDrawCanvasUtil {
1873
2012
  if (!lastElement.next_id) {
1874
2013
  return;
1875
2014
  }
1876
- if (lastElement.branches && lastElement.branches.length) {
2015
+ if (lastElement.branches?.length) {
1877
2016
  const dataOfLastElement = this.getDefaultStorageBranchEndCount();
1878
2017
  LibsUiDiagramDrawCanvasUtil.getBranchContainerAndCountElementHasNextIdToElement(lastElement, idElement, dataOfLastElement, flowFlatElements);
1879
2018
  if (!dataOfLastElement.count) {
@@ -1883,7 +2022,8 @@ class LibsUiDiagramDrawCanvasUtil {
1883
2022
  data.count++;
1884
2023
  data.branchContainer = branch;
1885
2024
  if (dataOfLastElement.count === 1) {
1886
- return (data.branchContainer = dataOfLastElement.branchContainer);
2025
+ data.branchContainer = dataOfLastElement.branchContainer;
2026
+ return;
1887
2027
  }
1888
2028
  return;
1889
2029
  }
@@ -1893,7 +2033,6 @@ class LibsUiDiagramDrawCanvasUtil {
1893
2033
  }
1894
2034
  data.count++;
1895
2035
  data.branchContainer = branch;
1896
- return;
1897
2036
  });
1898
2037
  }
1899
2038
  static getElementHasCurrentBranchOrCurrentElement(currentBranch, currentElement, flatElements) {
@@ -1901,15 +2040,15 @@ class LibsUiDiagramDrawCanvasUtil {
1901
2040
  currentBranch: undefined,
1902
2041
  element: undefined,
1903
2042
  };
1904
- if (!flatElements || !flatElements.length || (!currentBranch && !currentElement)) {
2043
+ if (!flatElements?.length || (!currentBranch && !currentElement)) {
1905
2044
  return data;
1906
2045
  }
1907
2046
  if (!currentElement) {
1908
2047
  data.currentBranch = currentBranch;
1909
- data.element = flatElements.find((el) => el.branches && !!el.branches.find((branch) => branch === currentBranch));
2048
+ data.element = flatElements.find((el) => !!el.branches?.find((branch) => branch === currentBranch));
1910
2049
  return data;
1911
2050
  }
1912
- const elementsHasBranches = flatElements.filter((item) => item.branches && item.branches.length);
2051
+ const elementsHasBranches = flatElements.filter((item) => item.branches?.length);
1913
2052
  if (!elementsHasBranches) {
1914
2053
  return data;
1915
2054
  }
@@ -1919,7 +2058,7 @@ class LibsUiDiagramDrawCanvasUtil {
1919
2058
  return data;
1920
2059
  }
1921
2060
  for (const branch of branches) {
1922
- if (!branch.elements || !branch.elements.length) {
2061
+ if (!branch.elements?.length) {
1923
2062
  continue;
1924
2063
  }
1925
2064
  if (branch.elements.find((item) => item.id === currentElement.id)) {
@@ -1938,11 +2077,11 @@ class LibsUiDiagramDrawCanvasUtil {
1938
2077
  containerElement.splice(+index, 1);
1939
2078
  return true;
1940
2079
  }
1941
- if (!elementOfIndex.branches || !elementOfIndex.branches.length) {
2080
+ if (!elementOfIndex.branches?.length) {
1942
2081
  continue;
1943
2082
  }
1944
2083
  for (const branch of elementOfIndex.branches) {
1945
- if (!branch.elements || !branch.elements.length) {
2084
+ if (!branch.elements?.length) {
1946
2085
  continue;
1947
2086
  }
1948
2087
  if (this.findAndDeleteElementFromContainer(branch.elements, elementDelete)) {
@@ -1958,7 +2097,7 @@ class LibsUiDiagramDrawCanvasUtil {
1958
2097
  return;
1959
2098
  }
1960
2099
  for (const item of flatElementHasBranch) {
1961
- if (!item.branches || !item.branches.length) {
2100
+ if (!item.branches?.length) {
1962
2101
  continue;
1963
2102
  }
1964
2103
  for (const branch of item.branches) {
@@ -1990,11 +2129,11 @@ const findAndDeleteElementFromContainer = (containerElement, elementDelete) => {
1990
2129
  containerElement.splice(+index, 1);
1991
2130
  return true;
1992
2131
  }
1993
- if (!elementOfIndex.branches || !elementOfIndex.branches.length) {
2132
+ if (!elementOfIndex.branches?.length) {
1994
2133
  continue;
1995
2134
  }
1996
2135
  for (const branch of elementOfIndex.branches) {
1997
- if (!branch.elements || !branch.elements.length) {
2136
+ if (!branch.elements?.length) {
1998
2137
  continue;
1999
2138
  }
2000
2139
  if (findAndDeleteElementFromContainer(branch.elements, elementDelete)) {
@@ -2678,7 +2817,7 @@ const getAllItemPreOfElement = (element, flatElements) => {
2678
2817
  };
2679
2818
  const getAllItemNextOfElement = (element, flatElements) => {
2680
2819
  if (!element.next_id) {
2681
- if (!element.branches || !element.branches.length) {
2820
+ if (!element.branches?.length) {
2682
2821
  return;
2683
2822
  }
2684
2823
  const flatElementInElementCurrent = [];
@@ -2783,17 +2922,17 @@ class LibsUiDiagramDrawDirectionService {
2783
2922
  /**xóa line đến và xóa line đi ở toàn bộ các khối và nhánh bị xóa */
2784
2923
  deleteLineConnectFromElement(elements, flatElements) {
2785
2924
  elements.forEach((item) => {
2786
- if (item.branches && item.branches.length) {
2925
+ if (item.branches?.length) {
2787
2926
  item.branches.forEach((branch) => {
2788
- if (branch.next_other_id && branch.next_other_id.length) {
2927
+ if (branch.next_other_id?.length) {
2789
2928
  this.deletePreOtherId(item.id ?? '', branch.next_other_id, flatElements);
2790
2929
  }
2791
2930
  });
2792
2931
  }
2793
- if (item.next_other_id && item.next_other_id.length) {
2932
+ if (item.next_other_id?.length) {
2794
2933
  this.deletePreOtherId(item.id ?? '', item.next_other_id, flatElements);
2795
2934
  }
2796
- if (item.pre_other_id && item.pre_other_id.length) {
2935
+ if (item.pre_other_id?.length) {
2797
2936
  // nhánh chỉ lưu id next đi thôi chứ không lưu được pre => chỉ cần xóa pre trong khối.
2798
2937
  this.deleteNextOtherId(item.id ?? '', item.pre_other_id, flatElements);
2799
2938
  }
@@ -2803,7 +2942,7 @@ class LibsUiDiagramDrawDirectionService {
2803
2942
  deletePreOtherId(itemId, nextOtherId, flatElements) {
2804
2943
  nextOtherId.forEach((nextToId) => {
2805
2944
  const nextElement = flatElements.find((item) => item.id === nextToId);
2806
- if (!nextElement || !nextElement.pre_other_id || !nextElement.pre_other_id.length) {
2945
+ if (!nextElement?.pre_other_id?.length) {
2807
2946
  return;
2808
2947
  }
2809
2948
  const indexIdPre = nextElement.pre_other_id.findIndex((id) => id === itemId);
@@ -2821,28 +2960,28 @@ class LibsUiDiagramDrawDirectionService {
2821
2960
  }
2822
2961
  if (preElement.element_type === canvasConfigReadonly().TYPE_ELEMENT_WORKFLOW) {
2823
2962
  preElement.branches?.forEach((branch) => {
2824
- if (!branch.next_other_id || !branch.next_other_id.length) {
2963
+ if (!branch.next_other_id?.length) {
2825
2964
  return;
2826
2965
  }
2827
2966
  const indexIdNextInBranch = branch.next_other_id.findIndex((id) => id === itemId);
2828
2967
  if (indexIdNextInBranch !== -1) {
2829
2968
  branch.next_other_id.splice(indexIdNextInBranch, 1);
2830
2969
  }
2831
- if (!branch.next_other_id || !branch.next_other_id.length) {
2970
+ if (!branch.next_other_id?.length) {
2832
2971
  branch.nodeOtherConfig = undefined;
2833
2972
  this.canvasService.addElementExitWhenDeleteDirectionLine(preElement, branch);
2834
2973
  }
2835
2974
  });
2836
2975
  return;
2837
2976
  }
2838
- if (!preElement.next_other_id || !preElement.next_other_id.length) {
2977
+ if (!preElement.next_other_id?.length) {
2839
2978
  return;
2840
2979
  }
2841
2980
  const indexIdNext = preElement.next_other_id.findIndex((id) => id === itemId);
2842
2981
  if (indexIdNext !== -1) {
2843
2982
  preElement.next_other_id.splice(indexIdNext, 1);
2844
2983
  }
2845
- if (!preElement.next_other_id || !preElement.next_other_id.length) {
2984
+ if (!preElement.next_other_id?.length) {
2846
2985
  // thêm khối thoát vì không còn khối nào connect tới nó
2847
2986
  if (preElement.element_type === canvasConfigReadonly().TYPE_ELEMENT_WORKFLOW) {
2848
2987
  const getConfigDefaultBranches = this.canvasService.HandlerFunction?.getConfigDefaultBranches ?? getDefaultConfigConstituentBranches;
@@ -2885,7 +3024,7 @@ class LibsUiDiagramDrawDirectionService {
2885
3024
  deleteElementsBehindElementConnectTo(element, flatElements) {
2886
3025
  const listElementDelete = [];
2887
3026
  let flatElementInElementCurrent = [];
2888
- if (element.branches && element.branches.length) {
3027
+ if (element.branches?.length) {
2889
3028
  buildFlatElement([element], flatElementInElementCurrent);
2890
3029
  flatElementInElementCurrent = flatElementInElementCurrent.filter((item) => item.id !== element.id);
2891
3030
  }
@@ -2904,11 +3043,11 @@ class LibsUiDiagramDrawDirectionService {
2904
3043
  containerElement.splice(+index, 1);
2905
3044
  return true;
2906
3045
  }
2907
- if (!elementOfIndex.branches || !elementOfIndex.branches.length) {
3046
+ if (!elementOfIndex.branches?.length) {
2908
3047
  continue;
2909
3048
  }
2910
3049
  for (const branch of elementOfIndex.branches) {
2911
- if (!branch.elements || !branch.elements.length) {
3050
+ if (!branch.elements?.length) {
2912
3051
  continue;
2913
3052
  }
2914
3053
  if (this.findAndDeleteElementFromContainer(branch.elements, elementDelete)) {
@@ -2926,7 +3065,7 @@ class LibsUiDiagramDrawDirectionService {
2926
3065
  const idOldNextTo = element.next_other_id?.[0];
2927
3066
  const elementOldTo = flatElements?.find((item) => item.id === idOldNextTo);
2928
3067
  // xóa line cũ
2929
- if (elementOldTo && elementOldTo.pre_other_id) {
3068
+ if (elementOldTo?.pre_other_id) {
2930
3069
  const itemIndex = elementOldTo.pre_other_id?.findIndex((id) => id === element.id);
2931
3070
  if (itemIndex !== -1) {
2932
3071
  elementOldTo.pre_other_id?.splice(itemIndex, 1);
@@ -2949,7 +3088,7 @@ class LibsUiDiagramDrawDirectionService {
2949
3088
  const idOldNextTo = branch.next_other_id?.[0];
2950
3089
  const elementOldTo = flatElements?.find((item) => item.id === idOldNextTo);
2951
3090
  // xóa line cũ
2952
- if (elementOldTo && elementOldTo.pre_other_id) {
3091
+ if (elementOldTo?.pre_other_id) {
2953
3092
  const itemIndex = elementOldTo.pre_other_id?.findIndex((id) => id === element.id);
2954
3093
  if (itemIndex !== -1) {
2955
3094
  elementOldTo.pre_other_id?.splice(itemIndex, 1);