977 lines
30 KiB
JavaScript

import Route from '@ember/routing/route';
import { scheduleOnce } from '@ember/runloop';
import _ from 'lodash';
import $ from 'jquery';
const d3 = window.d3;
let rotation = false;
let ZOOM_DURATION = 2000;
let g_upLevel = 1;
let g_downLevel = 1;
let $field;
let $results;
function setupSearch({ lineageType, lineageId }) {
const height = $(window).height() * 0.99;
$('#graphSplitter').height(height * 0.6);
$('#nodeInfoSplitter')
.height(height * 0.4)
.tabs({ active: 0 });
$('#main-splitter')
.height(height)
.splitter({
type: 'h',
dock: 'bottom',
dockSpeed: 200,
dockKey: 'W',
accessKey: 'W',
sizeTop: true
});
refreshLineageData(lineageType, lineageId);
$('#rotationgraphbtn').on('click', function() {
if (window.g_currentData) {
rotation = !rotation;
setupDagreGraph(window.g_currentData, rotation, lineageType);
}
});
$('#uplevelbtn').on('click', function() {
g_upLevel++;
refreshLineageData(lineageType, lineageId);
});
$('#downlevelbtn').on('click', function() {
g_downLevel++;
refreshLineageData(lineageType, lineageId);
});
}
function refreshLineageData(type, id) {
let application = $('#application').val();
if (application) {
application = application.replace(/\./g, ' ');
}
let project = $('#project').val();
let flow = $('#flow').val();
let url = '';
if (type === 'chains') {
url = 'api/v1/lineage/chains';
$('#chainComboBox').on('change', function() {
var items = $('#chainComboBox').jqxComboBox('getSelectedItems');
var names = '';
$.each(items, function(index) {
names = names + this.label;
if (items.length - 1 !== index) {
names += ',';
}
});
if (names) {
var dataUrl = 'api/v1/lineage/appworxflow/' + names;
$('#loading').show();
$.get(dataUrl, function(data) {
if (data && data.status === 'ok') {
$('#loading').hide();
renderTables(data.data);
window.g_currentData = data.data;
setupDagreGraph(data.data, rotation, type);
$('#nodeInfoTab a:first').tab('show');
}
});
}
});
$('#loading').show();
$.get(url, function(data) {
if (data && data.status === 'ok') {
$('#chainComboBox').jqxComboBox({ source: data.chains, multiSelect: true, width: 450, height: 25 });
$('#chainComboBox').jqxComboBox('selectItem', 'TAGG_PV_PAGE_STATS');
}
$('#loading').hide();
});
} else if (type === 'dataset') {
url = '/api/v1/lineage/dataset/' + id + '?upLevel=' + g_upLevel + '&downLevel=' + g_downLevel;
$('#loading').show();
$.get(url, function(data) {
if (data && data.status === 'ok') {
$('#loading').hide();
const $title = $('#title');
if ($title && data.data && data.data.urn) {
$title.text('Lineage for: ' + data.data.urn);
}
renderTables(data.data);
window.g_currentData = data.data;
setupDagreGraph(data.data, rotation, type);
$('#nodeInfoTab a:first').tab('show');
}
});
} else if (type === 'metric') {
url = '/api/v1/lineage/metric/' + id + '?upLevel=' + g_upLevel + '&downLevel=' + g_downLevel;
$('#loading').show();
$.get(url, function(data) {
if (data && data.status === 'ok') {
$('#loading').hide();
renderTables(data.data);
window.g_currentData = data.data;
setupDagreGraph(data.data, rotation, type);
$('#nodeInfoTab a:first').tab('show');
}
});
} else if (type === 'azkaban') {
url = '/api/v1/lineage/flow/' + application + '/' + project + '/' + flow;
$('#loading').show();
$.get(url, function(data) {
if (data && data.status === 'ok') {
$('#loading').hide();
var titleObj = $('#title');
if (titleObj && data.data && data.data.flowName) {
titleObj.text('Lineage for: ' + application + '/' + project + '/' + data.data.flowName);
}
renderTables(data.data);
window.g_currentData = data.data;
setupDagreGraph(data.data, rotation, type);
$('#nodeInfoTab a:first').tab('show');
}
});
} else if (type === 'appworx') {
url = '/api/v1/lineage/flow/' + application + '/' + project + '/' + flow;
$('#loading').show();
$.get(url, function(data) {
if (data && data.status === 'ok') {
$('#loading').hide();
var titleObj = $('#title');
if (titleObj && data.data && data.data.flowName) {
titleObj.text('Lineage for: ' + application + '/' + project + '/' + data.data.flowName);
}
renderTables(data.data);
window.g_currentData = data.data;
setupDagreGraph(data.data, rotation, type);
$('#nodeInfoTab a:first').tab('show');
}
});
}
}
function renderTables(data) {
var dataTable = $('#lineagedatatable');
var jobTable = $('#lineagejobtable');
dataTable.html('');
jobTable.html('');
var firstDataNode = false;
var firstJobNode = false;
if (dataTable && data) {
var nodes = data.nodes;
if (nodes) {
var dataHeader = '<thead>';
var dataBody = '<tbody>';
var jobHeader = '<thead>';
var jobBody = '<tbody>';
dataHeader += '<tr class="results-header wrap-all-word">';
jobHeader += '<tr class="results-header wrap-all-word">';
var dataHeaderNames = [];
var jobHeaderNames = [];
for (var i = 0; i < nodes.length; i++) {
dataBody += '<tr id="data-table-tr-' + nodes[i].id + '" class="result">';
jobBody += '<tr id="job-table-tr-' + nodes[i].id + '" class="result">';
if (nodes[i].node_type === 'data') {
if (!firstDataNode) {
if (nodes[i]['_sort_list']) {
$.each(nodes[i]['_sort_list'], function(k, v) {
dataHeader += '<th >' + v + '</th>';
dataHeaderNames.push(v);
if (nodes[i][v]) {
dataBody += '<td class="wrap-all-word">' + nodes[i][v] + '</td>';
} else {
dataBody += '<td class="wrap-all-word">' + '</td>';
}
});
}
firstDataNode = true;
} else {
for (var j = 0; j < dataHeaderNames.length; j++) {
if (nodes[i][dataHeaderNames[j]]) {
dataBody += '<td class="wrap-all-word">' + nodes[i][dataHeaderNames[j]] + '</td>';
} else {
dataBody += '<td class="wrap-all-word">' + '</td>';
}
}
}
} else if (nodes[i].node_type === 'script') {
if (!firstJobNode) {
if (nodes[i]['_sort_list']) {
$.each(nodes[i]['_sort_list'], function(k, v) {
jobHeader += '<th >' + v + '</th>';
jobHeaderNames.push(v);
if (nodes[i][v]) {
jobBody += '<td class="wrap-all-word">' + nodes[i][v] + '</td>';
} else {
jobBody += '<td class="wrap-all-word">' + '</td>';
}
});
}
firstJobNode = true;
} else {
for (var j = 0; j < jobHeaderNames.length; j++) {
if (nodes[i][jobHeaderNames[j]]) {
jobBody += '<td class="wrap-all-word">' + nodes[i][jobHeaderNames[j]] + '</td>';
} else {
jobBody += '<td class="wrap-all-word">' + '</td>';
}
}
}
}
dataBody += '</tr>';
jobBody += '</tr>';
}
dataBody += '</tbody>';
jobBody += '</tbody>';
dataHeader += '</tr>';
dataHeader += '</thead>';
jobHeader += '</tr>';
jobHeader += '</thead>';
dataTable.append(dataHeader);
dataTable.append(dataBody);
jobTable.append(jobHeader);
jobTable.append(jobBody);
}
}
}
function setViewport(scale, translation, duration) {
if (!duration || duration < 0) {
duration = 0;
}
d3
.select('.graph-attach g')
.transition()
.duration(duration)
.attr('transform', 'translate(' + translation[0] + ',' + translation[1] + ') scale(' + 1 + ')');
//renderer.setOriginalScale(1);
//minimapZoom(translation, 1);
}
function zoomTo(scale, focus, duration) {
var width = $('#svg-canvas').width();
var height = $('#svg-canvas').height();
var translation = [-(focus[0] * scale - width / 2), -(focus[1] * scale - height / 2)];
return setViewport(scale, translation, duration);
}
function setupDagreGraph(data, rotation, type) {
d3.select('svg').remove();
$('#canvas').html('<svg id="svg-canvas" width="1024"></svg>');
let width = $(window).width() * 0.99;
$('#svg-canvas').width(width);
$('#svg-canvas').height(($(window).height() * 0.99 - 82) * 0.6 - 40);
const $container = $('#controls');
$field = $container.find('.search-field');
$results = $('<ul/>', { class: 'search-results' }).appendTo($container);
$field.keydown(_.debounce(onFieldKeydown, 200));
$container.on('click', '.search-field, .search-submit, .search-clear', onSearchClick);
$results.on('focus', 'li', onResultFocus);
const SELECTED = 'result-selected';
const KEYCODES = { up: 38, down: 40, enter: 13, esc: 27 };
const MIN_QUERY_LENGTH = 3;
let resultNodes = {};
const selectedNodes = [];
function getSelectedNodeData() {
var selected = $results.children('.' + SELECTED).get();
return _.map(
selected,
function(el) {
var id = $(el).data('node-id');
return resultNodes[id];
},
this
);
}
function highlightNodesAndLinks(nodes = [], duration) {
const [graphNodes] = d3.selectAll('.node');
const [graphLinks = []] = d3.selectAll('.edgePath');
nodes.forEach(({ id: nodeId }) => {
graphLinks.forEach((graphLink = {}) => {
const { __data__: { v, w } = {} } = graphLink;
if (v) {
const node = window.g_currentData.nodes[nodeId];
const { sourceLinks = [], targetLinks = [] } = node;
sourceLinks.some(({ source, target }) => {
const match = v === source && w === target;
if (match) {
d3
.select(graphLink)
.transition()
.duration(ZOOM_DURATION)
.style('opacity', 1);
return match;
}
});
targetLinks.some(({ source, target }) => {
const match = v === source && w === target;
if (match) {
d3
.select(graphLink)
.transition()
.duration(ZOOM_DURATION)
.style('opacity', 1);
return match;
}
});
}
});
d3
.select(graphNodes[nodeId])
.transition()
.duration(duration)
.style('opacity', 1);
});
}
function zoomToNodes(nodes, duration) {
if (!nodes) {
return;
}
if (!_.isArray(nodes)) {
nodes = [nodes];
} // Allow passing a single node
if (!nodes.length) {
return;
}
if (nodes.length === 1) {
selectTabularRow(nodes[0].id, nodes[0].id);
}
maskGraph(duration);
var graphNodes = d3.selectAll('.node');
var graphLinks = d3.selectAll('.edgePath');
highlightNodesAndLinks(nodes, duration);
var padding = {
left: 40,
right: 80, // use more padding on bottom/right
top: 40,
bottom: 80 // accommodate node width and height
},
left =
_.min(
_.map(nodes, function(node) {
var n = graphNodes[0][node.id];
var transformIndex = 0;
for (i = 0; i < n.attributes.length; i++) {
if (n.attributes[i].name === 'transform') {
transformIndex = i;
break;
}
}
var index = n.attributes[transformIndex].value.indexOf(',');
var x = parseFloat(n.attributes[transformIndex].value.substring(10, index));
var y = parseFloat(
n.attributes[transformIndex].value.substring(index + 1, n.attributes[transformIndex].value.length - 1)
);
return x;
})
) - padding.left,
top =
_.min(
_.map(nodes, function(node) {
var n = graphNodes[0][node.id];
var transformIndex = 0;
for (i = 0; i < n.attributes.length; i++) {
if (n.attributes[i].name === 'transform') {
transformIndex = i;
break;
}
}
var index = n.attributes[transformIndex].value.indexOf(',');
var x = parseFloat(n.attributes[transformIndex].value.substring(10, index));
var y = parseFloat(
n.attributes[transformIndex].value.substring(index + 1, n.attributes[transformIndex].value.length - 1)
);
return y;
})
) - padding.top;
const groupCenter = [left, top];
return zoomTo(1, groupCenter, duration);
}
function focusOnNodes(nodes) {
deselectAll();
zoomToNodes(nodes, ZOOM_DURATION);
}
function onResultFocus() {
selectResultListItem($(this));
focusOnNodes(getSelectedNodeData());
}
function selectResultListItem($result) {
if ($result.hasClass(SELECTED)) {
$result.removeClass(SELECTED);
} else {
$results.children().removeClass(SELECTED);
$result.addClass(SELECTED);
}
}
function onSearchClick() {
var $target = $(this);
if ($target.hasClass('search-field')) {
$results.children().removeClass(SELECTED);
} else if ($target.hasClass('search-submit')) {
} else if ($target.hasClass('search-clear')) {
$field.val('');
clearResults();
}
}
$(document).on('keydown', function(evt) {
if (evt.which === KEYCODES.esc) {
$results.fadeOut('fast', function() {
$results.empty();
});
}
});
$(document).on('keydown', '.search .search-field, .search .search-result', function(evt) {
var $target = $(this),
$toSelect;
// On down arrow press (from search input), select first result
if ($target.hasClass('search-field')) {
if (evt.which === KEYCODES.down) {
$results.children(':first-child').focus();
evt.stopPropagation();
evt.preventDefault();
}
// On up/down arrow press (from search result li) select prev/next result
} else if ($target.hasClass('search-result')) {
if (evt.which === KEYCODES.down || evt.which === KEYCODES.up) {
if (evt.which === KEYCODES.up) {
$toSelect = $target.prev();
}
if (evt.which === KEYCODES.down) {
$toSelect = $target.next();
}
if ($toSelect.length) {
$results.children().removeClass(SELECTED);
$toSelect.focus();
}
evt.preventDefault();
evt.stopPropagation();
}
}
});
function maskGraph(duration) {
d3
.selectAll('.edgePath')
.transition()
.duration(duration)
.style('opacity', 0.2);
d3
.selectAll('.edgeLabel')
.transition()
.duration(duration)
.style('opacity', 0.2);
d3
.selectAll('.node')
.transition()
.duration(duration)
.style('opacity', 0.2);
}
function clearGraph(duration) {
d3
.selectAll('.edgePath')
.transition()
.duration(duration)
.style('opacity', 1);
d3
.selectAll('.edgeLabel')
.transition()
.duration(duration)
.style('opacity', 1);
d3
.selectAll('.node')
.transition()
.duration(duration)
.style('opacity', 1);
}
function deselectAll() {
selectedNodes.length = 0;
clearGraph(ZOOM_DURATION);
d3.select('.graph-attach g').attr('transform', 'translate(' + 0 + ',' + 0 + ') scale(' + originalMapScale + ')');
}
function clearResults() {
deselectAll();
resultNodes = {};
$results.fadeOut('fast', function() {
$results.empty();
});
}
function graphSearch(nodes, query) {
if (!query || !query.length) {
return [];
}
function getMatches(nodes) {
var matches = _(nodes).map(function(node) {
var text = '';
if (
window.g_currentData.nodes[node.id].hasOwnProperty('script_name') &&
window.g_currentData.nodes[node.id]['script_name']
) {
text = window.g_currentData.nodes[node.id]['script_name'];
}
if (node.label.toLowerCase().indexOf(query.toLowerCase()) !== -1) {
return node;
} else if (text && text.toLowerCase().indexOf(query.toLowerCase()) !== -1) {
return node;
} else {
return null;
}
});
return matches
.filter() // filter out nulls
.flatten() // merge results from clusters
.value(); // extract array from Lodash object
}
return getMatches(nodes);
}
function performSearch() {
deselectAll();
var query = $field.val(),
results = query.length >= MIN_QUERY_LENGTH ? graphSearch(g._nodes, query) : [];
if (!results.length) {
clearResults();
graphSelect();
} else {
$results.empty();
_.each(
results,
function(node) {
var text = node.label;
if (
window.g_currentData.nodes[node.id].hasOwnProperty('script_name') &&
window.g_currentData.nodes[node.id]['script_name']
) {
text = window.g_currentData.nodes[node.id]['script_name'];
}
$results.append(
$('<li/>', {
'data-node-id': node.id,
text: text,
class: 'search-result',
tabindex: 1
})
);
resultNodes[node.id] = node;
},
this
);
$results.fadeIn();
graphSelect(results);
}
}
function graphSelect(nodes) {
if (!nodes) {
clearGraph(ZOOM_DURATION);
return;
}
if (!_.isArray(nodes)) {
nodes = [nodes]; // Allow passing a single node
}
if (nodes.length) {
maskGraph(ZOOM_DURATION);
highlightNodesAndLinks(nodes, ZOOM_DURATION);
} else {
clearGraph(ZOOM_DURATION);
}
}
function onFieldKeydown(evt) {
if (!_.contains(KEYCODES, evt.which)) {
performSearch();
}
if (evt.which === KEYCODES.enter) {
//search.focusOnNodes(graph.selectedNodes);
}
}
$('#search-clear').click(function() {
$('#searchfield').val('');
clearGraph(ZOOM_DURATION);
});
var g = new dagreD3.graphlib.Graph();
if (rotation) {
g.setGraph({ rankdir: 'LR' });
} else {
g.setGraph({ rankdir: 'TB' });
}
g.setDefaultEdgeLabel(function() {
return {};
});
var styles = {
LI_FLOW_START: 'fill:lightsteelblue',
LI_FLOW_END: 'fill:lightsteelblue',
LI_BTEQ: 'fill:aquamarine',
LINKEDIN_SHELL_PARAM: 'fill:lightcyan',
LI_INFA: 'fill:lightpink',
LINKEDIN_TD_DAILY_TBL_CHECK: 'fill:powderblue',
LINKEDIN_ODS_DB_CHECK: 'fill:thistle',
LI_PIG_JOB: 'fill:salmon',
KFK_SONORA_TD_LOAD: 'fill:rosybrown',
KFK_SONORA_HADOOP_GET: 'fill:khaki',
LI_HADOOP_MV: 'fill:peachpuff',
LI_ARCHIVE: 'fill:mistyrose',
LI_SHELL: 'fill:lavendar'
};
if (type === 'job') {
for (var i = 0; i < data.nodes.length; i++) {
var path = data.nodes[i].job_path;
var index = path.lastIndexOf('/');
var label = path.substring(index + 1);
var style = styles[data.nodes[i].job_type];
if (!style) style = 'fill:palegoldenrod';
//g.addNode(i+1, { label: label, style:style, title:path})
g.setNode(i, { label: label, style: style });
}
for (var i = 0; i < data.links.length; i++) {
if (data.links[i].type === 'job') {
g.setEdge(data.links[i].source, data.links[i].target, {
style: 'stroke: #66B2FF; stroke-width: 2px; stroke-dasharray: 5, 5;'
});
} else {
g.setEdge(data.links[i].source, data.links[i].target);
}
}
} else {
for (var i = 0; i < data.nodes.length; i++) {
var schema_type = '';
var name;
var shape = 'rect';
if (data.nodes[i].node_type === 'data') {
if (data.nodes[i]['storage_type']) {
schema_type = data.nodes[i]['storage_type'];
} else {
schema_type = 'hdfs';
}
if (data.nodes[i].hasOwnProperty('abstracted_path')) {
name = data.nodes[i]['abstracted_path'];
} else {
name = data.nodes[i]['abstracted_object_name'];
}
} else {
shape = 'ellipse';
if (data.nodes[i]['job_type']) {
schema_type = data.nodes[i]['job_type'];
name = data.nodes[i]['job_type'];
} else {
schema_type = 'sql';
name = 'sql';
}
}
if (schema_type.toLowerCase() === 'pig')
g.setNode(data.nodes[i].id, { label: name, style: 'fill:lightblue', id: data.nodes[i].id, shape: shape });
else if (schema_type.toLowerCase() === 'hdfs')
g.setNode(data.nodes[i].id, { label: name, style: 'fill:thistle', id: data.nodes[i].id, shape: shape });
else if (schema_type.toLowerCase() === 'nas')
g.setNode(data.nodes[i].id, { label: name, style: 'fill:tan', id: data.nodes[i].id, shape: shape });
else if (schema_type.toLowerCase() === 'teradata')
g.setNode(data.nodes[i].id, { label: name, style: 'fill:mistyrose', id: data.nodes[i].id, shape: shape });
else if (schema_type.toLowerCase() === 'shell')
g.setNode(data.nodes[i].id, { label: name, style: 'fill:sandybrown', id: data.nodes[i].id, shape: shape });
else if (schema_type.toLowerCase() === 'mload')
g.setNode(data.nodes[i].id, { label: name, style: 'fill:peachpuff', id: data.nodes[i].id, shape: shape });
else if (schema_type.toLowerCase() === 'sql')
g.setNode(data.nodes[i].id, { label: name, style: 'fill:navajowhite', id: data.nodes[i].id, shape: shape });
else if (schema_type.toLowerCase() === 'lassen')
g.setNode(data.nodes[i].id, { label: name, style: 'fill:palegreen', id: data.nodes[i].id, shape: shape });
else if (schema_type.toLowerCase() === 'cmd')
g.setNode(data.nodes[i].id, { label: name, style: 'fill:orange', id: data.nodes[i].id, shape: shape });
else if (schema_type.toLowerCase() === 'tpt')
g.setNode(data.nodes[i].id, { label: name, style: 'fill:wheat', id: data.nodes[i].id, shape: shape });
else if (schema_type.toLowerCase() === 'informatica')
g.setNode(data.nodes[i].id, { label: name, style: 'fill:seagreen', id: data.nodes[i].id, shape: shape });
else if (schema_type.toLowerCase() === 'java')
g.setNode(data.nodes[i].id, { label: name, style: 'fill:lightcoral', id: data.nodes[i].id, shape: shape });
else g.setNode(data.nodes[i].id, { label: name, style: 'fill:pink', id: data.nodes[i].id, shape: shape });
}
for (var i = 0; i < data.links.length; i++) {
var source = data.links[i].source;
var target = data.links[i].target;
if (!data.nodes[target].sourceLinks) {
data.nodes[target].sourceLinks = [];
}
data.nodes[target].sourceLinks.push(data.links[i]);
if (!data.nodes[source].targetLinks) {
data.nodes[source].targetLinks = [];
}
data.nodes[source].targetLinks.push(data.links[i]);
if (data.links[i].type === 'job') {
g.setEdge(data.links[i].source, data.links[i].target, {
label: data.links[i].label,
style: 'stroke: #66B2FF; stroke-width: 2px; stroke-dasharray: 5, 5;'
});
} else {
g.setEdge(data.links[i].source, data.links[i].target, { label: data.links[i].label });
}
}
}
var originalMapScale = 1;
var styleTooltip = function(name, description) {
return '<p class="description">' + description + '</p>';
};
g.nodes().forEach(function(v) {
var node = g.node(v);
// Round the corners of the nodes
node.rx = node.ry = 5;
});
var render = new dagreD3.render();
var svg = d3.select('#svg-canvas');
var graphSVG = svg
.append('svg')
.attr('class', 'graph-attach')
.attr('width', '100%')
.attr('height', '100%');
var svgGroup = graphSVG.append('g');
var miniSVG = svg
.append('svg')
.attr('class', 'minimap')
.attr('width', '19.6%')
.attr('height', '19.5%')
.attr('x', '80%')
.attr('y', '0');
miniSVG
.insert('rect', ':first-child')
.attr('class', 'background')
.attr('width', '100%')
.attr('height', '100%')
.style('fill', '#DDD')
.style('opacity', '0.5');
var minimapSVG = miniSVG
.append('svg')
.attr('class', 'minimap-attach')
.attr('width', '100%')
.attr('height', '100%');
var overlay = minimapSVG
.append('rect', ':first-child')
.attr('class', 'overlay')
.attr('width', '100%')
.attr('height', '100%')
.style('fill', '#000')
.style('opacity', '0.1');
var miniSVGGroup = minimapSVG.append('g');
graphSVG.node().oncontextmenu = function(d) {
return false;
};
var tooltip = d3LineageTooltip();
tooltip.hide();
function attachContextMenus() {
contextMenu.call(graphSVG.node(), graphSVG.selectAll('.node'));
contextMenu
.on('open', function() {
tooltip.hide();
})
.on('close', function() {});
}
// Detaches any bound context menus
function detachContextMenus() {
$('.graph .node').unbind('contextmenu');
}
var origWidth = $('#svg-canvas').width();
var origHeight = $('#svg-canvas').height();
var contextMenu = d3LineageContextMenu(svgGroup.node(), svgGroup);
var minimapScale = 1;
function selectTabularRow(d, i) {
var str = '#data-table-tr-' + window.g_currentData.nodes[d].id;
if (type === 'job') {
str = '#job-data-table-tr-' + window.g_currentData.nodes[d].id;
} else {
if (window.g_currentData.nodes[i].node_type === 'script') {
str = '#job-table-tr-' + window.g_currentData.nodes[d].id;
if ($('#datatabpage').hasClass('active')) {
$('#datatabpage').removeClass('active');
$('#jobtabpage').addClass('active');
$('#datanodestab').removeClass('active');
$('#jobnodestab').addClass('active');
$('#nodeInfoSplitter').tabs({ active: 1 });
}
} else if (window.g_currentData.nodes[i].node_type === 'data') {
if ($('#jobtabpage').hasClass('active')) {
$('#jobnodestab').removeClass('active');
$('#jobtabpage').removeClass('active');
$('#datanodestab').addClass('active');
$('#datatabpage').addClass('active');
$('#nodeInfoSplitter').tabs({ active: 0 });
}
}
}
var obj = $(str);
$('#nodeInfoSplitter').scrollTo(obj, 800);
obj
.addClass('highlight')
.siblings()
.removeClass('highlight');
}
var resetViewport = function() {
var curbbox = svg.node().getBBox();
var bbox = { x: curbbox.x, y: curbbox.y, width: curbbox.width + 50, height: curbbox.height + 50 };
var scale = Math.min(origWidth / g.graph().width, origHeight / g.graph().height);
if (scale > 1) scale = 1;
originalMapScale = scale;
minimapScale = scale * 0.195;
var zoomScale = [];
zoomScale[0] = originalMapScale;
zoomScale[1] = 1;
let w = origWidth / scale;
let h = origHeight / scale;
let tx = 0;
let ty = 0;
zoom
.translate([0, 0])
.scale(scale)
.event(svg);
svg.attr('height', g.graph().height * scale);
svg.attr('width', g.graph().width * scale);
var t = [0, 0];
miniSVGGroup.attr('transform', 'translate(' + t + ')' + 'scale(' + minimapScale + ')');
};
var zoom = d3.behavior.zoom().on('zoom', function() {
svgGroup.attr('transform', 'translate(' + d3.event.translate + ')' + 'scale(' + d3.event.scale + ')');
var t = [
-d3.event.translate[0] * minimapScale / d3.event.scale,
-d3.event.translate[1] * minimapScale / d3.event.scale
];
overlay
.attr('x', t[0])
.attr('y', t[1])
.attr('width', origWidth / d3.event.scale * minimapScale)
.attr('height', origHeight / d3.event.scale * minimapScale);
});
// Run the renderer. This is what draws the final graph.
render(svgGroup, g);
render(miniSVGGroup, g);
resetViewport();
svg.call(zoom);
svgGroup
.selectAll('.node')
.on('click', function(d, i) {
selectTabularRow(d, i);
})
.call(tooltip);
attachContextMenus();
}
const d3LineageTooltip = function(gravity) {
const toOuterHTML = function(data) {
return $('<div />')
.append(data.eq(0).clone())
.html();
};
return window.Tooltip(gravity).title(function(d) {
if (!(window.g_currentData && window.g_currentData.nodes)) {
return '';
}
const data = window.g_currentData.nodes[d];
if (!data) {
return '';
}
const sortList = data['_sort_list'];
const $xtraceTooltip = $('<div>').attr('class', 'xtrace-tooltip');
if (sortList) {
sortList.forEach(sortList => appendRow(sortList, data[sortList], $xtraceTooltip));
} else {
Object.keys(data).forEach(dataKey => appendRow(dataKey, data[dataKey], $xtraceTooltip));
}
function appendRow(key, value, tooltip) {
const keyrow = $('<div>')
.attr('class', 'key')
.append(key);
const valrow = $('<div>')
.attr('class', 'value')
.append(value);
const clearrow = $('<div>').attr('class', 'clear');
tooltip.append(
$('<div>')
.append(keyrow)
.append(valrow)
.append(clearrow)
);
}
return toOuterHTML($xtraceTooltip);
});
};
export default Route.extend({
model({ id }) {
scheduleOnce('afterRender', this, setupSearch, { lineageId: id, lineageType: 'dataset' });
},
deactivate() {
$('#rotationgraphbtn').off('click');
$('#uplevelbtn').off('click');
$('#downlevelbtn').off('click');
return this;
}
});