You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by as...@apache.org on 2021/03/19 15:06:34 UTC
[airflow] 32/42: Remember expanded task groups in localStorage
(#14661)
This is an automated email from the ASF dual-hosted git repository.
ash pushed a commit to branch v2-0-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 3a0fb37dd82724a4b0b602d436e6a0c464ba00d9
Author: yuqian90 <yu...@gmail.com>
AuthorDate: Fri Mar 12 23:11:58 2021 +0800
Remember expanded task groups in localStorage (#14661)
* Save expanded and focused state of TaskGroups in localStorage
* Restore focus on refresh
* Address style issues according to comments
(cherry picked from commit 456a7ddfd1da797d493abd8a57d36d05424eaaa6)
---
airflow/www/templates/airflow/graph.html | 117 +++++++++++++++++++++++++++++--
1 file changed, 110 insertions(+), 7 deletions(-)
diff --git a/airflow/www/templates/airflow/graph.html b/airflow/www/templates/airflow/graph.html
index 844ce38..807cef1 100644
--- a/airflow/www/templates/airflow/graph.html
+++ b/airflow/www/templates/airflow/graph.html
@@ -235,7 +235,7 @@
});
d3.selectAll("g.node").on("mouseout", function (d) {
- d3.select(this).selectAll("rect").style("stroke", null);
+ d3.select(this).selectAll("rect,circle").style("stroke", null);
highlight_nodes(g.predecessors(d), null, initialStrokeWidth)
highlight_nodes(g.successors(d), null, initialStrokeWidth)
d3.selectAll("g.node")
@@ -244,6 +244,7 @@
.style("stroke-width", initialStrokeWidth);
d3.selectAll("g.edgePath")
.style("opacity", 1);
+ localStorage.removeItem(focused_group_key(dag_id));
});
updateNodesStates(task_instances);
setUpZoomSupport();
@@ -417,6 +418,8 @@
.style("opacity", 1);
d3.selectAll('.js-state-legend-item')
.style("background-color", null);
+
+ localStorage.removeItem(focused_group_key(dag_id));
}
function focusState(state, node, color){
@@ -591,6 +594,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;
+ }
+
// Return the state for the node based on the state of its taskinstance or that of its
// children if it's a group node
@@ -626,6 +645,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}`;
+ }
+
// Focus the graph on the expanded/collapsed node
function focus_group(node_id) {
if(node_id != null && zoom != null) {
@@ -668,11 +697,13 @@
.style("opacity", 0.2).duration(duration)
}
});
+
+ localStorage.setItem(focused_group_key(dag_id), node_id);
}
}
// Expands a group node
- function expand_group(node_id, node) {
+ function expand_group(node_id, node, focus=true) {
node.children.forEach(function (val) {
// Set children nodes
g.setNode(val.id, val.value)
@@ -706,17 +737,22 @@
})
draw()
- focus_group(node_id)
+
+ if (focus) {
+ focus_group(node_id);
+ }
+
+ save_expanded_group(node_id)
}
// Remove the node with this node_id from g.
function remove_node(node_id) {
- if(g.hasNode(node_id)) {
+ if (g.hasNode(node_id)) {
node = g.node(node_id)
if(node.children != undefined) {
// If the child is an expanded group node, remove children too.
node.children.forEach(function (child) {
- remove_node(child.id)
+ remove_node(child.id);
})
}
}
@@ -745,10 +781,77 @@
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);
+ }
- initRefresh();
+ initRefresh();
</script>
{% endblock %}