Repository: kestra-io/kestra
Issue: Moving outside task in place of a Dag subtask which others depend on break everything
Labels: bug
enhancement
frontend

### Expected Behavior

_No response_

### Actual Behaviour

Here I moved "hello" task which was outside, in place of the "b" task which is a dependance of "a" task.

It breaks everything -> yaml editor was properly updated (although incorrect due to missing dependency) while the topology looks buggy and can't move my "hello" task except by drag&dropping on the underneath "b" task which moves back the "hello" task outside and "b" task inside due to flow becoming valid again
![image](https://github.com/kestra-io/kestra/assets/37618489/f9c5309f-d5b8-40c1-aac4-ff4fe8a4bea0)


### Steps To Reproduce

Create a Dag task with two task, including one which is dependant of the other
Create a task outside of the Dag
Move the outside task in place of the dependance task

-> If you move the outside task on a dag task which has no dependency it works properly

### Environment Information

- Kestra Version: 0.10.0-SNAPSHOT
- Operating System (OS / Docker / Kubernetes):
- Java Version (If not docker):


### Example flow

```
id: hello-worldf
namespace: dev
labels:
  some: flowLabel
tasks:
  - id: dag
    type: io.kestra.core.tasks.flows.Dag
    tasks:
      - task:
          id: a
          type: io.kestra.core.tasks.flows.Flow
          namespace: dev
          flowId: hello-world
        dependsOn:
          - b
      - task:
          id: b
          type: io.kestra.core.tasks.scripts.Bash
          commands:
            - "sleep 5"
      - task:
          id: c
          type: io.kestra.core.tasks.log.Log
          message: Ended all
        dependsOn:
          - a
  - id: hello
    type: io.kestra.core.tasks.log.Log
    message: Kestra team wishes you a great day! 👋
```

Issue comments:

Pull request review comments:

Patch that resolved the issue:
diff --git a/ui/src/components/inputs/LowCodeEditor.vue b/ui/src/components/inputs/LowCodeEditor.vue
index 8d0a33cb95..8923583025 100644
--- a/ui/src/components/inputs/LowCodeEditor.vue
+++ b/ui/src/components/inputs/LowCodeEditor.vue
@@ -208,12 +208,21 @@
             // check multiple intersection with task
             const taskNode2 = e.intersections.find(n => n.type === "task");
             if (taskNode2) {
-                emit("on-edit", YamlUtils.swapTasks(props.source, taskNode1.id, taskNode2.id))
+                try {
+                    emit("on-edit", YamlUtils.swapTasks(props.source, taskNode1.id, taskNode2.id))
+                } catch (e) {
+                    store.dispatch("core/showMessage", {
+                        variant: "error",
+                        title: t("cannot swap tasks"),
+                        message: t(e.message, e.messageOptions)
+                    });
+                    taskNode1.position = lastPosition.value;
+                }
             } else {
-                getNodes.value.find(n => n.id === e.node.id).position = lastPosition.value;
+                taskNode1.position = lastPosition.value;
             }
         } else {
-            getNodes.value.find(n => n.id === e.node.id).position = lastPosition.value;
+            e.node.position = lastPosition.value;
         }
         resetNodesStyle();
         e.node.style = {...e.node.style, zIndex: 1}
diff --git a/ui/src/translations.json b/ui/src/translations.json
index d986793b6d..ff07889c0e 100644
--- a/ui/src/translations.json
+++ b/ui/src/translations.json
@@ -457,7 +457,9 @@
     "collapse all": "Collapse all",
     "log expand setting": "Log default display",
     "slack support": "Ask help on our Slack",
-    "error detected": "Error detected"
+    "error detected": "Error detected",
+    "cannot swap tasks": "Can't swap the tasks",
+    "dependency task": "Task {taskId} is a dependency of another task"
   },
   "fr": {
     "id": "Identifiant",
@@ -919,6 +921,8 @@
     "collapse all": "Masquer tout",
     "log expand setting": "Affichage par défaut des journaux",
     "slack support": "Demandez de l'aide sur notre Slack",
-    "error detected": "Erreur détectée"
+    "error detected": "Erreur détectée",
+    "cannot swap tasks": "Impossible de permuter les tâches",
+    "dependency task": "La tâche {taskId} est une dépendance d'une autre tâche"
   }
 }
diff --git a/ui/src/utils/yamlUtils.js b/ui/src/utils/yamlUtils.js
index 67d6cbdbce..45dfbbfb79 100644
--- a/ui/src/utils/yamlUtils.js
+++ b/ui/src/utils/yamlUtils.js
@@ -205,6 +205,17 @@ export default class YamlUtils {
         const task1 = YamlUtils._extractTask(yamlDoc, taskId1);
         const task2 = YamlUtils._extractTask(yamlDoc, taskId2);
 
+        yaml.visit(yamlDoc, {
+            Pair(_, pair) {
+                if (pair.key.value === 'dependsOn' && pair.value.items.map(e => e.value).includes(taskId2)) {
+                    throw {
+                        message: 'dependency task',
+                        messageOptions: { taskId: taskId2 }
+                    };
+                }
+            }
+        });
+
         YamlUtils._extractTask(yamlDoc, taskId1, () => task2);
         YamlUtils._extractTask(yamlDoc, taskId2, () => task1);
 


Test patch: