ryanahamilton commented on a change in pull request #14661:
URL: https://github.com/apache/airflow/pull/14661#discussion_r589675746



##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -667,11 +696,13 @@
                       .style("opacity", 0.2).duration(duration)
               }
             });
+
+            localStorage.setItem(focused_group_key(dag_id), node_id)

Review comment:
       ```suggestion
               localStorage.setItem(focused_group_key(dag_id), node_id);
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -244,6 +244,7 @@
             .style("stroke-width", initialStrokeWidth);
           d3.selectAll("g.edgePath")
             .style("opacity", 1);
+          localStorage.removeItem(focused_group_key(dag_id))

Review comment:
       ```suggestion
             localStorage.removeItem(focused_group_key(dag_id));
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -744,10 +779,76 @@
 
         draw()
         focus_group(node_id)
+
+        remove_expanded_group(node_id, node)
       }
 
-      expand_group(null, nodes)
+    function get_saved_groups(dag_id) {
+        // expanded_groups is a Set
+        try {
+            var expanded_groups = new 
Set(JSON.parse(localStorage.getItem(expanded_groups_key(dag_id))));
+        } catch {
+            var expanded_groups = new Set();
+        }
+
+        return expanded_groups;
+    }
+
+    // Clean up invalid group_ids from saved_group_ids (e.g. due to DAG 
changes)
+    function prune_invalid_saved_group_ids() {
+        // All the group_ids in the whole DAG
+        const all_group_ids = new Set(get_all_group_ids(nodes))

Review comment:
       ```suggestion
           const all_group_ids = new Set(get_all_group_ids(nodes));
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -744,10 +779,76 @@
 
         draw()
         focus_group(node_id)
+
+        remove_expanded_group(node_id, node)
       }
 
-      expand_group(null, nodes)
+    function get_saved_groups(dag_id) {
+        // expanded_groups is a Set
+        try {
+            var expanded_groups = new 
Set(JSON.parse(localStorage.getItem(expanded_groups_key(dag_id))));
+        } catch {
+            var expanded_groups = new Set();
+        }
+
+        return expanded_groups;
+    }
+
+    // Clean up invalid group_ids from saved_group_ids (e.g. due to DAG 
changes)
+    function prune_invalid_saved_group_ids() {
+        // All the group_ids in the whole DAG
+        const all_group_ids = new Set(get_all_group_ids(nodes))
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups = Array.from(expanded_groups).filter(group_id => 
all_group_ids.has(group_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(expanded_groups))
+    }
+
+    // Remember the expanded groups in local storage so that it can be used to 
restore the expanded state
+    // of task groups.
+    function save_expanded_group(node_id) {
+        // expanded_groups is a Set
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups.add(node_id)
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Remove the node_id from the expanded state
+    function remove_expanded_group(node_id, node) {
+        var expanded_groups = get_saved_groups(dag_id);
+        const child_group_ids = get_all_group_ids(node)
+        child_group_ids.forEach(child_id => expanded_groups.delete(child_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Restore previously expanded task groups
+    function expand_saved_groups(expanded_groups, node) {
+        if (node.children == undefined) {
+            return;
+        }
+
+        node.children.forEach(function (child_node) {
+            if(expanded_groups.has(child_node.id)) {
+                expand_group(child_node.id, g.node(child_node.id), false)
+
+                expand_saved_groups(expanded_groups, child_node)
+            }
+        })

Review comment:
       ```suggestion
           node.children.forEach(function (child_node) {
               if (expanded_groups.has(child_node.id)) {
                   expand_group(child_node.id, g.node(child_node.id), false);
                   expand_saved_groups(expanded_groups, child_node);
               }
           });
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -744,10 +779,76 @@
 
         draw()
         focus_group(node_id)
+
+        remove_expanded_group(node_id, node)
       }
 
-      expand_group(null, nodes)
+    function get_saved_groups(dag_id) {
+        // expanded_groups is a Set
+        try {
+            var expanded_groups = new 
Set(JSON.parse(localStorage.getItem(expanded_groups_key(dag_id))));
+        } catch {
+            var expanded_groups = new Set();
+        }
+
+        return expanded_groups;
+    }
+
+    // Clean up invalid group_ids from saved_group_ids (e.g. due to DAG 
changes)
+    function prune_invalid_saved_group_ids() {
+        // All the group_ids in the whole DAG
+        const all_group_ids = new Set(get_all_group_ids(nodes))
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups = Array.from(expanded_groups).filter(group_id => 
all_group_ids.has(group_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(expanded_groups))
+    }
+
+    // Remember the expanded groups in local storage so that it can be used to 
restore the expanded state
+    // of task groups.
+    function save_expanded_group(node_id) {
+        // expanded_groups is a Set
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups.add(node_id)
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Remove the node_id from the expanded state
+    function remove_expanded_group(node_id, node) {
+        var expanded_groups = get_saved_groups(dag_id);
+        const child_group_ids = get_all_group_ids(node)
+        child_group_ids.forEach(child_id => expanded_groups.delete(child_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Restore previously expanded task groups
+    function expand_saved_groups(expanded_groups, node) {
+        if (node.children == undefined) {
+            return;
+        }
+
+        node.children.forEach(function (child_node) {
+            if(expanded_groups.has(child_node.id)) {
+                expand_group(child_node.id, g.node(child_node.id), false)
+
+                expand_saved_groups(expanded_groups, child_node)
+            }
+        })
+    }
+
+    prune_invalid_saved_group_ids()
+    const focus_node_id = localStorage.getItem(focused_group_key(dag_id))
+    const expanded_groups = get_saved_groups(dag_id)
+
+    // Always expand the root node
+    expand_group(null, nodes)
+
+    // Expand the node that were previously expanded
+    expand_saved_groups(expanded_groups, nodes)
+
+    // Restore focus (if available)
+    if(g.hasNode(focus_node_id))
+      focus_group(focus_node_id)

Review comment:
       ```suggestion
       if (g.hasNode(focus_node_id)) {
          focus_group(focus_node_id);
       }
        
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -625,6 +644,16 @@
         return "no_status"
       }
 
+      // Returns the key used to store expanded task group ids in localStorage
+      function expanded_groups_key(dag_id) {
+          return `expanded_groups_${dag_id}`
+      }
+
+      // Returns the key used to store the focused task group id in 
localStorage
+      function focused_group_key(dag_id) {
+          return `focused_group_${dag_id}`

Review comment:
       ```suggestion
             return `focused_group_${dag_id}`;
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -625,6 +644,16 @@
         return "no_status"
       }
 
+      // Returns the key used to store expanded task group ids in localStorage
+      function expanded_groups_key(dag_id) {
+          return `expanded_groups_${dag_id}`

Review comment:
       ```suggestion
             return `expanded_groups_${dag_id}`;
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -590,6 +593,22 @@
         return children
       }
 
+      // Return list of all task group ids in the given task group including 
the given group itself.
+      function get_all_group_ids(group) {
+        var children = [group.id]
+
+        for(const [key, val] of Object.entries(group.children)) {
+          if(val.children != undefined) {
+            // group
+            const sub_group_children = get_all_group_ids(val)
+            for(const id of sub_group_children) {
+              children.push(id)
+            }
+          }
+        }
+        return children
+      }

Review comment:
       ```suggestion
         function get_all_group_ids(group) {
           var children = [group.id];
   
           for (const [key, val] of Object.entries(group.children)) {
             if (val.children != undefined) {
               // group
               const sub_group_children = get_all_group_ids(val);
               for (const id of sub_group_children) {
                 children.push(id);
               }
             }
           }
           return children;
         }
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -744,10 +779,76 @@
 
         draw()
         focus_group(node_id)
+
+        remove_expanded_group(node_id, node)
       }
 
-      expand_group(null, nodes)
+    function get_saved_groups(dag_id) {
+        // expanded_groups is a Set
+        try {
+            var expanded_groups = new 
Set(JSON.parse(localStorage.getItem(expanded_groups_key(dag_id))));
+        } catch {
+            var expanded_groups = new Set();
+        }
+
+        return expanded_groups;
+    }
+
+    // Clean up invalid group_ids from saved_group_ids (e.g. due to DAG 
changes)
+    function prune_invalid_saved_group_ids() {
+        // All the group_ids in the whole DAG
+        const all_group_ids = new Set(get_all_group_ids(nodes))
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups = Array.from(expanded_groups).filter(group_id => 
all_group_ids.has(group_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(expanded_groups))
+    }
+
+    // Remember the expanded groups in local storage so that it can be used to 
restore the expanded state
+    // of task groups.
+    function save_expanded_group(node_id) {
+        // expanded_groups is a Set
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups.add(node_id)
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))

Review comment:
       ```suggestion
           expanded_groups.add(node_id);
           localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)));
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -705,7 +736,11 @@
         })
 
         draw()
-        focus_group(node_id)
+
+        if (focus)
+          focus_group(node_id)
+

Review comment:
       ```suggestion
           if (focus) {
             focus_group(node_id);
           }
   
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -744,10 +779,76 @@
 
         draw()
         focus_group(node_id)
+
+        remove_expanded_group(node_id, node)

Review comment:
       ```suggestion
           remove_expanded_group(node_id, node);
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -416,6 +417,8 @@
               .style("opacity", 1);
           d3.selectAll('.js-state-legend-item')
               .style("background-color", null);
+
+          localStorage.removeItem(focused_group_key(dag_id))

Review comment:
       ```suggestion
             localStorage.removeItem(focused_group_key(dag_id));
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -744,10 +779,76 @@
 
         draw()
         focus_group(node_id)
+
+        remove_expanded_group(node_id, node)
       }
 
-      expand_group(null, nodes)
+    function get_saved_groups(dag_id) {
+        // expanded_groups is a Set
+        try {
+            var expanded_groups = new 
Set(JSON.parse(localStorage.getItem(expanded_groups_key(dag_id))));
+        } catch {
+            var expanded_groups = new Set();
+        }
+
+        return expanded_groups;
+    }
+
+    // Clean up invalid group_ids from saved_group_ids (e.g. due to DAG 
changes)
+    function prune_invalid_saved_group_ids() {
+        // All the group_ids in the whole DAG
+        const all_group_ids = new Set(get_all_group_ids(nodes))
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups = Array.from(expanded_groups).filter(group_id => 
all_group_ids.has(group_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(expanded_groups))
+    }
+
+    // Remember the expanded groups in local storage so that it can be used to 
restore the expanded state
+    // of task groups.
+    function save_expanded_group(node_id) {
+        // expanded_groups is a Set
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups.add(node_id)
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Remove the node_id from the expanded state
+    function remove_expanded_group(node_id, node) {
+        var expanded_groups = get_saved_groups(dag_id);
+        const child_group_ids = get_all_group_ids(node)
+        child_group_ids.forEach(child_id => expanded_groups.delete(child_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))

Review comment:
       ```suggestion
           const child_group_ids = get_all_group_ids(node);
           child_group_ids.forEach(child_id => 
expanded_groups.delete(child_id));
           localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)));
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -744,10 +779,76 @@
 
         draw()
         focus_group(node_id)
+
+        remove_expanded_group(node_id, node)
       }
 
-      expand_group(null, nodes)
+    function get_saved_groups(dag_id) {
+        // expanded_groups is a Set
+        try {
+            var expanded_groups = new 
Set(JSON.parse(localStorage.getItem(expanded_groups_key(dag_id))));
+        } catch {
+            var expanded_groups = new Set();
+        }
+
+        return expanded_groups;
+    }
+
+    // Clean up invalid group_ids from saved_group_ids (e.g. due to DAG 
changes)
+    function prune_invalid_saved_group_ids() {
+        // All the group_ids in the whole DAG
+        const all_group_ids = new Set(get_all_group_ids(nodes))
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups = Array.from(expanded_groups).filter(group_id => 
all_group_ids.has(group_id))

Review comment:
       ```suggestion
           expanded_groups = Array.from(expanded_groups).filter(group_id => 
all_group_ids.has(group_id));
   ```
   ```suggestion
           expanded_groups = Array.from(expanded_groups).filter(group_id => 
all_group_ids.has(group_id))
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -744,10 +779,76 @@
 
         draw()
         focus_group(node_id)
+
+        remove_expanded_group(node_id, node)
       }
 
-      expand_group(null, nodes)
+    function get_saved_groups(dag_id) {
+        // expanded_groups is a Set
+        try {
+            var expanded_groups = new 
Set(JSON.parse(localStorage.getItem(expanded_groups_key(dag_id))));
+        } catch {
+            var expanded_groups = new Set();
+        }
+
+        return expanded_groups;
+    }
+
+    // Clean up invalid group_ids from saved_group_ids (e.g. due to DAG 
changes)
+    function prune_invalid_saved_group_ids() {
+        // All the group_ids in the whole DAG
+        const all_group_ids = new Set(get_all_group_ids(nodes))
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups = Array.from(expanded_groups).filter(group_id => 
all_group_ids.has(group_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(expanded_groups))
+    }
+
+    // Remember the expanded groups in local storage so that it can be used to 
restore the expanded state
+    // of task groups.
+    function save_expanded_group(node_id) {
+        // expanded_groups is a Set
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups.add(node_id)
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Remove the node_id from the expanded state
+    function remove_expanded_group(node_id, node) {
+        var expanded_groups = get_saved_groups(dag_id);
+        const child_group_ids = get_all_group_ids(node)
+        child_group_ids.forEach(child_id => expanded_groups.delete(child_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Restore previously expanded task groups
+    function expand_saved_groups(expanded_groups, node) {
+        if (node.children == undefined) {
+            return;
+        }
+
+        node.children.forEach(function (child_node) {
+            if(expanded_groups.has(child_node.id)) {
+                expand_group(child_node.id, g.node(child_node.id), false)
+
+                expand_saved_groups(expanded_groups, child_node)
+            }
+        })
+    }
+
+    prune_invalid_saved_group_ids()

Review comment:
       ```suggestion
       prune_invalid_saved_group_ids();
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -744,10 +779,76 @@
 
         draw()
         focus_group(node_id)
+
+        remove_expanded_group(node_id, node)
       }
 
-      expand_group(null, nodes)
+    function get_saved_groups(dag_id) {
+        // expanded_groups is a Set
+        try {
+            var expanded_groups = new 
Set(JSON.parse(localStorage.getItem(expanded_groups_key(dag_id))));
+        } catch {
+            var expanded_groups = new Set();
+        }
+
+        return expanded_groups;
+    }
+
+    // Clean up invalid group_ids from saved_group_ids (e.g. due to DAG 
changes)
+    function prune_invalid_saved_group_ids() {
+        // All the group_ids in the whole DAG
+        const all_group_ids = new Set(get_all_group_ids(nodes))
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups = Array.from(expanded_groups).filter(group_id => 
all_group_ids.has(group_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(expanded_groups))
+    }
+
+    // Remember the expanded groups in local storage so that it can be used to 
restore the expanded state
+    // of task groups.
+    function save_expanded_group(node_id) {
+        // expanded_groups is a Set
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups.add(node_id)
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Remove the node_id from the expanded state
+    function remove_expanded_group(node_id, node) {
+        var expanded_groups = get_saved_groups(dag_id);
+        const child_group_ids = get_all_group_ids(node)
+        child_group_ids.forEach(child_id => expanded_groups.delete(child_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Restore previously expanded task groups
+    function expand_saved_groups(expanded_groups, node) {
+        if (node.children == undefined) {
+            return;
+        }
+
+        node.children.forEach(function (child_node) {
+            if(expanded_groups.has(child_node.id)) {
+                expand_group(child_node.id, g.node(child_node.id), false)
+
+                expand_saved_groups(expanded_groups, child_node)
+            }
+        })
+    }
+
+    prune_invalid_saved_group_ids()
+    const focus_node_id = localStorage.getItem(focused_group_key(dag_id))
+    const expanded_groups = get_saved_groups(dag_id)
+
+    // Always expand the root node
+    expand_group(null, nodes)

Review comment:
       ```suggestion
       expand_group(null, nodes);
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -744,10 +779,76 @@
 
         draw()
         focus_group(node_id)
+
+        remove_expanded_group(node_id, node)
       }
 
-      expand_group(null, nodes)
+    function get_saved_groups(dag_id) {
+        // expanded_groups is a Set
+        try {
+            var expanded_groups = new 
Set(JSON.parse(localStorage.getItem(expanded_groups_key(dag_id))));
+        } catch {
+            var expanded_groups = new Set();
+        }
+
+        return expanded_groups;
+    }
+
+    // Clean up invalid group_ids from saved_group_ids (e.g. due to DAG 
changes)
+    function prune_invalid_saved_group_ids() {
+        // All the group_ids in the whole DAG
+        const all_group_ids = new Set(get_all_group_ids(nodes))
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups = Array.from(expanded_groups).filter(group_id => 
all_group_ids.has(group_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(expanded_groups))
+    }
+
+    // Remember the expanded groups in local storage so that it can be used to 
restore the expanded state
+    // of task groups.
+    function save_expanded_group(node_id) {
+        // expanded_groups is a Set
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups.add(node_id)
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Remove the node_id from the expanded state
+    function remove_expanded_group(node_id, node) {
+        var expanded_groups = get_saved_groups(dag_id);
+        const child_group_ids = get_all_group_ids(node)
+        child_group_ids.forEach(child_id => expanded_groups.delete(child_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Restore previously expanded task groups
+    function expand_saved_groups(expanded_groups, node) {
+        if (node.children == undefined) {
+            return;
+        }
+
+        node.children.forEach(function (child_node) {
+            if(expanded_groups.has(child_node.id)) {
+                expand_group(child_node.id, g.node(child_node.id), false)
+
+                expand_saved_groups(expanded_groups, child_node)
+            }
+        })
+    }
+
+    prune_invalid_saved_group_ids()
+    const focus_node_id = localStorage.getItem(focused_group_key(dag_id))
+    const expanded_groups = get_saved_groups(dag_id)
+
+    // Always expand the root node
+    expand_group(null, nodes)
+
+    // Expand the node that were previously expanded
+    expand_saved_groups(expanded_groups, nodes)

Review comment:
       ```suggestion
       expand_saved_groups(expanded_groups, nodes);
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -744,10 +779,76 @@
 
         draw()
         focus_group(node_id)
+
+        remove_expanded_group(node_id, node)
       }
 
-      expand_group(null, nodes)
+    function get_saved_groups(dag_id) {
+        // expanded_groups is a Set
+        try {
+            var expanded_groups = new 
Set(JSON.parse(localStorage.getItem(expanded_groups_key(dag_id))));
+        } catch {
+            var expanded_groups = new Set();
+        }
+
+        return expanded_groups;
+    }
+
+    // Clean up invalid group_ids from saved_group_ids (e.g. due to DAG 
changes)
+    function prune_invalid_saved_group_ids() {
+        // All the group_ids in the whole DAG
+        const all_group_ids = new Set(get_all_group_ids(nodes))
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups = Array.from(expanded_groups).filter(group_id => 
all_group_ids.has(group_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(expanded_groups))

Review comment:
       ```suggestion
           localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(expanded_groups));
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -744,10 +779,76 @@
 
         draw()
         focus_group(node_id)
+
+        remove_expanded_group(node_id, node)
       }
 
-      expand_group(null, nodes)
+    function get_saved_groups(dag_id) {
+        // expanded_groups is a Set
+        try {
+            var expanded_groups = new 
Set(JSON.parse(localStorage.getItem(expanded_groups_key(dag_id))));
+        } catch {
+            var expanded_groups = new Set();
+        }
+
+        return expanded_groups;
+    }
+
+    // Clean up invalid group_ids from saved_group_ids (e.g. due to DAG 
changes)
+    function prune_invalid_saved_group_ids() {
+        // All the group_ids in the whole DAG
+        const all_group_ids = new Set(get_all_group_ids(nodes))
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups = Array.from(expanded_groups).filter(group_id => 
all_group_ids.has(group_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(expanded_groups))
+    }
+
+    // Remember the expanded groups in local storage so that it can be used to 
restore the expanded state
+    // of task groups.
+    function save_expanded_group(node_id) {
+        // expanded_groups is a Set
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups.add(node_id)
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Remove the node_id from the expanded state
+    function remove_expanded_group(node_id, node) {
+        var expanded_groups = get_saved_groups(dag_id);
+        const child_group_ids = get_all_group_ids(node)
+        child_group_ids.forEach(child_id => expanded_groups.delete(child_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Restore previously expanded task groups
+    function expand_saved_groups(expanded_groups, node) {
+        if (node.children == undefined) {
+            return;
+        }
+
+        node.children.forEach(function (child_node) {
+            if(expanded_groups.has(child_node.id)) {
+                expand_group(child_node.id, g.node(child_node.id), false)
+
+                expand_saved_groups(expanded_groups, child_node)
+            }
+        })
+    }
+
+    prune_invalid_saved_group_ids()
+    const focus_node_id = localStorage.getItem(focused_group_key(dag_id))

Review comment:
       ```suggestion
       const focus_node_id = localStorage.getItem(focused_group_key(dag_id));
   ```

##########
File path: airflow/www/templates/airflow/graph.html
##########
@@ -744,10 +779,76 @@
 
         draw()
         focus_group(node_id)
+
+        remove_expanded_group(node_id, node)
       }
 
-      expand_group(null, nodes)
+    function get_saved_groups(dag_id) {
+        // expanded_groups is a Set
+        try {
+            var expanded_groups = new 
Set(JSON.parse(localStorage.getItem(expanded_groups_key(dag_id))));
+        } catch {
+            var expanded_groups = new Set();
+        }
+
+        return expanded_groups;
+    }
+
+    // Clean up invalid group_ids from saved_group_ids (e.g. due to DAG 
changes)
+    function prune_invalid_saved_group_ids() {
+        // All the group_ids in the whole DAG
+        const all_group_ids = new Set(get_all_group_ids(nodes))
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups = Array.from(expanded_groups).filter(group_id => 
all_group_ids.has(group_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(expanded_groups))
+    }
+
+    // Remember the expanded groups in local storage so that it can be used to 
restore the expanded state
+    // of task groups.
+    function save_expanded_group(node_id) {
+        // expanded_groups is a Set
+        var expanded_groups = get_saved_groups(dag_id);
+        expanded_groups.add(node_id)
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Remove the node_id from the expanded state
+    function remove_expanded_group(node_id, node) {
+        var expanded_groups = get_saved_groups(dag_id);
+        const child_group_ids = get_all_group_ids(node)
+        child_group_ids.forEach(child_id => expanded_groups.delete(child_id))
+        localStorage.setItem(expanded_groups_key(dag_id), 
JSON.stringify(Array.from(expanded_groups)))
+    }
+
+    // Restore previously expanded task groups
+    function expand_saved_groups(expanded_groups, node) {
+        if (node.children == undefined) {
+            return;
+        }
+
+        node.children.forEach(function (child_node) {
+            if(expanded_groups.has(child_node.id)) {
+                expand_group(child_node.id, g.node(child_node.id), false)
+
+                expand_saved_groups(expanded_groups, child_node)
+            }
+        })
+    }
+
+    prune_invalid_saved_group_ids()
+    const focus_node_id = localStorage.getItem(focused_group_key(dag_id))
+    const expanded_groups = get_saved_groups(dag_id)

Review comment:
       ```suggestion
       const expanded_groups = get_saved_groups(dag_id);
   ```




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to