From a39aba2d0694b2c21441c12507dfd7a4397abeae Mon Sep 17 00:00:00 2001 From: Qian Yu Date: Wed, 22 Feb 2023 16:29:23 +0800 Subject: [PATCH 1/5] Center clicked node around mouse graph zoom changes Fix find zoom Remove unused args Refactor --- airflow/example_dags/example_task_group.py | 11 +++--- airflow/www/static/js/graph.js | 41 +++++++++++++--------- airflow/www/templates/airflow/graph.html | 2 +- airflow/www/views.py | 2 -- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/airflow/example_dags/example_task_group.py b/airflow/example_dags/example_task_group.py index 9d7a9f2e74d59..87a9ca601b38c 100644 --- a/airflow/example_dags/example_task_group.py +++ b/airflow/example_dags/example_task_group.py @@ -35,12 +35,13 @@ start = EmptyOperator(task_id="start") # [START howto_task_group_section_1] - with TaskGroup("section_1", tooltip="Tasks for section_1") as section_1: - task_1 = EmptyOperator(task_id="task_1") - task_2 = BashOperator(task_id="task_2", bash_command="echo 1") - task_3 = EmptyOperator(task_id="task_3") + for i in range(10): + with TaskGroup(f"section_a_{i}", tooltip=f"Tasks for section_{i}") as section_1: + task_1 = EmptyOperator(task_id="task_1") + task_2 = BashOperator(task_id="task_2", bash_command="echo 1") + task_3 = EmptyOperator(task_id="task_3") - task_1 >> [task_2, task_3] + task_1 >> [task_2, task_3] # [END howto_task_group_section_1] # [START howto_task_group_section_2] diff --git a/airflow/www/static/js/graph.js b/airflow/www/static/js/graph.js index 4e1283040761e..28b592cc527dc 100644 --- a/airflow/www/static/js/graph.js +++ b/airflow/www/static/js/graph.js @@ -269,17 +269,18 @@ function setUpZoomSupport() { // Get Dagre Graph dimensions const graphWidth = g.graph().width; const graphHeight = g.graph().height; - // Get SVG dimensions - const padding = 80; - const svgBb = svg.node().getBoundingClientRect(); - const width = svgBb.width - padding * 2; - const height = svgBb.height - padding; // we are not centering the dag vertically + const {width, height} = svg.node().viewBox.animVal; + const padding = width * 0.05; // Calculate applicable scale for zoom const zoomScale = Math.min( Math.min(width / graphWidth, height / graphHeight), +<<<<<<< HEAD 1.5 // cap zoom level to 1.5 so nodes are not too large ); +======= + ) * 0.8; +>>>>>>> fd8b161fa1 (Center clicked node around mouse) zoom.translate([width / 2 - (graphWidth * zoomScale) / 2 + padding, padding]); zoom.scale(zoomScale); @@ -373,6 +374,7 @@ d3.select("#searchbox").on("keyup", () => { // This moves the matched node to the center of the graph area if (match) { +<<<<<<< HEAD const transform = d3.transform(d3.select(match).attr("transform")); const svgBb = svg.node().getBoundingClientRect(); @@ -387,6 +389,9 @@ d3.select("#searchbox").on("keyup", () => { zoom.scale(1); zoom.event(innerSvg); } +======= + focusGroup(match.id, false); +>>>>>>> fd8b161fa1 (Center clicked node around mouse) } }); @@ -656,11 +661,11 @@ function focusedGroupKey() { } // Focus the graph on the expanded/collapsed node -function focusGroup(nodeId) { +function focusGroup(nodeId, followMouse=true) { if (nodeId != null && zoom != null) { - const { x } = g.node(nodeId); + const { x, y } = g.node(nodeId); // This is the total canvas size. - const { width, height } = svg.node().getBoundingClientRect(); + const {width, height} = svg.node().viewBox.animVal; // This is the size of the node or the cluster (i.e. group) let rect = d3 @@ -673,6 +678,8 @@ function focusGroup(nodeId) { .filter((n) => n === nodeId) .select("rect"); + const [mouseX, mouseY] = d3.mouse(svg.node()); + // Is there a better way to get nodeWidth and nodeHeight ? const [nodeWidth, nodeHeight] = [ rect[0][0].attributes.width.value, @@ -680,17 +687,17 @@ function focusGroup(nodeId) { ]; // Calculate zoom scale to fill most of the canvas with the node/cluster in focus. - const scale = - Math.min( - Math.min(width / nodeWidth, height / nodeHeight), - 1.5 // cap zoom level to 1.5 so nodes are not too large - ) * 0.9; - - // deltaY of 5 keeps the zoom at the top of the view but with a slight margin - const [deltaX, deltaY] = [width / 2 - x * scale, 5]; + const scale = Math.min( + Math.min(width / nodeWidth, height / nodeHeight), 1 + ) * 0.2; + + // Move the graph so that the node that was expanded/collapsed is centered around + // the mouse click. + const [toX, toY] = followMouse ? [mouseX, mouseY] : [width / 2, height / 5]; + const [deltaX, deltaY] = [toX - x * scale, toY + (nodeHeight / 2 - y) * scale]; zoom.translate([deltaX, deltaY]); zoom.scale(scale); - zoom.event(innerSvg.transition().duration(duration)); + zoom.event(innerSvg); const children = new Set(g.children(nodeId)); // Set data attr to highlight the focused group (via CSS). diff --git a/airflow/www/templates/airflow/graph.html b/airflow/www/templates/airflow/graph.html index c4e28c32fb622..9d4ee6e8172ed 100644 --- a/airflow/www/templates/airflow/graph.html +++ b/airflow/www/templates/airflow/graph.html @@ -121,7 +121,7 @@
- +
diff --git a/airflow/www/views.py b/airflow/www/views.py index 401c667bc7a72..c0125ed272b23 100644 --- a/airflow/www/views.py +++ b/airflow/www/views.py @@ -2953,8 +2953,6 @@ class GraphForm(DateTimeWithNumRunsWithDagRunsForm): "airflow/graph.html", dag=dag, form=form, - width=request.args.get("width", "100%"), - height=request.args.get("height", "800"), dag_run_id=dag_run_id, execution_date=dttm.isoformat(), state_token=wwwutils.state_token(dt_nr_dr_data["dr_state"]), From 8e6127afaa2a3c6d0d80acce264d00e2240dbf2a Mon Sep 17 00:00:00 2001 From: Qian Yu Date: Wed, 8 Mar 2023 14:53:10 +0800 Subject: [PATCH 2/5] rebase --- airflow/www/static/js/graph.js | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/airflow/www/static/js/graph.js b/airflow/www/static/js/graph.js index 28b592cc527dc..45e6fe3147bfd 100644 --- a/airflow/www/static/js/graph.js +++ b/airflow/www/static/js/graph.js @@ -275,12 +275,7 @@ function setUpZoomSupport() { // Calculate applicable scale for zoom const zoomScale = Math.min( Math.min(width / graphWidth, height / graphHeight), -<<<<<<< HEAD - 1.5 // cap zoom level to 1.5 so nodes are not too large - ); -======= ) * 0.8; ->>>>>>> fd8b161fa1 (Center clicked node around mouse) zoom.translate([width / 2 - (graphWidth * zoomScale) / 2 + padding, padding]); zoom.scale(zoomScale); @@ -374,24 +369,7 @@ d3.select("#searchbox").on("keyup", () => { // This moves the matched node to the center of the graph area if (match) { -<<<<<<< HEAD - const transform = d3.transform(d3.select(match).attr("transform")); - - const svgBb = svg.node().getBoundingClientRect(); - transform.translate = [ - svgBb.width / 2 - transform.translate[0], - svgBb.height / 2 - transform.translate[1], - ]; - transform.scale = [1, 1]; - - if (zoom != null) { - zoom.translate(transform.translate); - zoom.scale(1); - zoom.event(innerSvg); - } -======= focusGroup(match.id, false); ->>>>>>> fd8b161fa1 (Center clicked node around mouse) } }); From ca18d30b55a6afc3da0f7cc3357130f846fbab3a Mon Sep 17 00:00:00 2001 From: Qian Yu Date: Wed, 8 Mar 2023 15:59:14 +0800 Subject: [PATCH 3/5] revert redundant change --- airflow/example_dags/example_task_group.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/airflow/example_dags/example_task_group.py b/airflow/example_dags/example_task_group.py index 87a9ca601b38c..9d7a9f2e74d59 100644 --- a/airflow/example_dags/example_task_group.py +++ b/airflow/example_dags/example_task_group.py @@ -35,13 +35,12 @@ start = EmptyOperator(task_id="start") # [START howto_task_group_section_1] - for i in range(10): - with TaskGroup(f"section_a_{i}", tooltip=f"Tasks for section_{i}") as section_1: - task_1 = EmptyOperator(task_id="task_1") - task_2 = BashOperator(task_id="task_2", bash_command="echo 1") - task_3 = EmptyOperator(task_id="task_3") + with TaskGroup("section_1", tooltip="Tasks for section_1") as section_1: + task_1 = EmptyOperator(task_id="task_1") + task_2 = BashOperator(task_id="task_2", bash_command="echo 1") + task_3 = EmptyOperator(task_id="task_3") - task_1 >> [task_2, task_3] + task_1 >> [task_2, task_3] # [END howto_task_group_section_1] # [START howto_task_group_section_2] From e8619c21a9bb5ab21cab538e4c5ccd05bd103116 Mon Sep 17 00:00:00 2001 From: Qian Yu Date: Thu, 9 Mar 2023 08:07:15 +0800 Subject: [PATCH 4/5] Fix unused variable --- airflow/www/static/js/graph.js | 1 - 1 file changed, 1 deletion(-) diff --git a/airflow/www/static/js/graph.js b/airflow/www/static/js/graph.js index 45e6fe3147bfd..0d91acd64b2d9 100644 --- a/airflow/www/static/js/graph.js +++ b/airflow/www/static/js/graph.js @@ -47,7 +47,6 @@ const getTaskInstanceURL = `${taskInstancesUrl}?dag_id=${encodeURIComponent( dagId )}&execution_date=${encodeURIComponent(executionDate)}`; -const duration = 500; const stateFocusMap = { success: false, running: false, From 16e5b4eacf676f70a818930645a8607c80deacc8 Mon Sep 17 00:00:00 2001 From: Qian Yu Date: Thu, 9 Mar 2023 09:17:05 +0800 Subject: [PATCH 5/5] pre-commit --- airflow/www/static/js/graph.js | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/airflow/www/static/js/graph.js b/airflow/www/static/js/graph.js index 0d91acd64b2d9..c58acef761cbd 100644 --- a/airflow/www/static/js/graph.js +++ b/airflow/www/static/js/graph.js @@ -268,13 +268,12 @@ function setUpZoomSupport() { // Get Dagre Graph dimensions const graphWidth = g.graph().width; const graphHeight = g.graph().height; - const {width, height} = svg.node().viewBox.animVal; + const { width, height } = svg.node().viewBox.animVal; const padding = width * 0.05; // Calculate applicable scale for zoom - const zoomScale = Math.min( - Math.min(width / graphWidth, height / graphHeight), - ) * 0.8; + const zoomScale = + Math.min(Math.min(width / graphWidth, height / graphHeight)) * 0.8; zoom.translate([width / 2 - (graphWidth * zoomScale) / 2 + padding, padding]); zoom.scale(zoomScale); @@ -638,11 +637,11 @@ function focusedGroupKey() { } // Focus the graph on the expanded/collapsed node -function focusGroup(nodeId, followMouse=true) { +function focusGroup(nodeId, followMouse = true) { if (nodeId != null && zoom != null) { const { x, y } = g.node(nodeId); // This is the total canvas size. - const {width, height} = svg.node().viewBox.animVal; + const { width, height } = svg.node().viewBox.animVal; // This is the size of the node or the cluster (i.e. group) let rect = d3 @@ -664,14 +663,16 @@ function focusGroup(nodeId, followMouse=true) { ]; // Calculate zoom scale to fill most of the canvas with the node/cluster in focus. - const scale = Math.min( - Math.min(width / nodeWidth, height / nodeHeight), 1 - ) * 0.2; - + const scale = + Math.min(Math.min(width / nodeWidth, height / nodeHeight), 1) * 0.2; + // Move the graph so that the node that was expanded/collapsed is centered around // the mouse click. const [toX, toY] = followMouse ? [mouseX, mouseY] : [width / 2, height / 5]; - const [deltaX, deltaY] = [toX - x * scale, toY + (nodeHeight / 2 - y) * scale]; + const [deltaX, deltaY] = [ + toX - x * scale, + toY + (nodeHeight / 2 - y) * scale, + ]; zoom.translate([deltaX, deltaY]); zoom.scale(scale); zoom.event(innerSvg);