mirror of
https://github.com/apache/superset.git
synced 2026-04-24 02:25:13 +00:00
refactor(monorepo): move superset-ui to superset(stage 2) (#17552)
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
/* eslint-disable react/sort-prop-types, func-names, no-param-reassign */
|
||||
import d3 from 'd3';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const propTypes = {
|
||||
data: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
source: PropTypes.string,
|
||||
target: PropTypes.string,
|
||||
value: PropTypes.number,
|
||||
}),
|
||||
),
|
||||
width: PropTypes.number,
|
||||
height: PropTypes.number,
|
||||
linkLength: PropTypes.number,
|
||||
charge: PropTypes.number,
|
||||
};
|
||||
|
||||
/* Modified from http://bl.ocks.org/d3noob/5141278 */
|
||||
function ForceDirected(element, props) {
|
||||
const { data, width, height, linkLength = 200, charge = -500 } = props;
|
||||
const div = d3.select(element);
|
||||
div.classed('superset-legacy-chart-force-directed', true);
|
||||
|
||||
const links = data;
|
||||
const nodes = {};
|
||||
// Compute the distinct nodes from the links.
|
||||
links.forEach(link => {
|
||||
link.source =
|
||||
nodes[link.source] ||
|
||||
(nodes[link.source] = {
|
||||
name: link.source,
|
||||
});
|
||||
link.target =
|
||||
nodes[link.target] ||
|
||||
(nodes[link.target] = {
|
||||
name: link.target,
|
||||
});
|
||||
link.value = Number(link.value);
|
||||
|
||||
const targetName = link.target.name;
|
||||
const sourceName = link.source.name;
|
||||
|
||||
if (nodes[targetName].total === undefined) {
|
||||
nodes[targetName].total = link.value;
|
||||
}
|
||||
if (nodes[sourceName].total === undefined) {
|
||||
nodes[sourceName].total = 0;
|
||||
}
|
||||
if (nodes[targetName].max === undefined) {
|
||||
nodes[targetName].max = 0;
|
||||
}
|
||||
if (link.value > nodes[targetName].max) {
|
||||
nodes[targetName].max = link.value;
|
||||
}
|
||||
if (nodes[targetName].min === undefined) {
|
||||
nodes[targetName].min = 0;
|
||||
}
|
||||
if (link.value > nodes[targetName].min) {
|
||||
nodes[targetName].min = link.value;
|
||||
}
|
||||
|
||||
nodes[targetName].total += link.value;
|
||||
});
|
||||
|
||||
/* eslint-disable no-use-before-define */
|
||||
// add the curvy lines
|
||||
function tick() {
|
||||
path.attr('d', d => {
|
||||
const dx = d.target.x - d.source.x;
|
||||
const dy = d.target.y - d.source.y;
|
||||
const dr = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
return `M${d.source.x},${d.source.y}A${dr},${dr} 0 0,1 ${d.target.x},${d.target.y}`;
|
||||
});
|
||||
|
||||
node.attr('transform', d => `translate(${d.x},${d.y})`);
|
||||
}
|
||||
/* eslint-enable no-use-before-define */
|
||||
|
||||
const force = d3.layout
|
||||
.force()
|
||||
.nodes(d3.values(nodes))
|
||||
.links(links)
|
||||
.size([width, height])
|
||||
.linkDistance(linkLength)
|
||||
.charge(charge)
|
||||
.on('tick', tick)
|
||||
.start();
|
||||
|
||||
div.selectAll('*').remove();
|
||||
const svg = div.append('svg').attr('width', width).attr('height', height);
|
||||
|
||||
// build the arrow.
|
||||
svg
|
||||
.append('svg:defs')
|
||||
.selectAll('marker')
|
||||
.data(['end']) // Different link/path types can be defined here
|
||||
.enter()
|
||||
.append('svg:marker') // This section adds in the arrows
|
||||
.attr('id', String)
|
||||
.attr('viewBox', '0 -5 10 10')
|
||||
.attr('refX', 15)
|
||||
.attr('refY', -1.5)
|
||||
.attr('markerWidth', 6)
|
||||
.attr('markerHeight', 6)
|
||||
.attr('orient', 'auto')
|
||||
.append('svg:path')
|
||||
.attr('d', 'M0,-5L10,0L0,5');
|
||||
|
||||
const edgeScale = d3.scale.linear().range([0.1, 0.5]);
|
||||
// add the links and the arrows
|
||||
const path = svg
|
||||
.append('svg:g')
|
||||
.selectAll('path')
|
||||
.data(force.links())
|
||||
.enter()
|
||||
.append('svg:path')
|
||||
.attr('class', 'link')
|
||||
.style('opacity', d => edgeScale(d.value / d.target.max))
|
||||
.attr('marker-end', 'url(#end)');
|
||||
|
||||
// define the nodes
|
||||
const node = svg
|
||||
.selectAll('.node')
|
||||
.data(force.nodes())
|
||||
.enter()
|
||||
.append('g')
|
||||
.attr('class', 'node')
|
||||
.on('mouseenter', function () {
|
||||
d3.select(this).select('circle').transition().style('stroke-width', 5);
|
||||
|
||||
d3.select(this).select('text').transition().style('font-size', 25);
|
||||
})
|
||||
.on('mouseleave', function () {
|
||||
d3.select(this).select('circle').transition().style('stroke-width', 1.5);
|
||||
d3.select(this).select('text').transition().style('font-size', 12);
|
||||
})
|
||||
.call(force.drag);
|
||||
|
||||
// add the nodes
|
||||
const ext = d3.extent(d3.values(nodes), d => Math.sqrt(d.total));
|
||||
const circleScale = d3.scale.linear().domain(ext).range([3, 30]);
|
||||
|
||||
node.append('circle').attr('r', d => circleScale(Math.sqrt(d.total)));
|
||||
|
||||
// add the text
|
||||
node
|
||||
.append('text')
|
||||
.attr('x', 6)
|
||||
.attr('dy', '.35em')
|
||||
.text(d => d.name);
|
||||
}
|
||||
|
||||
ForceDirected.displayName = 'ForceDirected';
|
||||
ForceDirected.propTypes = propTypes;
|
||||
|
||||
export default ForceDirected;
|
||||
Reference in New Issue
Block a user