You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by ya...@apache.org on 2023/09/13 01:51:10 UTC

[spark] branch master updated: [SPARK-45120][UI] Upgrade d3 from v3 to v7(v7.8.5) and apply api changes in UI

This is an automated email from the ASF dual-hosted git repository.

yao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new 4221235a6b2 [SPARK-45120][UI] Upgrade d3 from v3 to v7(v7.8.5) and apply api changes in UI
4221235a6b2 is described below

commit 4221235a6b2742a42e63f143a62191f94ae05ed8
Author: Kent Yao <ya...@apache.org>
AuthorDate: Wed Sep 13 09:50:54 2023 +0800

    [SPARK-45120][UI] Upgrade d3 from v3 to v7(v7.8.5) and apply api changes in UI
    
    ### What changes were proposed in this pull request?
    
    This PR upgrades d3 from v3 to v7(v7.8.5).
    
    This PR also applies the API changes to our UI drawing. The related changes are listed below:
    
    - d3.svg.line -> d3.line
    - ~~d3.transfrom~~
    - d3.layout.histogram -> d3.histogram() -> d3.bin()
      - d.x -> d.x0
      - d.dx -> d.x1 - d.x0
      - d.y -> d.length
    - d3.scale.linear() -> d3.scaleLinear
    - d3.svg.axis and axis.orient -> d3.axisTop, d3.axisRight, d3.axisBottom, d3.axisLeft
      - d3.svg.axis().scale(x).orient("bottom") -> d3.axisBottom
    - d3.time.format -> d3.timeFormat
    - d3.layout.stack ↦ d3.stack
    - d3.scale.ordinal ↦ d3.scaleOrdinal
    - d3.mouse -> d3.pointer
      - selection.on("mousemove", function(d) {
        … do something with d3.event and d…
      })
      - becomes:
    
      - selection.on("mousemove", function(event, d) {
        … do something with event and d …
      })
    - svg.selectAll("g rect")[0] -> svg.selectAll("g rect").nodes()
    
    Most of these changes come from v4 and v6, a full list of changes can be found at https://github.com/d3/d3/blob/main/CHANGES.md
    
    ### Why are the changes needed?
    
    d3 v3 is very old(Feb 11, 2015), deprecated by some of its downstream that we depends on
    
    ### Does this PR introduce _any_ user-facing change?
    
    no
    
    ### How was this patch tested?
    
    This PR was locally tested with `org.apache.spark.examples.streaming.SqlNetworkWordCount`
    
    #### Streaming page loading
    
    ![image](https://github.com/apache/spark/assets/8326978/d688b9a7-4e14-42de-a28c-9d81a96bc4d5)
    
    #### SQL page loading
    
    ![image](https://github.com/apache/spark/assets/8326978/a1cac4e8-8f1f-480e-a0ac-359cbcfefaee)
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    no
    
    Closes #42879 from yaooqinn/SPARK-45120.
    
    Authored-by: Kent Yao <ya...@apache.org>
    Signed-off-by: Kent Yao <ya...@apache.org>
---
 LICENSE                                            |  6 ++-
 LICENSE-binary                                     |  6 ++-
 .../resources/org/apache/spark/ui/static/d3.min.js |  7 +---
 .../org/apache/spark/ui/static/spark-dag-viz.js    |  6 +--
 .../org/apache/spark/ui/static/streaming-page.js   | 48 ++++++++++++----------
 .../spark/ui/static/structured-streaming-page.js   | 31 ++++++--------
 licenses-binary/LICENSE-d3.min.js.txt              | 39 ++++++------------
 licenses/LICENSE-d3.min.js.txt                     | 39 ++++++------------
 .../spark/sql/execution/ui/static/spark-sql-viz.js |  4 +-
 9 files changed, 81 insertions(+), 105 deletions(-)

diff --git a/LICENSE b/LICENSE
index 1735d3208f2..3fee963db74 100644
--- a/LICENSE
+++ b/LICENSE
@@ -229,7 +229,6 @@ BSD 3-Clause
 python/lib/py4j-*-src.zip
 python/pyspark/cloudpickle/*.py
 python/pyspark/join.py
-core/src/main/resources/org/apache/spark/ui/static/d3.min.js
 
 The CSS style for the navigation sidebar of the documentation was originally
 submitted by Óscar Nájera for the scikit-learn project. The scikit-learn project
@@ -248,6 +247,11 @@ docs/js/vendor/anchor.min.js
 docs/js/vendor/jquery*
 docs/js/vendor/modernizer*
 
+ISC License
+-----------
+
+core/src/main/resources/org/apache/spark/ui/static/d3.min.js
+
 
 Creative Commons CC0 1.0 Universal Public Domain Dedication
 -----------------------------------------------------------
diff --git a/LICENSE-binary b/LICENSE-binary
index 05645977a0b..900b6461106 100644
--- a/LICENSE-binary
+++ b/LICENSE-binary
@@ -461,7 +461,6 @@ org.jdom:jdom2
 python/lib/py4j-*-src.zip
 python/pyspark/cloudpickle.py
 python/pyspark/join.py
-core/src/main/resources/org/apache/spark/ui/static/d3.min.js
 
 The CSS style for the navigation sidebar of the documentation was originally
 submitted by Óscar Nájera for the scikit-learn project. The scikit-learn project
@@ -498,6 +497,11 @@ docs/js/vendor/anchor.min.js
 docs/js/vendor/jquery*
 docs/js/vendor/modernizer*
 
+ISC License
+-----------
+
+core/src/main/resources/org/apache/spark/ui/static/d3.min.js
+
 
 Common Development and Distribution License (CDDL) 1.0
 ------------------------------------------------------
diff --git a/core/src/main/resources/org/apache/spark/ui/static/d3.min.js b/core/src/main/resources/org/apache/spark/ui/static/d3.min.js
index 30cd292198b..8d56002d90f 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/d3.min.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/d3.min.js
@@ -1,5 +1,2 @@
-/*v3.5.5*/!function(){function n(n){return n&&(n.ownerDocument||n.document||n).documentElement}function t(n){return n&&(n.ownerDocument&&n.ownerDocument.defaultView||n.document&&n||n.defaultView)}function e(n,t){return t>n?-1:n>t?1:n>=t?0:0/0}function r(n){return null===n?0/0:+n}function u(n){return!isNaN(n)}function i(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)<0?r=i+1:u=i}return r},right:function(t,e,r,u) [...]
-},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,l,s,f,h,g,p,v,d,m){var y=s-t,M=f-e,x=y*y+M*M;if(x>4*i&&d--){var b=a+g,_=c+p,w=l+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),E=ga(ga(w)-1)<Ca||ga(r-h)<Ca?(r+h)/2:Math.atan2(_,b),A=n(E,k),N=A[0],C=A[1],z=N-t,q=C-e,L=M*z-y*q;(L*L/x>i||ga((y*z+M*q)/x-.5)>.3||o>a*g+c*p+l*v)&&(u(t,e,r,a,c,l,N,C,E,b/=S,_/=S,w,d,m),m.point(N,C),u(N,C,E,b,_,w,s,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Da),a=16;return t.precision= [...]
-},t.y=function(n){return arguments.length?(u=i=n,t):i},t.y0=function(n){return arguments.length?(u=n,t):u},t.y1=function(n){return arguments.length?(i=n,t):i},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(c="function"==typeof n?a=n:(a=El.get(n)||go).key,l=a.reverse||a,s=a.closed?"M":"L",t):c},t.tension=function(n){return arguments.length?(f=n,t):f},t}function Po(n){return n.radius}function Uo(n){return[n.x,n.y]}function jo(n){ [...]
-},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var pc=new ce;ta.geo.stream=function(n,t){n&&vc.hasOwnProperty(n.type)?vc[n.type](n,t):se(n,t)};var vc={Feature:function(n,t){se(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++r<u;)se(e[r].geometry,t)}},dc={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)n=e[r],t. [...]
-return i.size=function(n){return arguments.length?(l=n,i):l},i.padding=function(n){function t(t){var e=n.call(i,t,t.depth);return null==e?Ri(t):Di(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return Di(t,n)}if(!arguments.length)return s;var r;return f=null==(s=n)?Ri:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,i},i.round=function(n){return arguments.length?(c=n?Math.round:Number,i):c!=Number},i.sticky=function(n){return arguments.length?(h=n,o=null,i):h},i.ratio=function( [...]
+// https://d3js.org v7.8.5 Copyright 2010-2023 Mike Bostock
+!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).d3=t.d3||{})}(this,(function(t){"use strict";function n(t,n){return null==t||null==n?NaN:t<n?-1:t>n?1:t>=n?0:NaN}function e(t,n){return null==t||null==n?NaN:n<t?-1:n>t?1:n>=t?0:NaN}function r(t){let r,o,a;function u(t,n,e=0,i=t.length){if(e<i){if(0!==r(n,n))return i;do{const r=e+i>>>1;o(t[r],n)<0 [...]
diff --git a/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js b/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js
index 6a0cd012146..137d68c93d4 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/spark-dag-viz.js
@@ -346,7 +346,7 @@ function preprocessGraphLayout(g, forJob) {
  * This assumes that all outermost elements are clusters (rectangles).
  */
 function resizeSvg(svg) {
-  var allClusters = svg.selectAll("g.cluster rect")[0];
+  var allClusters = svg.selectAll("g.cluster rect").nodes();
   var startX = -VizConstants.svgMarginX +
     toFloat(d3.min(allClusters, function(e) {
       return getAbsolutePosition(d3.select(e)).x;
@@ -433,7 +433,7 @@ function getAbsolutePosition(d3selection) {
   while (!obj.empty()) {
     var transformText = obj.attr("transform");
     if (transformText) {
-      var translate = d3.transform(transformText).translate;
+      var translate = transformText.substring("translate(".length, transformText.length - 1).split(",")
       _x += toFloat(translate[0]);
       _y += toFloat(translate[1]);
     }
@@ -497,7 +497,7 @@ function connectRDDs(fromRDDId, toRDDId, edgesContainer, svgContainer) {
     ];
   }
 
-  var line = d3.svg.line().interpolate("basis");
+  var line = d3.line().interpolate("basis");
   edgesContainer.append("path").datum(points).attr("d", line);
 }
 
diff --git a/core/src/main/resources/org/apache/spark/ui/static/streaming-page.js b/core/src/main/resources/org/apache/spark/ui/static/streaming-page.js
index 9f366025a8b..62e65ac9a76 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/streaming-page.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/streaming-page.js
@@ -100,16 +100,15 @@ function registerTimeline(minY, maxY) {
 // Register a histogram graph. All histogram graphs should be register before calling any
 // "drawHistogram" so that we can determine the max X value for histograms.
 function registerHistogram(values, minY, maxY) {
-  var data = d3.layout.histogram().range([minY, maxY]).bins(histogramBinCount)(values);
-  // d.x is the y values while d.y is the x values
-  var maxX = d3.max(data, function(d) { return d.y; });
+  var data = d3.bin().domain([minY, maxY]).thresholds(histogramBinCount)(values);
+  var maxX = d3.max(data, (d) => d.length);
   maxXForHistogram = maxX > maxXForHistogram ? maxX : maxXForHistogram;
 }
 /* eslint-enable no-unused-vars */
 
 // Draw a line between (x1, y1) and (x2, y2)
 function drawLine(svg, xFunc, yFunc, x1, y1, x2, y2) {
-  var line = d3.svg.line()
+  var line = d3.line()
     .x(function(d) { return xFunc(d.x); })
     .y(function(d) { return yFunc(d.y); });
   var data = [{x: x1, y: y1}, {x: x2, y: y2}];
@@ -141,10 +140,10 @@ function drawTimeline(id, data, minX, maxX, minY, maxY, unitY, batchInterval) {
   var width = 500 - margin.left - margin.right;
   var height = 150 - margin.top - margin.bottom;
 
-  var x = d3.scale.linear().domain([minX, maxX]).range([0, width]);
-  var y = d3.scale.linear().domain([minY, maxY]).range([height, 0]);
+  var x = d3.scaleLinear().domain([minX, maxX]).range([0, width]);
+  var y = d3.scaleLinear().domain([minY, maxY]).range([height, 0]);
 
-  var xAxis = d3.svg.axis().scale(x).orient("bottom").tickFormat(function(d) {
+  var xAxis = d3.axisBottom(x).tickFormat(function(d) {
     var formattedDate = timeFormat[d];
     var dotIndex = formattedDate.indexOf('.');
     if (dotIndex >= 0) {
@@ -154,10 +153,9 @@ function drawTimeline(id, data, minX, maxX, minY, maxY, unitY, batchInterval) {
       return formattedDate;
     }
   });
-  var formatYValue = d3.format(",.2f");
-  var yAxis = d3.svg.axis().scale(y).orient("left").ticks(5).tickFormat(formatYValue);
+  var yAxis = d3.axisLeft(y).ticks(5).tickFormat(yValueFormat);
 
-  var line = d3.svg.line()
+  var line = d3.line()
     .x(function(d) { return x(d.x); })
     .y(function(d) { return y(d.y); });
 
@@ -213,7 +211,7 @@ function drawTimeline(id, data, minX, maxX, minY, maxY, unitY, batchInterval) {
     .attr("cy", function(d) { return y(d.y); })
     .attr("r", function(d) { return isFailedBatch(d.x) ? "2" : "3";})
     .on('mouseover', function(d) {
-      var tip = formatYValue(d.y) + " " + unitY + " at " + timeTipStrings[d.x];
+      var tip = yValueFormat(d.y) + " " + unitY + " at " + timeTipStrings[d.x];
       showBootstrapTooltip(d3.select(this).node(), tip);
       // show the point
       d3.select(this)
@@ -252,13 +250,19 @@ function drawHistogram(id, values, minY, maxY, unitY, batchInterval) {
   var width = 350 - margin.left - margin.right;
   var height = 150 - margin.top - margin.bottom;
 
-  var x = d3.scale.linear().domain([0, maxXForHistogram]).range([0, width - 50]);
-  var y = d3.scale.linear().domain([minY, maxY]).range([height, 0]);
+  var x = d3
+    .scaleLinear()
+    .domain([0, maxXForHistogram])
+    .range([0, width - 50]);
+  var y = d3
+    .scaleLinear()
+    .domain([minY, maxY])
+    .range([height, 0]);
 
-  var xAxis = d3.svg.axis().scale(x).orient("top").ticks(5);
-  var yAxis = d3.svg.axis().scale(y).orient("left").ticks(0).tickFormat(function(d) { return ""; });
+  var xAxis = d3.axisTop(x).ticks(5);
+  var yAxis = d3.axisLeft(y).ticks(0).tickFormat(function(d) { return ""; });
 
-  var data = d3.layout.histogram().range([minY, maxY]).bins(histogramBinCount)(values);
+  var data = d3.bin().domain([minY, maxY]).thresholds(histogramBinCount)(values);
 
   var svg = d3.select(id).append("svg")
     .attr("width", width + margin.left + margin.right)
@@ -285,13 +289,13 @@ function drawHistogram(id, values, minY, maxY, unitY, batchInterval) {
     .data(data)
     .enter()
     .append("g")
-    .attr("transform", function(d) { return "translate(0," + (y(d.x) - height + y(d.dx))  + ")";})
+    .attr("transform", (d, i) => "translate(0," + (height - (i + 1) * (y(d.x0) - y(d.x1))) + ")")
     .attr("class", "bar").append("rect")
-    .attr("width", function(d) { return x(d.y); })
-    .attr("height", function(d) { return height - y(d.dx); })
-    .on('mouseover', function(d) {
-      var percent = yValueFormat(d.y * 100.0 / values.length) + "%";
-      var tip = d.y + " batches (" + percent + ") between " + yValueFormat(d.x) + " and " + yValueFormat(d.x + d.dx) + " " + unitY;
+    .attr("width", (d) => x(d.length))
+    .attr("height", (d) => y(d.x0) - y(d.x1))
+    .on('mouseover', function(event, d) {
+      var percent = yValueFormat(d.length / values.length) + "%";
+      var tip = d.length + " batches (" + percent + ") between " + yValueFormat(d.x0) + " and " + yValueFormat(d.x1) + " " + unitY;
       showBootstrapTooltip(d3.select(this).node(), tip);
     })
     .on('mouseout',  function() {
diff --git a/core/src/main/resources/org/apache/spark/ui/static/structured-streaming-page.js b/core/src/main/resources/org/apache/spark/ui/static/structured-streaming-page.js
index 9701f5a57e1..08b37a246b4 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/structured-streaming-page.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/structured-streaming-page.js
@@ -39,37 +39,30 @@ function drawAreaStack(id, labels, values, minX, maxX, minY, maxY) {
 
   var data = values;
 
-  var parse = d3.time.format("%H:%M:%S.%L").parse;
+  var parse = d3.timeParse("%H:%M:%S.%L");
 
   // Transpose the data into layers
-  var dataset = d3.layout.stack()(labels.map(function(fruit) {
+  var dataset = d3.stack()(labels.map(function(fruit) {
     return data.map(function(d) {
       return {_x: d.x, x: parse(d.x), y: +d[fruit]};
     });
   }));
 
   // Set x, y and colors
-  var x = d3.scale.ordinal()
+  var x = d3.scaleOrdinal()
     .domain(dataset[0].map(function(d) { return d.x; }))
     .rangeRoundBands([10, width-10], 0.02);
 
-  var y = d3.scale.linear()
+  var y = d3.scaleLinear()
     .domain([0, d3.max(dataset, function(d) {  return d3.max(d, function(d) { return d.y0 + d.y; });  })])
     .range([height, 0]);
 
   var colors = colorPool.slice(0, labels.length);
 
   // Define and draw axes
-  var yAxis = d3.svg.axis()
-    .scale(y)
-    .orient("left")
-    .ticks(7)
-    .tickFormat( function(d) { return d } );
+  var yAxis = d3.axisLeft(y).ticks(7).tickFormat( function(d) { return d } );
 
-  var xAxis = d3.svg.axis()
-    .scale(x)
-    .orient("bottom")
-    .tickFormat(d3.time.format("%H:%M:%S.%L"));
+  var xAxis = d3.axisBottom(x).tickFormat(d3.timeFormat("%H:%M:%S.%L"));
 
   // Only show the first and last time in the graph
   var xline = [];
@@ -118,9 +111,9 @@ function drawAreaStack(id, labels, values, minX, maxX, minY, maxY) {
     .on('mouseout',  function() {
       hideBootstrapTooltip(d3.select(this).node());
     })
-    .on("mousemove", function(d) {
-      var xPosition = d3.mouse(this)[0] - 15;
-      var yPosition = d3.mouse(this)[1] - 25;
+    .on("mousemove", (event, d) => {
+      var xPosition = d3.pointer(event)[0] - 15;
+      var yPosition = d3.pointer(event)[1] - 25;
       tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")");
       tooltip.select("text").text(d.y);
     });
@@ -144,9 +137,9 @@ function drawAreaStack(id, labels, values, minX, maxX, minY, maxY) {
     .on('mouseout',  function() {
       hideBootstrapTooltip(d3.select(this).node());
     })
-    .on("mousemove", function(d) {
-      var xPosition = d3.mouse(this)[0] - 15;
-      var yPosition = d3.mouse(this)[1] - 25;
+    .on("mousemove", (event, d) => {
+      var xPosition = d3.pointer(event)[0] - 15;
+      var yPosition = d3.pointer(event)[1] - 25;
       tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")");
       tooltip.select("text").text(d.y);
     });
diff --git a/licenses-binary/LICENSE-d3.min.js.txt b/licenses-binary/LICENSE-d3.min.js.txt
index c71e3f254c0..3594fffaf63 100644
--- a/licenses-binary/LICENSE-d3.min.js.txt
+++ b/licenses-binary/LICENSE-d3.min.js.txt
@@ -1,26 +1,13 @@
-Copyright (c) 2010-2015, Michael Bostock
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
-  this list of conditions and the following disclaimer in the documentation
-  and/or other materials provided with the distribution.
-
-* The name Michael Bostock may not be used to endorse or promote products
-  derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
+Copyright 2010-2023 Mike Bostock
+
+Permission to use, copy, modify, and/or distribute this software for any purpose
+with or without fee is hereby granted, provided that the above copyright notice
+and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
diff --git a/licenses/LICENSE-d3.min.js.txt b/licenses/LICENSE-d3.min.js.txt
index c71e3f254c0..3594fffaf63 100644
--- a/licenses/LICENSE-d3.min.js.txt
+++ b/licenses/LICENSE-d3.min.js.txt
@@ -1,26 +1,13 @@
-Copyright (c) 2010-2015, Michael Bostock
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
-  this list of conditions and the following disclaimer in the documentation
-  and/or other materials provided with the distribution.
-
-* The name Michael Bostock may not be used to endorse or promote products
-  derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
+Copyright 2010-2023 Mike Bostock
+
+Permission to use, copy, modify, and/or distribute this software for any purpose
+with or without fee is hereby granted, provided that the above copyright notice
+and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
diff --git a/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.js b/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.js
index d1def1b0a42..1847fd5f3ef 100644
--- a/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.js
+++ b/sql/core/src/main/resources/org/apache/spark/sql/execution/ui/static/spark-sql-viz.js
@@ -121,7 +121,7 @@ function preprocessGraphLayout(g) {
  * This assumes that all outermost elements are clusters (rectangles).
  */
 function resizeSvg(svg) {
-  var allClusters = svg.selectAll("g rect")[0];
+  var allClusters = svg.selectAll("g rect").nodes();
   var startX = -PlanVizConstants.svgMarginX +
     toFloat(d3.min(allClusters, function(e) {
       return getAbsolutePosition(d3.select(e)).x;
@@ -169,7 +169,7 @@ function getAbsolutePosition(d3selection) {
   while (!obj.empty()) {
     var transformText = obj.attr("transform");
     if (transformText) {
-      var translate = d3.transform(transformText).translate;
+      var translate = transformText.substring("translate(".length, transformText.length - 1).split(",")
       _x += toFloat(translate[0]);
       _y += toFloat(translate[1]);
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org