Commit 3c0b2746 by kevalbhatt

ATLAS-3954: UI: Type system property table improvement

parent 39ff496f
......@@ -180,6 +180,11 @@ pre {
.json-string {
color: olive;
&.cursor {
cursor: pointer;
text-decoration: underline;
}
}
}
......@@ -191,6 +196,11 @@ pre {
.panel-body .memory-details {
pre {
&.code-block {
&.fixed-height {
max-height: 112px;
overflow: auto;
}
&.shrink {
height: 144px;
......
......@@ -193,7 +193,7 @@ span#zoom_in {
width: 100%;
right: 0;
padding: 0 !important;
z-index: 9999;
z-index: 99;
overflow: hidden !important;
background: white;
......@@ -266,4 +266,38 @@ span#zoom_in {
box-shadow: 0px 0px 3px 1px #80808080;
}
}
.box-panel.fix-box {
position: fixed;
top: 0;
right: 0;
bottom: 0;
height: 100vh;
max-height: 100vh;
z-index: 999;
bottom: 0;
width: 400px;
overflow: auto;
border-radius: 0px;
margin: 0 !important;
&.slide-from-left.size-lg {
left: -413px;
&.show-box-panel {
left: 0;
margin: 0 !important;
}
}
.body {
tbody {
overflow: auto;
height: calc(100vh - 48px);
position: absolute;
padding-bottom: 15px;
}
}
}
\ No newline at end of file
......@@ -41,6 +41,7 @@ tr.empty {
}
.entity-detail-table,
.type-node-details,
.relationship-detail-table {
position: relative;
......@@ -66,6 +67,26 @@ tr.empty {
}
}
.type-node-details {
.header {
.pretty.p-switch .state:before {
border: 1px solid white;
}
.pretty.p-switch .state label:after {
background-color: white !important;
}
.pretty.p-switch.p-fill input:checked~.state label:after {
background-color: #4a90e2 !important;
}
.pretty.p-switch.p-fill input:checked~.state.p-primary:before {
background-color: white !important;
}
}
}
.backgrid {
td {
white-space: normal;
......@@ -98,6 +119,13 @@ tr.empty {
}
}
}
.debuggging-table-header {
padding-right: 0px !important;
button{
float: right;
}
}
}
.backgrid-paginator ul {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -374,7 +374,7 @@ const LineageUtils = {
reader.addEventListener("load", () => callback(reader.result));
reader.readAsDataURL(file);
},
imgShapeRender: function (parent, bbox, node, { dagreD3, defsEl, imgBasePath, guid }) {
imgShapeRender: function (parent, bbox, node, { dagreD3, defsEl, imgBasePath, guid, isRankdirToBottom }) {
var that = this,
viewGuid = guid,
imageIconPath = this.getEntityIconPath({ entityData: node, imgBasePath }),
......@@ -391,7 +391,7 @@ const LineageUtils = {
var shapeSvg = parent
.append("circle")
.attr("fill", "url(#img_" + imgName + ")")
.attr("r", "24px")
.attr("r", isRankdirToBottom ? "30px" : "24px")
.attr("data-stroke", node.id)
.attr("stroke-width", "2px")
.attr("class", "nodeImage " + (currentNode ? "currentNode" : node.isProcess ? "process" : "node"));
......@@ -478,8 +478,8 @@ const LineageUtils = {
});
}
})
.attr("x", "4")
.attr("y", currentNode ? "3" : "4")
.attr("x", isRankdirToBottom ? "11" : "4")
.attr("y", isRankdirToBottom ? "20" : currentNode ? "3" : "4")
.attr("width", "40")
.attr("height", "40");
}
......
......@@ -26,6 +26,7 @@ import "./styles/style.scss";
export default class LineageHelper {
constructor(options) {
this.options = {};
this._updateOptions(options);
const { el, manualTrigger = false } = this.options;
if (el === undefined) {
......@@ -33,6 +34,7 @@ export default class LineageHelper {
}
this.initReturnObj = {
init: (arg) => this.init(arg),
updateOptions: (options) => this._updateAllOptions(options),
createGraph: (opt = {}) => this._createGraph(this.options, this.graphOptions, opt),
clear: (arg) => this.clear(arg),
refresh: (arg) => this.refresh(arg),
......@@ -78,12 +80,27 @@ export default class LineageHelper {
return this.initReturnObj;
}
/**
* [updateAllOptions]
* @param {[type]}
* @return {[type]}
*/
_updateAllOptions(options) {
Object.assign(this.options, options);
var svgRect = this.svg.node().getBoundingClientRect();
this.graphOptions.width = this.options.width || svgRect.width;
this.graphOptions.height = this.options.height || svgRect.height;
const { svg, width, height, guid } = this.graphOptions;
const { fitToScreen } = this.options;
svg.select("g").node().removeAttribute("transform");
svg.attr("viewBox", "0 0 " + width + " " + height).attr("enable-background", "new 0 0 " + width + " " + height);
this.centerAlign({ fitToScreen, guid });
}
/**
* [updateOptions get the options from user and appedn add it in this,option context]
* @param {[Object]} options [lib options from user]
* @return {[null]} [null]
*/
_updateOptions(options) {
this.options = {};
Object.assign(this.options, { filterObj: { isProcessHideCheck: false, isDeletedEntityHideCheck: false } }, options);
}
/**
......@@ -200,7 +217,7 @@ export default class LineageHelper {
if (node && node.attributes) {
downloadFileName = `${node.attributes.qualifiedName || node.attributes.name || "lineage_export"}.png`;
} else {
downloadFileName = "lineage_export.png";
downloadFileName = "export.png";
}
}
......@@ -258,6 +275,7 @@ export default class LineageHelper {
this.svg = select(el);
if (!(el instanceof SVGElement)) {
this.svg.selectAll("*").remove();
this.svg = this.svg
.append("svg")
.attr("xmlns", "http://www.w3.org/2000/svg")
......@@ -385,7 +403,19 @@ export default class LineageHelper {
* @return {[type]} [description]
*/
_createGraph(
{ data = {}, imgBasePath, isShowTooltip, isShowHoverPath, onLabelClick, onPathClick, onNodeClick, zoom, fitToScreen },
{
data = {},
imgBasePath,
isShowTooltip,
isShowHoverPath,
onLabelClick,
onPathClick,
onNodeClick,
zoom,
fitToScreen,
getToolTipContent,
toolTipTitle
},
graphOptions,
{ refresh }
) {
......@@ -393,7 +423,8 @@ export default class LineageHelper {
this.options.beforeRender();
}
const that = this,
{ svg, g, width, height } = graphOptions;
{ svg, g, width, height } = graphOptions,
isRankdirToBottom = this.options.dagreOptions && this.options.dagreOptions.rankdir === "tb";
if (svg instanceof selection === false) {
throw new Error("svg is not initialized or something went wrong while creatig graph instance");
......@@ -428,6 +459,7 @@ export default class LineageHelper {
render.shapes().img = function () {
return LineageUtils.imgShapeRender(...arguments, {
...graphOptions,
isRankdirToBottom: isRankdirToBottom,
imgBasePath: that._getValueFromUser(imgBasePath),
defsEl
});
......@@ -437,19 +469,26 @@ export default class LineageHelper {
.attr("class", "d3-tip")
.offset([10, 0])
.html((d) => {
var value = g.node(d);
var htmlStr = "";
if (value.id !== this.guid) {
htmlStr = "<h5 style='text-align: center;'>" + (value.isLineage ? "Lineage" : "Impact") + "</h5>";
}
htmlStr += "<h5 class='text-center'><span style='color:#359f89'>" + value.toolTipLabel + "</span></h5> ";
if (value.typeName) {
htmlStr += "<h5 class='text-center'><span>(" + value.typeName + ")</span></h5> ";
}
if (value.queryText) {
htmlStr += "<h5>Query: <span style='color:#359f89'>" + value.queryText + "</span></h5> ";
if (getToolTipContent && typeof getToolTipContent === "function") {
return getToolTipContent(d, g.node(d));
} else {
var value = g.node(d);
var htmlStr = "";
if (toolTipTitle) {
htmlStr = "<h5 style='text-align: center;'>" + toolTipTitle + "</h5>";
} else if (value.id !== this.guid) {
htmlStr = "<h5 style='text-align: center;'>" + (value.isLineage ? "Lineage" : "Impact") + "</h5>";
}
htmlStr += "<h5 class='text-center'><span style='color:#359f89'>" + value.toolTipLabel + "</span></h5> ";
if (value.typeName) {
htmlStr += "<h5 class='text-center'><span>(" + value.typeName + ")</span></h5> ";
}
if (value.queryText) {
htmlStr += "<h5>Query: <span style='color:#359f89'>" + value.queryText + "</span></h5> ";
}
return "<div class='tip-inner-scroll'>" + htmlStr + "</div>";
}
return "<div class='tip-inner-scroll'>" + htmlStr + "</div>";
});
svg.call(tooltip);
......@@ -463,7 +502,12 @@ export default class LineageHelper {
//change text postion
svgGroupEl
.selectAll("g.nodes g.label")
.attr("transform", "translate(2,-35)")
.attr("transform", () => {
if (isRankdirToBottom) {
return "translate(2,-20)";
}
return "translate(2,-35)";
})
.on("mouseenter", function (d) {
event.preventDefault();
select(this).classed("highlight", true);
......
......@@ -37,7 +37,7 @@
<div id="r_adminTableLayoutView">
</div>
</div>
<div id="tab-typeSystem" role="typeSystem" class="tab-pane animated fadeIn" style="position: relative;">
<div id="tab-typeSystem" role="typeSystem" class="tab-pane" style="position: relative;">
<div id="r_typeSystemTreeLayoutView">
</div>
</div>
......
......@@ -91,7 +91,7 @@
</div>
</div>
</div>
<div id="tab-lineage" role="lineage" class="tab-pane animated fadeIn">
<div id="tab-lineage" role="lineage" class="tab-pane">
<div id="r_lineageLayoutView" class="animated position-relative" align="center">
<div class="fontLoader-relative">
<i class="fa fa-refresh fa-spin-custom"></i>
......
......@@ -124,22 +124,22 @@
</button>
</div>
</div>
<div class="box-panel size-lg node-details slide-from-left lineage-node-detail">
<div class="header clearfix">
<h4><span data-id="typeName"></span></h4>
<span data-id="box-close" class="btn btn-sm btn-close lineage-node-detail-close"><i class="fa fa-close"></i></span>
<span data-id="box-close" class="btn btn-sm btn-close lineage-node-detail-close"><i class="fa fa-close"></i></span>
</div>
<div class="body">
<table class="table bold-key">
<tbody data-id="nodeDetailTable"></tbody>
</table>
</div>
</div>
<div class="fontLoader">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
<div class="legends pull-left" style="height: 25px; padding: 2px;"></div>
<div class="svg" style="height: 100%; width: 100%"></div>
</div>
<div class="box-panel size-lg slide-from-left lineage-node-detail fix-box">
<div class="header clearfix">
<h4><span data-id="typeName"></span></h4>
<span data-id="box-close" class="btn btn-sm btn-close lineage-node-detail-close"><i class="fa fa-close"></i></span>
<span data-id="box-close" class="btn btn-sm btn-close lineage-node-detail-close"><i class="fa fa-close"></i></span>
</div>
<div class="body">
<table class="table bold-key">
<tbody data-id="nodeDetailTable"></tbody>
</table>
</div>
</div>
<div class="hidden-svg"></div>
\ No newline at end of file
......@@ -15,16 +15,30 @@
* limitations under the License.
-->
<div id="typeSystemTreeViewPage" data-id="typeSystemTreeViewPage" class="systemTypeTree" style="height: calc(100vh - 180px); width: 100%; position: relative;overflow: hidden;">
<div class="box-panel size-lg node-details slide-from-left lineage-node-detail">
<div class="box-panel size-lg type-node-details fix-box slide-from-left lineage-node-detail">
<div class="header clearfix">
<h4><span data-id="typeName"></span></h4>
<span data-id="box-close" class="btn btn-sm btn-close lineage-node-detail-close"><i class="fa fa-close"></i></span>
<span data-id="box-close" class="btn btn-sm btn-close lineage-node-detail-close"><i class="fa fa-close"></i></span>
<div class="typeDetailHeader">
<h4 style="padding-right: 67px;"><span data-id="typeName"></span></h4>
<div class="pretty p-switch p-fill" style="position: absolute;top: 13px;right: 32px;">
<input type="checkbox" data-id="noValueToggle" title="Show empty values" />
<div class="state p-primary">
<label></label>
</div>
</div>
<span data-id="box-close" class="btn btn-sm btn-close "><i class="fa fa-close"></i></span>
</div>
<div class="typeAttrDetailHeader" style="display: none;">
<span data-id="box-back" class="btn btn-sm btn-close" style="left: 0px; right: auto;"><i class="fa fa-angle-left"></i></span>
<h4 style="padding-left: 27px;"><span data-id="typeAttrDetailHeader"></span></h4>
</div>
</div>
<div class="body">
<table class="table bold-key">
<tbody data-id="nodeDetailTable"></tbody>
<tbody data-id="nodeDetailTable" class="hide-empty-value"></tbody>
</table>
<div data-id="attribute-table" style="height: calc(100vh - 60px);display: none">
<pre class="code-block" style="height: 100%"></pre>
</div>
</div>
</div>
<div class="fontLoader">
......@@ -49,7 +63,6 @@
<div class="body">
<div class="col-sm-12 no-padding">
<div class="srchType clearfix">
<label class="srchTitle">Search Lineage Entity: </label>
<div class="">
<div class="col-sm-12 no-padding temFilter">
<select data-id="typeSearch"></select>
......@@ -59,28 +72,62 @@
</div>
</div>
</div>
<div class="box-panel setting-box">
<div class="header clearfix">
<h4>Settings</h4>
<span data-id="box-close" class="btn btn-sm btn-close"><i class="fa fa-close"></i></span>
</div>
<div class="body">
<div class="showOnlyHoverPath form-group text-left col-sm-12">
<div class="pretty p-switch p-fill">
<input type="checkbox" checked class="pull-left" data-id="showOnlyHoverPath" value="" />
<div class="state p-primary">
<label>On hover show current path</label>
</div>
</div>
</div>
<div class="showTooltip form-group text-left col-sm-12">
<div class="pretty p-switch p-fill">
<input type="checkbox" class="pull-left" data-id="showTooltip" value="" />
<div class="state p-primary">
<label>Show node details on hover</label>
</div>
</div>
</div>
</div>
</div>
<div class="graph-button-group pull-right">
<div>
<button data-id="reset" class="btn btn-action btn-gray btn-sm" title="Realign Lineage">
<button data-id="reset" class="btn btn-action btn-gray btn-sm" title="Reset">
<i class="fa fa-retweet"></i>
</button>
</div>
<div>
<button data-id="saveSvg" class="btn btn-action btn-gray btn-sm" title="Export to PNG">
<i class="fa fa-camera"></i>
</button>
</div>
<div>
<button type="button" data-id="setting-toggler" title="Settings" class="btn btn-action btn-gray btn-sm">
<i class="fa fa-gear"></i>
</button>
</div>
<div>
<button type="button" data-id="filter-toggler" title="Filter" class="btn btn-action btn-gray btn-sm"><i class="fa fa-filter"></i></button>
</div>
<div>
<button type="button" data-id="search-toggler" title="Search" class="btn btn-action btn-gray btn-sm"><i class="fa fa-search"></i></button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-action btn-gray btn-sm lineageZoomButton" title="Zoom In" data-id="zoom-in">
<button type="button" class="btn btn-action btn-gray btn-sm" title="Zoom In" data-id="zoom-in">
<i class="fa fa-search-plus"></i>
</button>
<button type="button" class="btn btn-action btn-gray btn-sm lineageZoomButton" title="Zoom Out" data-id="zoom-out">
<button type="button" class="btn btn-action btn-gray btn-sm" title="Zoom Out" data-id="zoom-out">
<i class="fa fa-search-minus"></i>
</button>
</div>
<div>
<button type="button" data-id="fullScreen-toggler" title="Full screen" class="btn btn-action btn-gray btn-sm fullscreen_lineage">
<button type="button" data-id="fullScreen-toggler" title="Full screen" class="btn btn-action btn-gray btn-sm">
<i class="fa fa-expand"></i>
</button>
</div>
......
......@@ -79,6 +79,8 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
sortBy = options.sortBy,
valueObject = options.valueObject,
extractJSON = options.extractJSON,
getArrayOfStringElement = options.getArrayOfStringElement,
getArrayOfStringFormat = options.getArrayOfStringFormat,
isTable = _.isUndefined(options.isTable) ? true : options.isTable,
attributeDefs = options.attributeDefs,
formatIntVal = options.formatIntVal,
......@@ -108,6 +110,9 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
return "N/A";
},
getValue = function(val, key) {
if (options && options.getValue) {
val = options.getValue(val, key);
}
if (!_.isUndefined(val) && !_.isNull(val)) {
if ((_.isNumber(val) || !_.isNaN(parseInt(val))) && formatIntVal) {
return numberFormat(val);
......@@ -185,7 +190,12 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
if (_.isString(inputOutputField) || _.isBoolean(inputOutputField) || _.isNumber(inputOutputField)) {
var tempVarfor$check = inputOutputField.toString();
if (tempVarfor$check.indexOf("$") == -1) {
valueOfArray.push('<span class="json-string">' + getValue(inputOutputField, key) + '</span>');
var tmpVal = getValue(inputOutputField, key)
if (getArrayOfStringElement) {
valueOfArray.push(getArrayOfStringElement(tmpVal, key));
} else {
valueOfArray.push('<span class="json-string">' + tmpVal + '</span>');
}
}
} else if (_.isObject(inputOutputField) && !id) {
var attributesList = inputOutputField;
......@@ -251,7 +261,11 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
}
}
if (valueOfArray.length) {
subLink = valueOfArray.join(', ');
if (getArrayOfStringFormat) {
subLink = getArrayOfStringFormat(valueOfArray, key);
} else {
subLink = valueOfArray.join(', ');
}
}
return subLink === "" ? getEmptyString(key) : subLink;
}
......@@ -297,12 +311,17 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
if (_.isObject(valueObject[key]) && !_.isEmpty(valueObject[key])) {
var matchedLinkString = val.match(/href|value-loader\w*/g),
matchedJson = val.match(/json-value|json-string\w*/g),
matchedKey = val.match(/json-key\w*/g),
isMatchLinkStringIsSingle = matchedLinkString && matchedLinkString.length <= 5,
isMatchJSONStringIsSingle = matchedJson && matchedJson.length == 1,
expandCollapseButton = "";
if ((matchedJson && !isMatchJSONStringIsSingle) || (matchedLinkString && !isMatchLinkStringIsSingle)) {
expandCollapseButton = '<button class="expand-collapse-button"><i class="fa"></i></button>';
htmlTag = '<pre class="shrink code-block ' + (isMatchJSONStringIsSingle ? 'fixed-height' : '') + '">' + expandCollapseButton + '<code>' + val + '</code></pre>';
if ((matchedJson) || (matchedLinkString)) {
var className = "code-block fixed-height";
if (!isMatchJSONStringIsSingle) {
className += " shrink";
expandCollapseButton = '<button class="expand-collapse-button"><i class="fa"></i></button>';
}
htmlTag = '<pre class="' + className + '">' + expandCollapseButton + '<code>' + val + '</code></pre>';
}
}
table += '<tr class="' + appendClass + '"><td>' + (_.escape(key) + listCount) + '</td><td>' + htmlTag + '</td></tr>';
......
......@@ -134,13 +134,13 @@ define(['require',
},
onShow: function() {
this.$('.fontLoader').show();
this.$el.resizable({
handles: ' s',
minHeight: 375,
stop: function(event, ui) {
ui.element.height(($(this).height()));
},
});
// this.$el.resizable({
// handles: ' s',
// minHeight: 375,
// stop: function(event, ui) {
// ui.element.height(($(this).height()));
// },
// });
},
onClickLineageFullscreenToggler: function(e) {
var icon = $(e.currentTarget).find('i'),
......@@ -152,6 +152,11 @@ define(['require',
icon.parent('button').attr("data-original-title", "Default View");
}
panel.toggleClass('fullscreen-mode');
var node = this.$("svg").parent()[0].getBoundingClientRect();
this.LineageHelperRef.updateOptions({
width: node.width,
height: node.height
});
},
onCheckUnwantedEntity: function(e) {
var that = this;
......@@ -210,6 +215,8 @@ define(['require',
},
onClickResetLineage: function() {
this.LineageHelperRef.refresh();
this.searchNodeObj.selectedNode = "";
this.ui.lineageTypeSearch.data({ refresh: true }).val("").trigger("change");
},
onClickSaveSvg: function(e, a) {
this.LineageHelperRef.exportLineage();
......@@ -249,10 +256,6 @@ define(['require',
})
},
createGraph: function(data) {
// if (_.isEmpty(this.g._nodes)) {
// this.$('svg').html('<text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle">No relations to display</text>');
// return;
// }
var that = this;
$('.resizeGraph').css("height", this.$('.svg').height() + "px");
......@@ -364,9 +367,13 @@ define(['require',
}).on('change.select2', function(e) {
e.stopPropagation();
e.stopImmediatePropagation();
var selectedNode = $('[data-id="typeSearch"]').val();
that.searchNodeObj.selectedNode = selectedNode;
that.LineageHelperRef.searchNode({ guid: selectedNode });
if (!that.ui.lineageTypeSearch.data("refresh")) {
var selectedNode = $('[data-id="typeSearch"]').val();
that.searchNodeObj.selectedNode = selectedNode;
that.LineageHelperRef.searchNode({ guid: selectedNode });
} else {
that.ui.lineageTypeSearch.data("refresh", false);
}
});
if (this.searchNodeObj.selectedNode) {
this.ui.lineageTypeSearch.val(this.searchNodeObj.selectedNode);
......
......@@ -55,16 +55,23 @@ define([
typeSystemTreeViewPage: "[data-id='typeSystemTreeViewPage']",
boxClose: '[data-id="box-close"]',
nodeDetailTable: '[data-id="nodeDetailTable"]',
attributeTable: '[data-id="attribute-table"]',
typeSearch: '[data-id="typeSearch"]',
filterServiceType: '[data-id="filterServiceType"]',
onZoomIn: '[data-id="zoom-in"]',
onZoomOut: '[data-id="zoom-out"]',
filterBox: ".filter-box",
searchBox: ".search-box",
settingBox: '.setting-box',
filterToggler: '[data-id="filter-toggler"]',
settingToggler: '[data-id="setting-toggler"]',
searchToggler: '[data-id="search-toggler"]',
reset: '[data-id="reset"]',
fullscreenToggler: '[data-id="fullScreen-toggler"]'
fullscreenToggler: '[data-id="fullScreen-toggler"]',
noValueToggle: "[data-id='noValueToggle']",
showOnlyHoverPath: '[data-id="showOnlyHoverPath"]',
showTooltip: '[data-id="showTooltip"]',
saveSvg: '[data-id="saveSvg"]',
},
/** ui events hash */
events: function() {
......@@ -73,9 +80,19 @@ define([
events["click " + this.ui.onZoomIn] = "onClickZoomIn";
events["click " + this.ui.onZoomOut] = "onClickZoomOut";
events["click " + this.ui.filterToggler] = "onClickFilterToggler";
events["click " + this.ui.settingToggler] = 'onClickSettingToggler';
events["click " + this.ui.searchToggler] = "onClickSearchToggler";
events["click " + this.ui.saveSvg] = 'onClickSaveSvg';
events["click " + this.ui.fullscreenToggler] = "onClickFullscreenToggler";
events["click " + this.ui.reset] = "onClickReset";
events["click " + this.ui.noValueToggle] = function() {
this.showAllProperties = !this.showAllProperties;
this.ui.noValueToggle.attr("data-original-title", (this.showAllProperties ? "Hide" : "Show") + " empty values");
Utils.togglePropertyRelationshipTableEmptyValues({
"inputType": this.ui.noValueToggle,
"tableEl": this.ui.nodeDetailTable
});
};
return events;
},
......@@ -90,7 +107,35 @@ define([
this.initializeGraph();
this.fetchGraphData();
},
onRender: function() {},
onRender: function() {
var that = this;
this.$el.on("click", "code li[data-def]", function() {
if (that.selectedDetailNode) {
var dataObj = $(this).data(),
defObj = that.selectedDetailNode[dataObj.def],
newData = null;
if (dataObj.def === "businessAttributes") {
newData = defObj[dataObj.attribute];
} else {
newData = _.filter(defObj, { name: dataObj.attribute });
}
that.ui.attributeTable.find("pre").html('<code style="max-height: 100%">' + Utils.JSONPrettyPrint(newData, function(val) {
return val;
}) + '</code>');
that.$el.find('[data-id="typeAttrDetailHeader"]').text(dataObj.def);
that.ui.nodeDetailTable.hide("slide", { direction: "right" }, 400);
that.ui.attributeTable.show("slide", { direction: "left" }, 400);
that.$el.find(".typeDetailHeader").hide();
that.$el.find(".typeAttrDetailHeader").show()
}
});
this.$el.on("click", "span[data-id='box-back']", function() {
that.ui.nodeDetailTable.show("slide", { direction: "right" }, 400);
that.ui.attributeTable.hide("slide", { direction: "left" }, 400);
that.$el.find(".typeDetailHeader").show();
that.$el.find(".typeAttrDetailHeader").hide()
})
},
fetchGraphData: function(options) {
var that = this;
var entityTypeDef = that.entityDefCollection.fullCollection.toJSON();
......@@ -101,7 +146,7 @@ define([
}
if (entityTypeDef.length) {
that.generateData($.extend(true, {}, { data: entityTypeDef }, options)).then(function(graphObj) {
that.createGraph();
that.createGraph(options);
});
}
},
......@@ -161,91 +206,56 @@ define([
if (options.data) {
if (options.filter) {
var pendingSubList = {},
pendingSuperList = {},
temp = {},
doneList = {},
traveseSubSuper = function(obj, ignoreSubTypes) {
var fromEntityId = obj.guid;
if (!ignoreSubTypes && obj.subTypes.length) {
_.each(obj.subTypes, function(subType) {
var tempObj = doneList[subType] || temp[subType];
if (tempObj) {
// filter
var pendingSuperList = {},
outOfFilterData = {},
doneList = {};
var linkParents = function(obj) {
if (obj && obj.superTypes.length) {
_.each(obj.superTypes, function(superType) {
var fromEntityId = obj.guid;
var tempObj = doneList[superType] || outOfFilterData[superType];
if (tempObj) {
if (!doneList[superType]) {
setNode(tempObj.guid, tempObj);
setEdge(fromEntityId, tempObj.guid);
} else {
if (pendingSubList[subType]) {
pendingSubList[subType].push(fromEntityId);
} else {
pendingSubList[subType] = [fromEntityId];
}
}
});
}
if (obj.superTypes.length) {
_.each(obj.superTypes, function(superType) {
var tempObj = doneList[superType] || temp[superType];
if (tempObj) {
setNode(tempObj.guid, tempObj);
setEdge(tempObj.guid, fromEntityId);
if (tempObj.superTypes.length) {
traveseSubSuper(tempObj, true);
}
setEdge(tempObj.guid, fromEntityId);
linkParents(tempObj);
} else {
if (pendingSuperList[superType]) {
pendingSuperList[superType].push(fromEntityId);
} else {
if (pendingSuperList[superType]) {
pendingSuperList[superType].push(fromEntityId);
} else {
pendingSuperList[superType] = [fromEntityId];
}
pendingSuperList[superType] = [fromEntityId];
}
});
}
};
}
});
}
}
_.each(options.data, function(obj) {
var fromEntityId = obj.guid;
if (pendingSuperList[obj.name]) {
doneList[obj.name] = obj;
setNode(fromEntityId, obj);
_.map(pendingSuperList[obj.name], function(guid) {
setEdge(fromEntityId, guid);
});
delete pendingSuperList[obj.name];
linkParents(obj);
}
if (obj.serviceType === options.filter) {
doneList[obj.name] = obj;
setNode(fromEntityId, obj);
if (pendingSubList[obj.name]) {
_.map(pendingSubList[obj.name], function(guid) {
setEdge(guid, fromEntityId);
});
delete pendingSubList[obj.name];
}
if (pendingSuperList[obj.name]) {
_.map(pendingSuperList[obj.name], function(guid) {
setEdge(fromEntityId, guid);
});
delete pendingSuperList[obj.name];
}
traveseSubSuper(obj);
} else {
if (pendingSubList[obj.name]) {
setNode(fromEntityId, obj);
doneList[obj.name] = obj;
_.map(pendingSubList[obj.name], function(guid) {
setEdge(guid, fromEntityId);
});
delete pendingSubList[obj.name];
}
if (pendingSuperList[obj.name]) {
var fromEntityId = obj.guid;
setNode(fromEntityId, obj);
doneList[obj.name] = obj;
_.map(pendingSuperList[obj.name], function(guid) {
setEdge(fromEntityId, guid);
});
delete pendingSuperList[obj.name];
}
if (!doneList[obj.name]) {
temp[obj.name] = obj;
}
linkParents(obj);
} else if (!doneList[obj.name] && !outOfFilterData[obj.name]) {
outOfFilterData[obj.name] = obj;
}
});
pendingSubList = null;
pendingSuperList = null;
doneList = null;
outOfFilterData = null;
} else {
// Without filter
var pendingList = {},
doneList = {};
......@@ -308,11 +318,19 @@ define([
onClickFilterToggler: function() {
this.toggleBoxPanel({ el: this.ui.filterBox });
},
onClickSettingToggler: function() {
this.toggleBoxPanel({ el: this.ui.settingBox });
},
onClickSearchToggler: function() {
this.toggleBoxPanel({ el: this.ui.searchBox });
},
onClickReset: function() {
this.fetchGraphData({ refresh: true });
this.ui.typeSearch.data({ refresh: true }).val("").trigger("change");
this.ui.filterServiceType.data({ refresh: true }).val("").trigger("change");
},
onClickSaveSvg: function(e, a) {
this.LineageHelperRef.exportLineage({ downloadFileName: "TypeSystemView" });
},
onClickFullscreenToggler: function(e) {
var icon = $(e.currentTarget).find("i"),
......@@ -324,42 +342,65 @@ define([
icon.parent("button").attr("data-original-title", "Default View");
}
panel.toggleClass("fullscreen-mode");
var node = this.$("svg.main").parent()[0].getBoundingClientRect();
this.LineageHelperRef.updateOptions({
width: node.width,
height: node.height
});
},
updateDetails: function(data) {
this.$("[data-id='typeName']").text(Utils.getName(data));
delete data.id;
this.selectedDetailNode = {};
this.selectedDetailNode.atttributes = data.attributeDefs;
this.selectedDetailNode.businessAttributes = data.businessAttributeDefs;
this.selectedDetailNode.relationshipAttributes = data.relationshipAttributeDefs;
//atttributes
data["atttributes"] = (data.attributeDefs || []).map(function(obj) {
return obj.name;
});
delete data.attributeDefs;
//businessAttributes
data["businessAttributes"] = _.keys(data.businessAttributeDefs);
delete data.businessAttributeDefs;
//relationshipAttributes
data["relationshipAttributes"] = (data.relationshipAttributeDefs || []).map(function(obj) {
return obj.name;
});
delete data.relationshipAttributeDefs;
console.log(data);
this.ui.nodeDetailTable.html(
CommonViewFunction.propertyTable({
scope: this,
guidHyperLink: false,
getValue: function(val, key) {
if (key && key.toLowerCase().indexOf("time") > 0) {
return Utils.formatDate({ date: val });
} else {
return val;
}
},
getArrayOfStringElement: function(val, key) {
var def = null,
classname = "json-string";
if (key === "atttributes" || key === "businessAttributes" || key === "relationshipAttributes") {
def = key;
classname += " cursor";
}
return "<li class='" + classname + "' " + (def ? 'data-def="' + def + '" data-attribute="' + val + '"' : '') + ">" + val + "</li>"
},
getArrayOfStringFormat: function(valueArray) {
return valueArray.join("");
},
getEmptyString: function(key) {
if (key === "subTypes" || key === "superTypes" || key === "atttributes" || key === "relationshipAttributes") {
return "[]";
}
return "N/A";
},
valueObject: _.omit(data, ["isLineage", "isIncomplete", "label", "shape", "toolTipLabel", "updatedValues"]),
valueObject: _.omit(data, ["id", "attributeDefs", "relationshipAttributeDefs", "businessAttributeDefs", "isLineage", "isIncomplete", "label", "shape", "toolTipLabel", "updatedValues"]),
sortBy: true
})
);
},
createGraph: function(refresh) {
createGraph: function(opt) {
this.LineageHelperRef.createGraph();
},
filterData: function(value) {
......@@ -377,12 +418,14 @@ define([
setDataManually: true,
width: node.width,
height: node.height,
isShowHoverPath: true,
zoom: true,
fitToScreen: true,
dagreOptions: {
rankdir: "tb"
},
toolTipTitle: "Type",
isShowHoverPath: function() { return that.ui.showOnlyHoverPath.prop('checked') },
isShowTooltip: function() { return that.ui.showTooltip.prop('checked') },
onNodeClick: function(d) {
that.onClickNodeToggler();
that.updateDetails(that.LineageHelperRef.getNode(d.clickedData, true));
......@@ -425,14 +468,17 @@ define([
this.ui.typeSearch
.select2({
closeOnSelect: true,
placeholder: "Select Node"
placeholder: "Select Type"
})
.on("change.select2", function(e) {
e.stopPropagation();
e.stopImmediatePropagation();
var selectedNode = $('[data-id="typeSearch"]').val();
//that.searchNodeObj.selectedNode = selectedNode;
that.LineageHelperRef.searchNode({ guid: selectedNode });
if (!that.ui.typeSearch.data("refresh")) {
var selectedNode = $('[data-id="typeSearch"]').val();
that.LineageHelperRef.searchNode({ guid: selectedNode });
} else {
that.ui.typeSearch.data("refresh", false);
}
});
if (!this.ui.filterServiceType.data("select2")) {
this.ui.filterServiceType
......@@ -443,15 +489,13 @@ define([
.on("change.select2", function(e) {
e.stopPropagation();
e.stopImmediatePropagation();
var selectedNode = $('[data-id="filterServiceType"]').val();
that.filterData(selectedNode);
//that.searchNodeObj.selectedNode = selectedNode;
//that.LineageHelperRef.searchNode({ guid: selectedNode });
if (!that.ui.filterServiceType.data("refresh")) {
var selectedNode = $('[data-id="filterServiceType"]').val();
that.filterData(selectedNode);
} else {
that.ui.filterServiceType.data("refresh", false);
}
});
// if (this.searchNodeObj.selectedNode) {
// this.ui.typeSearch.val(this.searchNodeObj.selectedNode);
// this.ui.typeSearch.trigger("change.select2");
// }
}
}
});
......
......@@ -180,6 +180,11 @@ pre {
.json-string {
color: olive;
&.cursor {
cursor: pointer;
text-decoration: underline;
}
}
}
......@@ -191,6 +196,11 @@ pre {
.panel-body .memory-details {
pre {
&.code-block {
&.fixed-height {
max-height: 112px;
overflow: auto;
}
&.shrink {
height: 144px;
......
......@@ -197,7 +197,7 @@ span#zoom_in {
width: 100%;
right: 0;
padding: 0 !important;
z-index: 9999;
z-index: 99;
overflow: hidden !important;
background: white;
......@@ -277,4 +277,38 @@ span#zoom_in {
box-shadow: 0px 0px 3px 1px #80808080;
}
}
.box-panel.fix-box {
position: fixed;
top: 0;
right: 0;
bottom: 0;
height: 100vh;
max-height: 100vh;
z-index: 999;
bottom: 0;
width: 400px;
overflow: auto;
border-radius: 0px;
margin: 0 !important;
&.slide-from-left.size-lg {
left: -413px;
&.show-box-panel {
left: 0;
margin: 0 !important;
}
}
.body {
tbody {
overflow: auto;
height: calc(100vh - 48px);
position: absolute;
padding-bottom: 15px;
}
}
}
\ No newline at end of file
......@@ -41,6 +41,7 @@ tr.empty {
}
.entity-detail-table,
.type-node-details,
.relationship-detail-table {
position: relative;
......@@ -66,6 +67,26 @@ tr.empty {
}
}
.type-node-details {
.header {
.pretty.p-switch .state:before {
border: 1px solid white;
}
.pretty.p-switch .state label:after {
background-color: white !important;
}
.pretty.p-switch.p-fill input:checked~.state label:after {
background-color: #4a90e2 !important;
}
.pretty.p-switch.p-fill input:checked~.state.p-primary:before {
background-color: white !important;
}
}
}
.backgrid {
td {
white-space: normal;
......@@ -98,6 +119,14 @@ tr.empty {
}
}
}
.debuggging-table-header {
padding-right: 0px !important;
button {
float: right;
}
}
}
.backgrid-paginator ul {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -374,7 +374,7 @@ const LineageUtils = {
reader.addEventListener("load", () => callback(reader.result));
reader.readAsDataURL(file);
},
imgShapeRender: function (parent, bbox, node, { dagreD3, defsEl, imgBasePath, guid }) {
imgShapeRender: function (parent, bbox, node, { dagreD3, defsEl, imgBasePath, guid, isRankdirToBottom }) {
var that = this,
viewGuid = guid,
imageIconPath = this.getEntityIconPath({ entityData: node, imgBasePath }),
......@@ -391,7 +391,7 @@ const LineageUtils = {
var shapeSvg = parent
.append("circle")
.attr("fill", "url(#img_" + imgName + ")")
.attr("r", "24px")
.attr("r", isRankdirToBottom ? "30px" : "24px")
.attr("data-stroke", node.id)
.attr("stroke-width", "2px")
.attr("class", "nodeImage " + (currentNode ? "currentNode" : node.isProcess ? "process" : "node"));
......@@ -478,8 +478,8 @@ const LineageUtils = {
});
}
})
.attr("x", "4")
.attr("y", currentNode ? "3" : "4")
.attr("x", isRankdirToBottom ? "11" : "4")
.attr("y", isRankdirToBottom ? "20" : currentNode ? "3" : "4")
.attr("width", "40")
.attr("height", "40");
}
......
......@@ -26,6 +26,7 @@ import "./styles/style.scss";
export default class LineageHelper {
constructor(options) {
this.options = {};
this._updateOptions(options);
const { el, manualTrigger = false } = this.options;
if (el === undefined) {
......@@ -33,6 +34,7 @@ export default class LineageHelper {
}
this.initReturnObj = {
init: (arg) => this.init(arg),
updateOptions: (options) => this._updateAllOptions(options),
createGraph: (opt = {}) => this._createGraph(this.options, this.graphOptions, opt),
clear: (arg) => this.clear(arg),
refresh: (arg) => this.refresh(arg),
......@@ -78,12 +80,27 @@ export default class LineageHelper {
return this.initReturnObj;
}
/**
* [updateAllOptions]
* @param {[type]}
* @return {[type]}
*/
_updateAllOptions(options) {
Object.assign(this.options, options);
var svgRect = this.svg.node().getBoundingClientRect();
this.graphOptions.width = this.options.width || svgRect.width;
this.graphOptions.height = this.options.height || svgRect.height;
const { svg, width, height, guid } = this.graphOptions;
const { fitToScreen } = this.options;
svg.select("g").node().removeAttribute("transform");
svg.attr("viewBox", "0 0 " + width + " " + height).attr("enable-background", "new 0 0 " + width + " " + height);
this.centerAlign({ fitToScreen, guid });
}
/**
* [updateOptions get the options from user and appedn add it in this,option context]
* @param {[Object]} options [lib options from user]
* @return {[null]} [null]
*/
_updateOptions(options) {
this.options = {};
Object.assign(this.options, { filterObj: { isProcessHideCheck: false, isDeletedEntityHideCheck: false } }, options);
}
/**
......@@ -200,7 +217,7 @@ export default class LineageHelper {
if (node && node.attributes) {
downloadFileName = `${node.attributes.qualifiedName || node.attributes.name || "lineage_export"}.png`;
} else {
downloadFileName = "lineage_export.png";
downloadFileName = "export.png";
}
}
......@@ -258,6 +275,7 @@ export default class LineageHelper {
this.svg = select(el);
if (!(el instanceof SVGElement)) {
this.svg.selectAll("*").remove();
this.svg = this.svg
.append("svg")
.attr("xmlns", "http://www.w3.org/2000/svg")
......@@ -385,7 +403,19 @@ export default class LineageHelper {
* @return {[type]} [description]
*/
_createGraph(
{ data = {}, imgBasePath, isShowTooltip, isShowHoverPath, onLabelClick, onPathClick, onNodeClick, zoom, fitToScreen },
{
data = {},
imgBasePath,
isShowTooltip,
isShowHoverPath,
onLabelClick,
onPathClick,
onNodeClick,
zoom,
fitToScreen,
getToolTipContent,
toolTipTitle
},
graphOptions,
{ refresh }
) {
......@@ -393,7 +423,8 @@ export default class LineageHelper {
this.options.beforeRender();
}
const that = this,
{ svg, g, width, height } = graphOptions;
{ svg, g, width, height } = graphOptions,
isRankdirToBottom = this.options.dagreOptions && this.options.dagreOptions.rankdir === "tb";
if (svg instanceof selection === false) {
throw new Error("svg is not initialized or something went wrong while creatig graph instance");
......@@ -428,6 +459,7 @@ export default class LineageHelper {
render.shapes().img = function () {
return LineageUtils.imgShapeRender(...arguments, {
...graphOptions,
isRankdirToBottom: isRankdirToBottom,
imgBasePath: that._getValueFromUser(imgBasePath),
defsEl
});
......@@ -437,19 +469,26 @@ export default class LineageHelper {
.attr("class", "d3-tip")
.offset([10, 0])
.html((d) => {
var value = g.node(d);
var htmlStr = "";
if (value.id !== this.guid) {
htmlStr = "<h5 style='text-align: center;'>" + (value.isLineage ? "Lineage" : "Impact") + "</h5>";
}
htmlStr += "<h5 class='text-center'><span style='color:#359f89'>" + value.toolTipLabel + "</span></h5> ";
if (value.typeName) {
htmlStr += "<h5 class='text-center'><span>(" + value.typeName + ")</span></h5> ";
}
if (value.queryText) {
htmlStr += "<h5>Query: <span style='color:#359f89'>" + value.queryText + "</span></h5> ";
if (getToolTipContent && typeof getToolTipContent === "function") {
return getToolTipContent(d, g.node(d));
} else {
var value = g.node(d);
var htmlStr = "";
if (toolTipTitle) {
htmlStr = "<h5 style='text-align: center;'>" + toolTipTitle + "</h5>";
} else if (value.id !== this.guid) {
htmlStr = "<h5 style='text-align: center;'>" + (value.isLineage ? "Lineage" : "Impact") + "</h5>";
}
htmlStr += "<h5 class='text-center'><span style='color:#359f89'>" + value.toolTipLabel + "</span></h5> ";
if (value.typeName) {
htmlStr += "<h5 class='text-center'><span>(" + value.typeName + ")</span></h5> ";
}
if (value.queryText) {
htmlStr += "<h5>Query: <span style='color:#359f89'>" + value.queryText + "</span></h5> ";
}
return "<div class='tip-inner-scroll'>" + htmlStr + "</div>";
}
return "<div class='tip-inner-scroll'>" + htmlStr + "</div>";
});
svg.call(tooltip);
......@@ -463,7 +502,12 @@ export default class LineageHelper {
//change text postion
svgGroupEl
.selectAll("g.nodes g.label")
.attr("transform", "translate(2,-35)")
.attr("transform", () => {
if (isRankdirToBottom) {
return "translate(2,-20)";
}
return "translate(2,-35)";
})
.on("mouseenter", function (d) {
event.preventDefault();
select(this).classed("highlight", true);
......
......@@ -37,7 +37,7 @@
<div id="r_adminTableLayoutView">
</div>
</div>
<div id="tab-typeSystem" role="typeSystem" class="tab-pane animated fadeIn" style="position: relative;">
<div id="tab-typeSystem" role="typeSystem" class="tab-pane" style="position: relative;">
<div id="r_typeSystemTreeLayoutView">
</div>
</div>
......
......@@ -94,7 +94,7 @@
</div>
</div>
</div>
<div id="tab-lineage" role="lineage" class="tab-pane animated fadeIn">
<div id="tab-lineage" role="lineage" class="tab-pane">
<div id="r_lineageLayoutView" class="animated position-relative" align="center">
<div class="fontLoader-relative">
<i class="fa fa-refresh fa-spin-custom"></i>
......
......@@ -124,22 +124,22 @@
</button>
</div>
</div>
<div class="box-panel size-lg node-details slide-from-left lineage-node-detail">
<div class="header clearfix">
<h4><span data-id="typeName"></span></h4>
<span data-id="box-close" class="btn btn-sm btn-close lineage-node-detail-close"><i class="fa fa-close"></i></span>
<span data-id="box-close" class="btn btn-sm btn-close lineage-node-detail-close"><i class="fa fa-close"></i></span>
</div>
<div class="body">
<table class="table bold-key">
<tbody data-id="nodeDetailTable"></tbody>
</table>
</div>
</div>
<div class="fontLoader">
<i class="fa fa-refresh fa-spin-custom"></i>
</div>
<div class="legends pull-left" style="height: 25px; padding: 2px;"></div>
<div class="svg" style="height: 100%; width: 100%"></div>
</div>
<div class="box-panel size-lg slide-from-left lineage-node-detail fix-box">
<div class="header clearfix">
<h4><span data-id="typeName"></span></h4>
<span data-id="box-close" class="btn btn-sm btn-close lineage-node-detail-close"><i class="fa fa-close"></i></span>
<span data-id="box-close" class="btn btn-sm btn-close lineage-node-detail-close"><i class="fa fa-close"></i></span>
</div>
<div class="body">
<table class="table bold-key">
<tbody data-id="nodeDetailTable"></tbody>
</table>
</div>
</div>
<div class="hidden-svg"></div>
\ No newline at end of file
......@@ -15,16 +15,30 @@
* limitations under the License.
-->
<div id="typeSystemTreeViewPage" data-id="typeSystemTreeViewPage" class="systemTypeTree" style="height: calc(100vh - 180px); width: 100%; position: relative;overflow: hidden;">
<div class="box-panel size-lg node-details slide-from-left lineage-node-detail">
<div class="box-panel size-lg type-node-details fix-box slide-from-left lineage-node-detail">
<div class="header clearfix">
<h4><span data-id="typeName"></span></h4>
<span data-id="box-close" class="btn btn-sm btn-close lineage-node-detail-close"><i class="fa fa-close"></i></span>
<span data-id="box-close" class="btn btn-sm btn-close lineage-node-detail-close"><i class="fa fa-close"></i></span>
<div class="typeDetailHeader">
<h4 style="padding-right: 67px;"><span data-id="typeName"></span></h4>
<div class="pretty p-switch p-fill" style="position: absolute;top: 13px;right: 32px;">
<input type="checkbox" data-id="noValueToggle" title="Show empty values" />
<div class="state p-primary">
<label></label>
</div>
</div>
<span data-id="box-close" class="btn btn-sm btn-close "><i class="fa fa-close"></i></span>
</div>
<div class="typeAttrDetailHeader" style="display: none;">
<span data-id="box-back" class="btn btn-sm btn-close" style="left: 0px; right: auto;"><i class="fa fa-angle-left"></i></span>
<h4 style="padding-left: 27px;"><span data-id="typeAttrDetailHeader"></span></h4>
</div>
</div>
<div class="body">
<table class="table bold-key">
<tbody data-id="nodeDetailTable"></tbody>
<tbody data-id="nodeDetailTable" class="hide-empty-value"></tbody>
</table>
<div data-id="attribute-table" style="height: calc(100vh - 60px);display: none">
<pre class="code-block" style="height: 100%"></pre>
</div>
</div>
</div>
<div class="fontLoader">
......@@ -49,7 +63,6 @@
<div class="body">
<div class="col-sm-12 no-padding">
<div class="srchType clearfix">
<label class="srchTitle">Search Lineage Entity: </label>
<div class="">
<div class="col-sm-12 no-padding temFilter">
<select data-id="typeSearch"></select>
......@@ -59,28 +72,62 @@
</div>
</div>
</div>
<div class="box-panel setting-box">
<div class="header clearfix">
<h4>Settings</h4>
<span data-id="box-close" class="btn btn-sm btn-close"><i class="fa fa-close"></i></span>
</div>
<div class="body">
<div class="showOnlyHoverPath form-group text-left col-sm-12">
<div class="pretty p-switch p-fill">
<input type="checkbox" checked class="pull-left" data-id="showOnlyHoverPath" value="" />
<div class="state p-primary">
<label>On hover show current path</label>
</div>
</div>
</div>
<div class="showTooltip form-group text-left col-sm-12">
<div class="pretty p-switch p-fill">
<input type="checkbox" class="pull-left" data-id="showTooltip" value="" />
<div class="state p-primary">
<label>Show node details on hover</label>
</div>
</div>
</div>
</div>
</div>
<div class="graph-button-group pull-right">
<div>
<button data-id="reset" class="btn btn-action btn-gray btn-sm" title="Realign Lineage">
<button data-id="reset" class="btn btn-action btn-gray btn-sm" title="Reset">
<i class="fa fa-retweet"></i>
</button>
</div>
<div>
<button data-id="saveSvg" class="btn btn-action btn-gray btn-sm" title="Export to PNG">
<i class="fa fa-camera"></i>
</button>
</div>
<div>
<button type="button" data-id="setting-toggler" title="Settings" class="btn btn-action btn-gray btn-sm">
<i class="fa fa-gear"></i>
</button>
</div>
<div>
<button type="button" data-id="filter-toggler" title="Filter" class="btn btn-action btn-gray btn-sm"><i class="fa fa-filter"></i></button>
</div>
<div>
<button type="button" data-id="search-toggler" title="Search" class="btn btn-action btn-gray btn-sm"><i class="fa fa-search"></i></button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-action btn-gray btn-sm lineageZoomButton" title="Zoom In" data-id="zoom-in">
<button type="button" class="btn btn-action btn-gray btn-sm" title="Zoom In" data-id="zoom-in">
<i class="fa fa-search-plus"></i>
</button>
<button type="button" class="btn btn-action btn-gray btn-sm lineageZoomButton" title="Zoom Out" data-id="zoom-out">
<button type="button" class="btn btn-action btn-gray btn-sm" title="Zoom Out" data-id="zoom-out">
<i class="fa fa-search-minus"></i>
</button>
</div>
<div>
<button type="button" data-id="fullScreen-toggler" title="Full screen" class="btn btn-action btn-gray btn-sm fullscreen_lineage">
<button type="button" data-id="fullScreen-toggler" title="Full screen" class="btn btn-action btn-gray btn-sm">
<i class="fa fa-expand"></i>
</button>
</div>
......
......@@ -79,6 +79,8 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
sortBy = options.sortBy,
valueObject = options.valueObject,
extractJSON = options.extractJSON,
getArrayOfStringElement = options.getArrayOfStringElement,
getArrayOfStringFormat = options.getArrayOfStringFormat,
isTable = _.isUndefined(options.isTable) ? true : options.isTable,
attributeDefs = options.attributeDefs,
formatIntVal = options.formatIntVal,
......@@ -108,6 +110,9 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
return "N/A";
},
getValue = function(val, key) {
if (options && options.getValue) {
val = options.getValue(val, key);
}
if (!_.isUndefined(val) && !_.isNull(val)) {
if ((_.isNumber(val) || !_.isNaN(parseInt(val))) && formatIntVal) {
return numberFormat(val);
......@@ -185,7 +190,12 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
if (_.isString(inputOutputField) || _.isBoolean(inputOutputField) || _.isNumber(inputOutputField)) {
var tempVarfor$check = inputOutputField.toString();
if (tempVarfor$check.indexOf("$") == -1) {
valueOfArray.push('<span class="json-string">' + getValue(inputOutputField, key) + '</span>');
var tmpVal = getValue(inputOutputField, key)
if (getArrayOfStringElement) {
valueOfArray.push(getArrayOfStringElement(tmpVal, key));
} else {
valueOfArray.push('<span class="json-string">' + tmpVal + '</span>');
}
}
} else if (_.isObject(inputOutputField) && !id) {
var attributesList = inputOutputField;
......@@ -251,7 +261,11 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
}
}
if (valueOfArray.length) {
subLink = valueOfArray.join(', ');
if (getArrayOfStringFormat) {
subLink = getArrayOfStringFormat(valueOfArray, key);
} else {
subLink = valueOfArray.join(', ');
}
}
return subLink === "" ? getEmptyString(key) : subLink;
}
......@@ -297,12 +311,17 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum
if (_.isObject(valueObject[key]) && !_.isEmpty(valueObject[key])) {
var matchedLinkString = val.match(/href|value-loader\w*/g),
matchedJson = val.match(/json-value|json-string\w*/g),
matchedKey = val.match(/json-key\w*/g),
isMatchLinkStringIsSingle = matchedLinkString && matchedLinkString.length <= 5,
isMatchJSONStringIsSingle = matchedJson && matchedJson.length == 1,
expandCollapseButton = "";
if ((matchedJson && !isMatchJSONStringIsSingle) || (matchedLinkString && !isMatchLinkStringIsSingle)) {
expandCollapseButton = '<button class="expand-collapse-button"><i class="fa"></i></button>';
htmlTag = '<pre class="shrink code-block ' + (isMatchJSONStringIsSingle ? 'fixed-height' : '') + '">' + expandCollapseButton + '<code>' + val + '</code></pre>';
if ((matchedJson) || (matchedLinkString)) {
var className = "code-block fixed-height";
if (!isMatchJSONStringIsSingle) {
className += " shrink";
expandCollapseButton = '<button class="expand-collapse-button"><i class="fa"></i></button>';
}
htmlTag = '<pre class="' + className + '">' + expandCollapseButton + '<code>' + val + '</code></pre>';
}
}
table += '<tr class="' + appendClass + '"><td>' + (_.escape(key) + listCount) + '</td><td>' + htmlTag + '</td></tr>';
......
......@@ -134,13 +134,13 @@ define(['require',
},
onShow: function() {
this.$('.fontLoader').show();
this.$el.resizable({
handles: ' s',
minHeight: 375,
stop: function(event, ui) {
ui.element.height(($(this).height()));
},
});
// this.$el.resizable({
// handles: ' s',
// minHeight: 375,
// stop: function(event, ui) {
// ui.element.height(($(this).height()));
// },
// });
},
onClickLineageFullscreenToggler: function(e) {
var icon = $(e.currentTarget).find('i'),
......@@ -152,6 +152,11 @@ define(['require',
icon.parent('button').attr("data-original-title", "Default View");
}
panel.toggleClass('fullscreen-mode');
var node = this.$("svg").parent()[0].getBoundingClientRect();
this.LineageHelperRef.updateOptions({
width: node.width,
height: node.height
});
},
onCheckUnwantedEntity: function(e) {
var that = this;
......@@ -210,6 +215,8 @@ define(['require',
},
onClickResetLineage: function() {
this.LineageHelperRef.refresh();
this.searchNodeObj.selectedNode = "";
this.ui.lineageTypeSearch.data({ refresh: true }).val("").trigger("change");
},
onClickSaveSvg: function(e, a) {
this.LineageHelperRef.exportLineage();
......@@ -249,10 +256,6 @@ define(['require',
})
},
createGraph: function(data) {
// if (_.isEmpty(this.g._nodes)) {
// this.$('svg').html('<text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle">No relations to display</text>');
// return;
// }
var that = this;
$('.resizeGraph').css("height", this.$('.svg').height() + "px");
......@@ -364,9 +367,13 @@ define(['require',
}).on('change.select2', function(e) {
e.stopPropagation();
e.stopImmediatePropagation();
var selectedNode = $('[data-id="typeSearch"]').val();
that.searchNodeObj.selectedNode = selectedNode;
that.LineageHelperRef.searchNode({ guid: selectedNode });
if (!that.ui.lineageTypeSearch.data("refresh")) {
var selectedNode = $('[data-id="typeSearch"]').val();
that.searchNodeObj.selectedNode = selectedNode;
that.LineageHelperRef.searchNode({ guid: selectedNode });
} else {
that.ui.lineageTypeSearch.data("refresh", false);
}
});
if (this.searchNodeObj.selectedNode) {
this.ui.lineageTypeSearch.val(this.searchNodeObj.selectedNode);
......
......@@ -55,16 +55,23 @@ define([
typeSystemTreeViewPage: "[data-id='typeSystemTreeViewPage']",
boxClose: '[data-id="box-close"]',
nodeDetailTable: '[data-id="nodeDetailTable"]',
attributeTable: '[data-id="attribute-table"]',
typeSearch: '[data-id="typeSearch"]',
filterServiceType: '[data-id="filterServiceType"]',
onZoomIn: '[data-id="zoom-in"]',
onZoomOut: '[data-id="zoom-out"]',
filterBox: ".filter-box",
searchBox: ".search-box",
settingBox: '.setting-box',
filterToggler: '[data-id="filter-toggler"]',
settingToggler: '[data-id="setting-toggler"]',
searchToggler: '[data-id="search-toggler"]',
reset: '[data-id="reset"]',
fullscreenToggler: '[data-id="fullScreen-toggler"]'
fullscreenToggler: '[data-id="fullScreen-toggler"]',
noValueToggle: "[data-id='noValueToggle']",
showOnlyHoverPath: '[data-id="showOnlyHoverPath"]',
showTooltip: '[data-id="showTooltip"]',
saveSvg: '[data-id="saveSvg"]',
},
/** ui events hash */
events: function() {
......@@ -73,9 +80,19 @@ define([
events["click " + this.ui.onZoomIn] = "onClickZoomIn";
events["click " + this.ui.onZoomOut] = "onClickZoomOut";
events["click " + this.ui.filterToggler] = "onClickFilterToggler";
events["click " + this.ui.settingToggler] = 'onClickSettingToggler';
events["click " + this.ui.searchToggler] = "onClickSearchToggler";
events["click " + this.ui.saveSvg] = 'onClickSaveSvg';
events["click " + this.ui.fullscreenToggler] = "onClickFullscreenToggler";
events["click " + this.ui.reset] = "onClickReset";
events["click " + this.ui.noValueToggle] = function() {
this.showAllProperties = !this.showAllProperties;
this.ui.noValueToggle.attr("data-original-title", (this.showAllProperties ? "Hide" : "Show") + " empty values");
Utils.togglePropertyRelationshipTableEmptyValues({
"inputType": this.ui.noValueToggle,
"tableEl": this.ui.nodeDetailTable
});
};
return events;
},
......@@ -90,7 +107,35 @@ define([
this.initializeGraph();
this.fetchGraphData();
},
onRender: function() {},
onRender: function() {
var that = this;
this.$el.on("click", "code li[data-def]", function() {
if (that.selectedDetailNode) {
var dataObj = $(this).data(),
defObj = that.selectedDetailNode[dataObj.def],
newData = null;
if (dataObj.def === "businessAttributes") {
newData = defObj[dataObj.attribute];
} else {
newData = _.filter(defObj, { name: dataObj.attribute });
}
that.ui.attributeTable.find("pre").html('<code style="max-height: 100%">' + Utils.JSONPrettyPrint(newData, function(val) {
return val;
}) + '</code>');
that.$el.find('[data-id="typeAttrDetailHeader"]').text(dataObj.def);
that.ui.nodeDetailTable.hide("slide", { direction: "right" }, 400);
that.ui.attributeTable.show("slide", { direction: "left" }, 400);
that.$el.find(".typeDetailHeader").hide();
that.$el.find(".typeAttrDetailHeader").show()
}
});
this.$el.on("click", "span[data-id='box-back']", function() {
that.ui.nodeDetailTable.show("slide", { direction: "right" }, 400);
that.ui.attributeTable.hide("slide", { direction: "left" }, 400);
that.$el.find(".typeDetailHeader").show();
that.$el.find(".typeAttrDetailHeader").hide()
})
},
fetchGraphData: function(options) {
var that = this;
var entityTypeDef = that.entityDefCollection.fullCollection.toJSON();
......@@ -101,7 +146,7 @@ define([
}
if (entityTypeDef.length) {
that.generateData($.extend(true, {}, { data: entityTypeDef }, options)).then(function(graphObj) {
that.createGraph();
that.createGraph(options);
});
}
},
......@@ -161,91 +206,56 @@ define([
if (options.data) {
if (options.filter) {
var pendingSubList = {},
pendingSuperList = {},
temp = {},
doneList = {},
traveseSubSuper = function(obj, ignoreSubTypes) {
var fromEntityId = obj.guid;
if (!ignoreSubTypes && obj.subTypes.length) {
_.each(obj.subTypes, function(subType) {
var tempObj = doneList[subType] || temp[subType];
if (tempObj) {
// filter
var pendingSuperList = {},
outOfFilterData = {},
doneList = {};
var linkParents = function(obj) {
if (obj && obj.superTypes.length) {
_.each(obj.superTypes, function(superType) {
var fromEntityId = obj.guid;
var tempObj = doneList[superType] || outOfFilterData[superType];
if (tempObj) {
if (!doneList[superType]) {
setNode(tempObj.guid, tempObj);
setEdge(fromEntityId, tempObj.guid);
} else {
if (pendingSubList[subType]) {
pendingSubList[subType].push(fromEntityId);
} else {
pendingSubList[subType] = [fromEntityId];
}
}
});
}
if (obj.superTypes.length) {
_.each(obj.superTypes, function(superType) {
var tempObj = doneList[superType] || temp[superType];
if (tempObj) {
setNode(tempObj.guid, tempObj);
setEdge(tempObj.guid, fromEntityId);
if (tempObj.superTypes.length) {
traveseSubSuper(tempObj, true);
}
setEdge(tempObj.guid, fromEntityId);
linkParents(tempObj);
} else {
if (pendingSuperList[superType]) {
pendingSuperList[superType].push(fromEntityId);
} else {
if (pendingSuperList[superType]) {
pendingSuperList[superType].push(fromEntityId);
} else {
pendingSuperList[superType] = [fromEntityId];
}
pendingSuperList[superType] = [fromEntityId];
}
});
}
};
}
});
}
}
_.each(options.data, function(obj) {
var fromEntityId = obj.guid;
if (pendingSuperList[obj.name]) {
doneList[obj.name] = obj;
setNode(fromEntityId, obj);
_.map(pendingSuperList[obj.name], function(guid) {
setEdge(fromEntityId, guid);
});
delete pendingSuperList[obj.name];
linkParents(obj);
}
if (obj.serviceType === options.filter) {
doneList[obj.name] = obj;
setNode(fromEntityId, obj);
if (pendingSubList[obj.name]) {
_.map(pendingSubList[obj.name], function(guid) {
setEdge(guid, fromEntityId);
});
delete pendingSubList[obj.name];
}
if (pendingSuperList[obj.name]) {
_.map(pendingSuperList[obj.name], function(guid) {
setEdge(fromEntityId, guid);
});
delete pendingSuperList[obj.name];
}
traveseSubSuper(obj);
} else {
if (pendingSubList[obj.name]) {
setNode(fromEntityId, obj);
doneList[obj.name] = obj;
_.map(pendingSubList[obj.name], function(guid) {
setEdge(guid, fromEntityId);
});
delete pendingSubList[obj.name];
}
if (pendingSuperList[obj.name]) {
var fromEntityId = obj.guid;
setNode(fromEntityId, obj);
doneList[obj.name] = obj;
_.map(pendingSuperList[obj.name], function(guid) {
setEdge(fromEntityId, guid);
});
delete pendingSuperList[obj.name];
}
if (!doneList[obj.name]) {
temp[obj.name] = obj;
}
linkParents(obj);
} else if (!doneList[obj.name] && !outOfFilterData[obj.name]) {
outOfFilterData[obj.name] = obj;
}
});
pendingSubList = null;
pendingSuperList = null;
doneList = null;
outOfFilterData = null;
} else {
// Without filter
var pendingList = {},
doneList = {};
......@@ -308,11 +318,19 @@ define([
onClickFilterToggler: function() {
this.toggleBoxPanel({ el: this.ui.filterBox });
},
onClickSettingToggler: function() {
this.toggleBoxPanel({ el: this.ui.settingBox });
},
onClickSearchToggler: function() {
this.toggleBoxPanel({ el: this.ui.searchBox });
},
onClickReset: function() {
this.fetchGraphData({ refresh: true });
this.ui.typeSearch.data({ refresh: true }).val("").trigger("change");
this.ui.filterServiceType.data({ refresh: true }).val("").trigger("change");
},
onClickSaveSvg: function(e, a) {
this.LineageHelperRef.exportLineage({ downloadFileName: "TypeSystemView" });
},
onClickFullscreenToggler: function(e) {
var icon = $(e.currentTarget).find("i"),
......@@ -324,42 +342,65 @@ define([
icon.parent("button").attr("data-original-title", "Default View");
}
panel.toggleClass("fullscreen-mode");
var node = this.$("svg.main").parent()[0].getBoundingClientRect();
this.LineageHelperRef.updateOptions({
width: node.width,
height: node.height
});
},
updateDetails: function(data) {
this.$("[data-id='typeName']").text(Utils.getName(data));
delete data.id;
this.selectedDetailNode = {};
this.selectedDetailNode.atttributes = data.attributeDefs;
this.selectedDetailNode.businessAttributes = data.businessAttributeDefs;
this.selectedDetailNode.relationshipAttributes = data.relationshipAttributeDefs;
//atttributes
data["atttributes"] = (data.attributeDefs || []).map(function(obj) {
return obj.name;
});
delete data.attributeDefs;
//businessAttributes
data["businessAttributes"] = _.keys(data.businessAttributeDefs);
delete data.businessAttributeDefs;
//relationshipAttributes
data["relationshipAttributes"] = (data.relationshipAttributeDefs || []).map(function(obj) {
return obj.name;
});
delete data.relationshipAttributeDefs;
console.log(data);
this.ui.nodeDetailTable.html(
CommonViewFunction.propertyTable({
scope: this,
guidHyperLink: false,
getValue: function(val, key) {
if (key && key.toLowerCase().indexOf("time") > 0) {
return Utils.formatDate({ date: val });
} else {
return val;
}
},
getArrayOfStringElement: function(val, key) {
var def = null,
classname = "json-string";
if (key === "atttributes" || key === "businessAttributes" || key === "relationshipAttributes") {
def = key;
classname += " cursor";
}
return "<li class='" + classname + "' " + (def ? 'data-def="' + def + '" data-attribute="' + val + '"' : '') + ">" + val + "</li>"
},
getArrayOfStringFormat: function(valueArray) {
return valueArray.join("");
},
getEmptyString: function(key) {
if (key === "subTypes" || key === "superTypes" || key === "atttributes" || key === "relationshipAttributes") {
return "[]";
}
return "N/A";
},
valueObject: _.omit(data, ["isLineage", "isIncomplete", "label", "shape", "toolTipLabel", "updatedValues"]),
valueObject: _.omit(data, ["id", "attributeDefs", "relationshipAttributeDefs", "businessAttributeDefs", "isLineage", "isIncomplete", "label", "shape", "toolTipLabel", "updatedValues"]),
sortBy: true
})
);
},
createGraph: function(refresh) {
createGraph: function(opt) {
this.LineageHelperRef.createGraph();
},
filterData: function(value) {
......@@ -377,12 +418,14 @@ define([
setDataManually: true,
width: node.width,
height: node.height,
isShowHoverPath: true,
zoom: true,
fitToScreen: true,
dagreOptions: {
rankdir: "tb"
},
toolTipTitle: "Type",
isShowHoverPath: function() { return that.ui.showOnlyHoverPath.prop('checked') },
isShowTooltip: function() { return that.ui.showTooltip.prop('checked') },
onNodeClick: function(d) {
that.onClickNodeToggler();
that.updateDetails(that.LineageHelperRef.getNode(d.clickedData, true));
......@@ -425,14 +468,17 @@ define([
this.ui.typeSearch
.select2({
closeOnSelect: true,
placeholder: "Select Node"
placeholder: "Select Type"
})
.on("change.select2", function(e) {
e.stopPropagation();
e.stopImmediatePropagation();
var selectedNode = $('[data-id="typeSearch"]').val();
//that.searchNodeObj.selectedNode = selectedNode;
that.LineageHelperRef.searchNode({ guid: selectedNode });
if (!that.ui.typeSearch.data("refresh")) {
var selectedNode = $('[data-id="typeSearch"]').val();
that.LineageHelperRef.searchNode({ guid: selectedNode });
} else {
that.ui.typeSearch.data("refresh", false);
}
});
if (!this.ui.filterServiceType.data("select2")) {
this.ui.filterServiceType
......@@ -443,15 +489,13 @@ define([
.on("change.select2", function(e) {
e.stopPropagation();
e.stopImmediatePropagation();
var selectedNode = $('[data-id="filterServiceType"]').val();
that.filterData(selectedNode);
//that.searchNodeObj.selectedNode = selectedNode;
//that.LineageHelperRef.searchNode({ guid: selectedNode });
if (!that.ui.filterServiceType.data("refresh")) {
var selectedNode = $('[data-id="filterServiceType"]').val();
that.filterData(selectedNode);
} else {
that.ui.filterServiceType.data("refresh", false);
}
});
// if (this.searchNodeObj.selectedNode) {
// this.ui.typeSearch.val(this.searchNodeObj.selectedNode);
// this.ui.typeSearch.trigger("change.select2");
// }
}
}
});
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment