You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by pi...@apache.org on 2022/07/28 07:50:25 UTC
[atlas] branch master updated: ATLAS-4607: UI improvements to support Atlas Lineage fetch on-demand
This is an automated email from the ASF dual-hosted git repository.
pinal pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/atlas.git
The following commit(s) were added to refs/heads/master by this push:
new 6a1f2ef5c ATLAS-4607: UI improvements to support Atlas Lineage fetch on-demand
6a1f2ef5c is described below
commit 6a1f2ef5c1cdcbc001c6ea74f5cbcfdf9c98f448
Author: Farhan Khan <fa...@cloudera.com>
AuthorDate: Tue Jul 26 16:02:46 2022 +0530
ATLAS-4607: UI improvements to support Atlas Lineage fetch on-demand
Signed-off-by: Pinal Shah <pi...@freestoneinfotech.com>
---
dashboardv2/public/img/entity-icon/expandBtn.svg | 24 +
dashboardv2/public/js/collection/VLineageList.js | 6 +-
.../js/external_lib/atlas-lineage/dist/index.js | 2 +-
.../js/external_lib/atlas-lineage/dist/styles.css | 3 +-
.../atlas-lineage/src/Utils/DataUtils.js | 675 ++++++++++----------
.../atlas-lineage/src/Utils/LineageUtils.js | 259 ++++----
.../js/external_lib/atlas-lineage/src/index.js | 98 ++-
.../atlas-lineage/src/styles/graph.scss | 28 +-
dashboardv2/public/js/main.js | 6 +
.../js/templates/graph/LineageLayoutView_tmpl.html | 12 +-
dashboardv2/public/js/utils/Globals.js | 4 +
dashboardv2/public/js/utils/Helper.js | 11 +-
.../public/js/views/graph/LineageLayoutView.js | 206 ++++++-
dashboardv3/public/img/entity-icon/expandBtn.svg | 24 +
dashboardv3/public/js/collection/VLineageList.js | 6 +-
.../js/external_lib/atlas-lineage/dist/index.js | 2 +-
.../js/external_lib/atlas-lineage/dist/styles.css | 3 +-
.../atlas-lineage/src/Utils/DataUtils.js | 679 +++++++++++----------
.../atlas-lineage/src/Utils/LineageUtils.js | 259 ++++----
.../js/external_lib/atlas-lineage/src/index.js | 98 ++-
.../atlas-lineage/src/styles/graph.scss | 28 +-
dashboardv3/public/js/main.js | 6 +
.../js/templates/graph/LineageLayoutView_tmpl.html | 12 +-
dashboardv3/public/js/utils/Globals.js | 4 +
dashboardv3/public/js/utils/Helper.js | 9 +-
.../public/js/views/graph/LineageLayoutView.js | 206 ++++++-
26 files changed, 1649 insertions(+), 1021 deletions(-)
diff --git a/dashboardv2/public/img/entity-icon/expandBtn.svg b/dashboardv2/public/img/entity-icon/expandBtn.svg
new file mode 100644
index 000000000..88693e74b
--- /dev/null
+++ b/dashboardv2/public/img/entity-icon/expandBtn.svg
@@ -0,0 +1,24 @@
+<!--
+ * 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.
+ -->
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#4a90e2">
+ <g>
+ <path d="M12,2A10,10,0,1,0,22,12,10.011,10.011,0,0,0,12,2Zm0,18a8,8,0,1,1,8-8A8.009,8.009,0,0,1,12,20Z"/>
+ <polygon points="12 10.586 8.707 7.293 7.293 8.707 12 13.414 16.707 8.707 15.293 7.293 12 10.586"/>
+ <polygon points="12 14.586 8.707 11.293 7.293 12.707 12 17.414 16.707 12.707 15.293 11.293 12 14.586"/>
+ </g>
+</svg>
diff --git a/dashboardv2/public/js/collection/VLineageList.js b/dashboardv2/public/js/collection/VLineageList.js
index bda649220..4f980a737 100644
--- a/dashboardv2/public/js/collection/VLineageList.js
+++ b/dashboardv2/public/js/collection/VLineageList.js
@@ -42,7 +42,11 @@ define(['require',
dataType: 'json'
}, options);
- return this.constructor.nonCrudOperation.call(this, url, 'GET', options);
+ if (options.compactLineageEnabled) {
+ return this.constructor.nonCrudOperation.call(this, url, 'POST', options);
+ } else {
+ return this.constructor.nonCrudOperation.call(this, url, 'GET', options);
+ }
}
},
//Static Class Members
diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/dist/index.js b/dashboardv2/public/js/external_lib/atlas-lineage/dist/index.js
index b31ee4911..6a184ee6e 100644
--- a/dashboardv2/public/js/external_lib/atlas-lineage/dist/index.js
+++ b/dashboardv2/public/js/external_lib/atlas-lineage/dist/index.js
@@ -1 +1 @@
-!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("platform"),require("dagreD3")):"function"==typeof define&&define.amd?define(["platform","dagreD3"],e):"object"==typeof exports?exports.LineageHelper=e(require("platform"),require("dagreD3")):t.LineageHelper=e(t.platform,t.dagreD3)}(window,(function(t,e){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i. [...]
\ No newline at end of file
+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("platform"),require("dagreD3")):"function"==typeof define&&define.amd?define(["platform","dagreD3"],e):"object"==typeof exports?exports.LineageHelper=e(require("platform"),require("dagreD3")):t.LineageHelper=e(t.platform,t.dagreD3)}(window,(function(t,e){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i. [...]
\ No newline at end of file
diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/dist/styles.css b/dashboardv2/public/js/external_lib/atlas-lineage/dist/styles.css
index 2d7f9d9de..3bcce59e5 100644
--- a/dashboardv2/public/js/external_lib/atlas-lineage/dist/styles.css
+++ b/dashboardv2/public/js/external_lib/atlas-lineage/dist/styles.css
@@ -1,2 +1 @@
-.node{cursor:pointer}.node text{font-size:10px;font-family:sans-serif}.node .label{fill:#868686}.node .label.highlight{cursor:pointer;fill:#4a90e2;text-decoration:underline}.node .label.highlight tspan{font-weight:400}.node circle{-moz-transition:all 0.3s;-webkit-transition:all 0.3s;transition:all 0.3s;stroke-width:1.5px}.node circle.node-detail-highlight{stroke:#4a90e2;stroke-width:2px}.node circle.nodeImage.green:hover{stroke:#ffb203}.node circle.nodeImage.blue:hover{stroke:#4b91e2}.no [...]
-
+.node{cursor:pointer}.node text{font-size:10px;font-family:sans-serif}.node .label{fill:#868686}.node .label.highlight{cursor:pointer;fill:#4a90e2;text-decoration:underline}.node .label.highlight tspan{font-weight:400}.node circle{-moz-transition:all 0.3s;-webkit-transition:all 0.3s;transition:all 0.3s;stroke-width:1.5px}.node circle.node-detail-highlight{stroke:#4a90e2;stroke-width:2px}.node circle.nodeImage.green:hover{stroke:#ffb203}.node circle.nodeImage.blue:hover{stroke:#4b91e2}.no [...]
diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/DataUtils.js b/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/DataUtils.js
index 1255eb070..50068ab77 100644
--- a/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/DataUtils.js
+++ b/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/DataUtils.js
@@ -19,343 +19,350 @@ import Enums from "../Enums";
import { curveBasis } from "d3-shape";
const DataUtils = {
- /**
- * [getBaseUrl description]
- * @param {[type]} url [description]
- * @return {[type]} [description]
- */
- getBaseUrl: function(url) {
- return url.replace(/\/[\w-]+.(jsp|html)|\/+$/gi, "");
- },
- /**
- * [getEntityIconPath description]
- * @param {[type]} options.entityData [description]
- * @param {Object} options.errorUrl } [description]
- * @return {[type]} [description]
- */
- getEntityIconPath: function({ entityData, errorUrl } = {}) {
- var serviceType,
- status,
- typeName,
- iconBasePath = this.getBaseUrl(window.location.pathname) + Globals.entityImgPath;
- if (entityData) {
- typeName = entityData.typeName;
- serviceType = entityData && entityData.serviceType;
- status = entityData && entityData.status;
- }
+ /**
+ * [getBaseUrl description]
+ * @param {[type]} url [description]
+ * @return {[type]} [description]
+ */
+ getBaseUrl: function(url) {
+ return url.replace(/\/[\w-]+.(jsp|html)|\/+$/gi, "");
+ },
+ /**
+ * [getEntityIconPath description]
+ * @param {[type]} options.entityData [description]
+ * @param {Object} options.errorUrl } [description]
+ * @return {[type]} [description]
+ */
+ getEntityIconPath: function({ entityData, errorUrl } = {}) {
+ var serviceType,
+ status,
+ typeName,
+ iconBasePath = this.getBaseUrl(window.location.pathname) + Globals.entityImgPath;
+ if (entityData) {
+ typeName = entityData.typeName;
+ serviceType = entityData && entityData.serviceType;
+ status = entityData && entityData.status;
+ }
- function getImgPath(imageName) {
- return iconBasePath + (Enums.entityStateReadOnly[status] ? "disabled/" + imageName : imageName);
- }
+ function getImgPath(imageName) {
+ return iconBasePath + (Enums.entityStateReadOnly[status] ? "disabled/" + imageName : imageName);
+ }
- function getDefaultImgPath() {
- if (entityData.isProcess) {
- if (Enums.entityStateReadOnly[status]) {
- return iconBasePath + "disabled/process.png";
- } else {
- return iconBasePath + "process.png";
- }
- } else {
- if (Enums.entityStateReadOnly[status]) {
- return iconBasePath + "disabled/table.png";
- } else {
- return iconBasePath + "table.png";
- }
- }
- }
+ function getDefaultImgPath() {
+ if (entityData.isProcess) {
+ if (Enums.entityStateReadOnly[status]) {
+ return iconBasePath + "disabled/process.png";
+ } else {
+ return iconBasePath + "process.png";
+ }
+ } else {
+ if (Enums.entityStateReadOnly[status]) {
+ return iconBasePath + "disabled/table.png";
+ } else {
+ return iconBasePath + "table.png";
+ }
+ }
+ }
- if (entityData) {
- if (errorUrl) {
- var isErrorInTypeName = errorUrl && errorUrl.match("entity-icon/" + typeName + ".png|disabled/" + typeName + ".png") ? true : false;
- if (serviceType && isErrorInTypeName) {
- var imageName = serviceType + ".png";
- return getImgPath(imageName);
- } else {
- return getDefaultImgPath();
- }
- } else if (entityData.typeName) {
- var imageName = entityData.typeName + ".png";
- return getImgPath(imageName);
- } else {
- return getDefaultImgPath();
- }
- }
- },
- /**
- * [isProcess description]
- * @param {[type]} options.typeName [description]
- * @param {[type]} options.superTypes [description]
- * @param {[type]} options.entityDef [description]
- * @return {Boolean} [description]
- */
- isProcess: function({ typeName, superTypes, entityDef }) {
- if (typeName == "Process") {
- return true;
- }
- return superTypes.indexOf("Process") > -1;
- },
- /**
- * [isDeleted description]
- * @param {[type]} node [description]
- * @return {Boolean} [description]
- */
- isDeleted: function(node) {
- if (node === undefined) {
- return;
- }
- return Enums.entityStateReadOnly[node.status];
- },
- isNodeToBeUpdated: function(node, filterObj) {
- var isProcessHideCheck = filterObj.isProcessHideCheck,
- isDeletedEntityHideCheck = filterObj.isDeletedEntityHideCheck;
- var returnObj = {
- isProcess: isProcessHideCheck && node.isProcess,
- isDeleted: isDeletedEntityHideCheck && node.isDeleted
- };
- returnObj["update"] = returnObj.isProcess || returnObj.isDeleted;
- return returnObj;
- },
- /**
- * [getServiceType description]
- * @param {[type]} options.typeName [description]
- * @param {[type]} options.entityDef [description]
- * @return {[type]} [description]
- */
- getServiceType: function({ typeName, entityDef }) {
- var serviceType = null;
- if (typeName) {
- if (entityDef) {
- serviceType = entityDef.serviceType || null;
- }
- }
- return serviceType;
- },
- /**
- * [getEntityDef description]
- * @param {[type]} options.typeName [description]
- * @param {[type]} options.entityDefCollection [description]
- * @return {[type]} [description]
- */
- getEntityDef: function({ typeName, entityDefCollection }) {
- var entityDef = null;
- if (typeName) {
- entityDef = entityDefCollection.find(function(obj) {
- return obj.name == typeName;
- });
- }
- return entityDef;
- },
- /**
- * [getNestedSuperTypes description]
- * @param {[type]} options.entityDef [description]
- * @param {[type]} options.entityDefCollection [description]
- * @return {[type]} [description]
- */
- getNestedSuperTypes: function({ entityDef, entityDefCollection }) {
- var data = entityDef,
- collection = entityDefCollection,
- superTypes = new Set();
+ if (entityData) {
+ if (errorUrl) {
+ var isErrorInTypeName = errorUrl && errorUrl.match("entity-icon/" + typeName + ".png|disabled/" + typeName + ".png") ? true : false;
+ if (serviceType && isErrorInTypeName) {
+ var imageName = serviceType + ".png";
+ return getImgPath(imageName);
+ } else {
+ return getDefaultImgPath();
+ }
+ } else if (entityData.typeName) {
+ var imageName = entityData.typeName + ".png";
+ return getImgPath(imageName);
+ } else {
+ return getDefaultImgPath();
+ }
+ }
+ },
+ /**
+ * [isProcess description]
+ * @param {[type]} options.typeName [description]
+ * @param {[type]} options.superTypes [description]
+ * @param {[type]} options.entityDef [description]
+ * @return {Boolean} [description]
+ */
+ isProcess: function({ typeName, superTypes, entityDef }) {
+ if (typeName == "Process") {
+ return true;
+ }
+ return superTypes.indexOf("Process") > -1;
+ },
+ /**
+ * [isDeleted description]
+ * @param {[type]} node [description]
+ * @return {Boolean} [description]
+ */
+ isDeleted: function(node) {
+ if (node === undefined) {
+ return;
+ }
+ return Enums.entityStateReadOnly[node.status];
+ },
+ isNodeToBeUpdated: function(node, filterObj) {
+ var isProcessHideCheck = filterObj.isProcessHideCheck,
+ isDeletedEntityHideCheck = filterObj.isDeletedEntityHideCheck;
+ var returnObj = {
+ isProcess: isProcessHideCheck && node.isProcess,
+ isDeleted: isDeletedEntityHideCheck && node.isDeleted
+ };
+ returnObj["update"] = returnObj.isProcess || returnObj.isDeleted;
+ if (node.label === "Expand") {
+ returnObj["update"] = true;
+ }
+ return returnObj;
+ },
+ /**
+ * [getServiceType description]
+ * @param {[type]} options.typeName [description]
+ * @param {[type]} options.entityDef [description]
+ * @return {[type]} [description]
+ */
+ getServiceType: function({ typeName, entityDef }) {
+ var serviceType = null;
+ if (typeName) {
+ if (entityDef) {
+ serviceType = entityDef.serviceType || null;
+ }
+ }
+ return serviceType;
+ },
+ /**
+ * [getEntityDef description]
+ * @param {[type]} options.typeName [description]
+ * @param {[type]} options.entityDefCollection [description]
+ * @return {[type]} [description]
+ */
+ getEntityDef: function({ typeName, entityDefCollection }) {
+ var entityDef = null;
+ if (typeName) {
+ entityDef = entityDefCollection.find(function(obj) {
+ return obj.name == typeName;
+ });
+ }
+ return entityDef;
+ },
+ /**
+ * [getNestedSuperTypes description]
+ * @param {[type]} options.entityDef [description]
+ * @param {[type]} options.entityDefCollection [description]
+ * @return {[type]} [description]
+ */
+ getNestedSuperTypes: function({ entityDef, entityDefCollection }) {
+ var data = entityDef,
+ collection = entityDefCollection,
+ superTypes = new Set();
- var getData = function(data, collection) {
- if (data) {
- if (data.superTypes && data.superTypes.length) {
- data.superTypes.forEach(function(superTypeName) {
- superTypes.add(superTypeName);
- var collectionData = collection.find(function(obj) {
- obj.name === superTypeName;
- });
- if (collectionData) {
- getData(collectionData, collection);
- }
- });
- }
- }
- };
- getData(data, collection);
- return Array.from(superTypes);
- },
- generateData: function({ data = {}, filterObj, entityDefCollection, g, guid, setGraphEdge, setGraphNode }) {
- return new Promise((resolve, reject) => {
- try {
- var relations = data.relations || {},
- guidEntityMap = data.guidEntityMap || {},
- isHideFilterOn = filterObj.isProcessHideCheck || filterObj.isDeletedEntityHideCheck,
- newHashMap = {},
- styleObj = {
- fill: "none",
- stroke: "#ffb203",
- width: 3
- },
- makeNodeData = (relationObj) => {
- if (relationObj) {
- if (relationObj.updatedValues) {
- return relationObj;
- }
- var obj = Object.assign(relationObj, {
- shape: "img",
- updatedValues: true,
- label: relationObj.displayText.trunc(18),
- toolTipLabel: relationObj.displayText,
- id: relationObj.guid,
- isLineage: true,
- isIncomplete: relationObj.isIncomplete,
- entityDef: this.getEntityDef({ typeName: relationObj.typeName, entityDefCollection })
- });
- obj["serviceType"] = this.getServiceType(obj);
- obj["superTypes"] = this.getNestedSuperTypes({
- ...obj,
- entityDefCollection: entityDefCollection
- });
- obj["isProcess"] = this.isProcess(obj);
- obj["isDeleted"] = this.isDeleted(obj);
- return obj;
- }
- },
- crateLineageRelationshipHashMap = function({ relations } = {}) {
- var newHashMap = {};
- relations.forEach(function(obj) {
- if (newHashMap[obj.fromEntityId]) {
- newHashMap[obj.fromEntityId].push(obj.toEntityId);
- } else {
- newHashMap[obj.fromEntityId] = [obj.toEntityId];
- }
- });
- return newHashMap;
- },
- getStyleObjStr = function(styleObj) {
- return "fill:" + styleObj.fill + ";stroke:" + styleObj.stroke + ";stroke-width:" + styleObj.width;
- },
- getNewToNodeRelationship = (toNodeGuid, filterObj) => {
- if (toNodeGuid && relationshipMap[toNodeGuid]) {
- var newRelationship = [];
- relationshipMap[toNodeGuid].forEach((guid) => {
- var nodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[guid]), filterObj);
- if (nodeToBeUpdated.update) {
- var newRelation = getNewToNodeRelationship(guid, filterObj);
- if (newRelation) {
- newRelationship = newRelationship.concat(newRelation);
- }
- } else {
- newRelationship.push(guid);
- }
- });
- return newRelationship;
- } else {
- return null;
- }
- },
- getToNodeRelation = (toNodes, fromNodeToBeUpdated, filterObj) => {
- var toNodeRelationship = [];
- toNodes.forEach((toNodeGuid) => {
- var toNodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[toNodeGuid]), filterObj);
- if (toNodeToBeUpdated.update) {
- // To node need to updated
- if (pendingFromRelationship[toNodeGuid]) {
- toNodeRelationship = toNodeRelationship.concat(pendingFromRelationship[toNodeGuid]);
- } else {
- var newToNodeRelationship = getNewToNodeRelationship(toNodeGuid, filterObj);
- if (newToNodeRelationship) {
- toNodeRelationship = toNodeRelationship.concat(newToNodeRelationship);
- }
- }
- } else {
- //when bothe node not to be updated.
- toNodeRelationship.push(toNodeGuid);
- }
- });
- return toNodeRelationship;
- },
- setNode = (guid) => {
- if (!g._nodes[guid]) {
- var nodeData = makeNodeData(guidEntityMap[guid]);
- setGraphNode(guid, nodeData);
- return nodeData;
- } else {
- return g._nodes[guid];
- }
- },
- setEdge = function(fromNodeGuid, toNodeGuid, opt = {}) {
- setGraphEdge(fromNodeGuid, toNodeGuid, {
- arrowhead: "arrowPoint",
- curve: curveBasis,
- style: getStyleObjStr(styleObj),
- styleObj: styleObj,
- ...opt
- });
- },
- setGraphData = function(fromEntityId, toEntityId) {
- setNode(fromEntityId);
- setNode(toEntityId);
- setEdge(fromEntityId, toEntityId);
- },
- pendingFromRelationship = {};
- if (isHideFilterOn) {
- var relationshipMap = crateLineageRelationshipHashMap(data);
- Object.keys(relationshipMap).forEach((fromNodeGuid) => {
- var toNodes = relationshipMap[fromNodeGuid],
- fromNodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[fromNodeGuid]), filterObj),
- toNodeList = getToNodeRelation(toNodes, fromNodeToBeUpdated, filterObj);
- if (fromNodeToBeUpdated.update) {
- if (pendingFromRelationship[fromNodeGuid]) {
- pendingFromRelationship[fromNodeGuid] = pendingFromRelationship[fromNodeGuid].concat(toNodeList);
- } else {
- pendingFromRelationship[fromNodeGuid] = toNodeList;
- }
- } else {
- toNodeList.forEach(function(toNodeGuid) {
- setGraphData(fromNodeGuid, toNodeGuid);
- });
- }
- });
- } else {
- relations.forEach(function(obj) {
- setGraphData(obj.fromEntityId, obj.toEntityId);
- });
- }
- if (g._nodes[guid]) {
- if (g._nodes[guid]) {
- g._nodes[guid]["isLineage"] = false;
- }
- this.findImpactNodeAndUpdateData({
- guid,
- g,
- setEdge,
- getStyleObjStr
- });
- }
- resolve(g);
- } catch (e) {
- reject(e);
- }
- });
- },
- findImpactNodeAndUpdateData: function({ guid, getStyleObjStr, g, setEdge }) {
- var that = this,
- traversedMap = {},
- styleObj = {
- fill: "none",
- stroke: "#fb4200",
- width: 3
- },
- traversed = function(toNodeList = {}, fromNodeGuid) {
- let toNodeKeyList = Object.keys(toNodeList);
- if (toNodeKeyList.length) {
- if (!traversedMap[fromNodeGuid]) {
- traversedMap[fromNodeGuid] = true;
- toNodeKeyList.forEach(function(toNodeGuid) {
- if (g._nodes[toNodeGuid]) {
- g._nodes[toNodeGuid]["isLineage"] = false;
- }
- setEdge(fromNodeGuid, toNodeGuid, {
- style: getStyleObjStr(styleObj),
- styleObj: styleObj
- });
- traversed(g._sucs[toNodeGuid], toNodeGuid);
- });
- }
- }
- };
- traversed(g._sucs[guid], guid);
- }
+ var getData = function(data, collection) {
+ if (data) {
+ if (data.superTypes && data.superTypes.length) {
+ data.superTypes.forEach(function(superTypeName) {
+ superTypes.add(superTypeName);
+ var collectionData = collection.find(function(obj) {
+ obj.name === superTypeName;
+ });
+ if (collectionData) {
+ getData(collectionData, collection);
+ }
+ });
+ }
+ }
+ };
+ getData(data, collection);
+ return Array.from(superTypes);
+ },
+ generateData: function({ data = {}, filterObj, entityDefCollection, g, guid, setGraphEdge, setGraphNode }) {
+ return new Promise((resolve, reject) => {
+ try {
+ var relations = data.relations || {},
+ guidEntityMap = data.guidEntityMap || {},
+ isHideFilterOn = filterObj.isProcessHideCheck || filterObj.isDeletedEntityHideCheck,
+ newHashMap = {},
+ styleObj = {
+ fill: "none",
+ stroke: "#ffb203",
+ width: 3
+ },
+ makeNodeData = (relationObj) => {
+ if (relationObj) {
+ if (relationObj.updatedValues) {
+ return relationObj;
+ }
+ var nodeLabel = relationObj.displayText ? relationObj.displayText : " ",
+ obj = Object.assign(relationObj, {
+ shape: "img",
+ updatedValues: true,
+ label: nodeLabel.trunc(18),
+ toolTipLabel: nodeLabel,
+ id: relationObj.guid,
+ isLineage: true,
+ isIncomplete: relationObj.isIncomplete,
+ entityDef: this.getEntityDef({ typeName: relationObj.typeName, entityDefCollection })
+ });
+ obj["serviceType"] = this.getServiceType(obj);
+ obj["superTypes"] = this.getNestedSuperTypes({
+ ...obj,
+ entityDefCollection: entityDefCollection
+ });
+ obj["isProcess"] = this.isProcess(obj);
+ obj["isDeleted"] = this.isDeleted(obj);
+ return obj;
+ }
+ },
+ crateLineageRelationshipHashMap = function({ relations } = {}) {
+ var newHashMap = {};
+ relations.forEach(function(obj) {
+ if (newHashMap[obj.fromEntityId]) {
+ newHashMap[obj.fromEntityId].push(obj.toEntityId);
+ } else {
+ newHashMap[obj.fromEntityId] = [obj.toEntityId];
+ }
+ });
+ return newHashMap;
+ },
+ getStyleObjStr = function(styleObj) {
+ return "fill:" + styleObj.fill + ";stroke:" + styleObj.stroke + ";stroke-width:" + styleObj.width;
+ },
+ getNewToNodeRelationship = (toNodeGuid, filterObj) => {
+ if (toNodeGuid && relationshipMap[toNodeGuid]) {
+ var newRelationship = [];
+ relationshipMap[toNodeGuid].forEach((guid) => {
+ var nodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[guid]), filterObj);
+ if (nodeToBeUpdated.update) {
+ var newRelation = getNewToNodeRelationship(guid, filterObj);
+ if (newRelation) {
+ newRelationship = newRelationship.concat(newRelation);
+ }
+ } else {
+ newRelationship.push(guid);
+ }
+ });
+ return newRelationship;
+ } else {
+ return null;
+ }
+ },
+ getToNodeRelation = (toNodes, fromNodeToBeUpdated, filterObj) => {
+ var toNodeRelationship = [];
+ toNodes.forEach((toNodeGuid) => {
+ var toNodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[toNodeGuid]), filterObj);
+ if (toNodeToBeUpdated.update) {
+ // To node need to updated
+ if (pendingFromRelationship[toNodeGuid]) {
+ toNodeRelationship = toNodeRelationship.concat(pendingFromRelationship[toNodeGuid]);
+ } else {
+ var newToNodeRelationship = getNewToNodeRelationship(toNodeGuid, filterObj);
+ if (newToNodeRelationship) {
+ toNodeRelationship = toNodeRelationship.concat(newToNodeRelationship);
+ }
+ }
+ } else {
+ //when bothe node not to be updated.
+ toNodeRelationship.push(toNodeGuid);
+ }
+ });
+ return toNodeRelationship;
+ },
+ setNode = (guid) => {
+ if (!g._nodes[guid]) {
+ var nodeData = makeNodeData(guidEntityMap[guid]);
+ setGraphNode(guid, nodeData);
+ return nodeData;
+ } else {
+ return g._nodes[guid];
+ }
+ },
+ setEdge = function(fromNodeGuid, toNodeGuid, opt = {}) {
+ setGraphEdge(fromNodeGuid, toNodeGuid, {
+ arrowhead: "arrowPoint",
+ curve: curveBasis,
+ style: getStyleObjStr(styleObj),
+ styleObj: styleObj,
+ ...opt
+ });
+ },
+ setGraphData = function(fromEntityId, toEntityId) {
+ setNode(fromEntityId);
+ setNode(toEntityId);
+ setEdge(fromEntityId, toEntityId);
+ },
+ pendingFromRelationship = {};
+ if (isHideFilterOn) {
+ var relationshipMap = crateLineageRelationshipHashMap(data);
+ Object.keys(relationshipMap).forEach((fromNodeGuid) => {
+ var toNodes = relationshipMap[fromNodeGuid],
+ fromNodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[fromNodeGuid]), filterObj),
+ toNodeList = getToNodeRelation(toNodes, fromNodeToBeUpdated, filterObj);
+ if (fromNodeToBeUpdated.update) {
+ if (pendingFromRelationship[fromNodeGuid]) {
+ pendingFromRelationship[fromNodeGuid] = pendingFromRelationship[fromNodeGuid].concat(toNodeList);
+ } else {
+ pendingFromRelationship[fromNodeGuid] = toNodeList;
+ }
+ } else {
+ toNodeList.forEach(function(toNodeGuid) {
+ setGraphData(fromNodeGuid, toNodeGuid);
+ });
+ }
+ });
+ } else {
+ relations.forEach(function(obj) {
+ setGraphData(obj.fromEntityId, obj.toEntityId);
+ });
+ }
+ if (g._nodes[guid]) {
+ if (g._nodes[guid]) {
+ g._nodes[guid]["isLineage"] = false;
+ }
+ this.findImpactNodeAndUpdateData({
+ guid,
+ g,
+ setEdge,
+ getStyleObjStr
+ });
+ }
+ if (!g._nodes[guid]) {
+ setNode(guid);
+ }
+ resolve(g);
+ } catch (e) {
+ reject(e);
+ }
+ });
+ },
+ findImpactNodeAndUpdateData: function({ guid, getStyleObjStr, g, setEdge }) {
+ var that = this,
+ traversedMap = {},
+ styleObj = {
+ fill: "none",
+ stroke: "#fb4200",
+ width: 3
+ },
+ traversed = function(toNodeList = {}, fromNodeGuid) {
+ let toNodeKeyList = Object.keys(toNodeList);
+ if (toNodeKeyList.length) {
+ if (!traversedMap[fromNodeGuid]) {
+ traversedMap[fromNodeGuid] = true;
+ toNodeKeyList.forEach(function(toNodeGuid) {
+ if (g._nodes[toNodeGuid]) {
+ g._nodes[toNodeGuid]["isLineage"] = false;
+ }
+ setEdge(fromNodeGuid, toNodeGuid, {
+ style: getStyleObjStr(styleObj),
+ styleObj: styleObj
+ });
+ traversed(g._sucs[toNodeGuid], toNodeGuid);
+ });
+ }
+ }
+ };
+ traversed(g._sucs[guid], guid);
+ }
};
export default DataUtils;
\ No newline at end of file
diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/LineageUtils.js b/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/LineageUtils.js
index 448a95ae6..588e3ac67 100644
--- a/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/LineageUtils.js
+++ b/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/LineageUtils.js
@@ -31,25 +31,25 @@ const LineageUtils = {
* @type {Number}
*/
nodeArrowDistance: 24,
- refreshGraphForSafari: function (options) {
+ refreshGraphForSafari: function(options) {
var edgePathEl = options.edgeEl,
IEGraphRenderDone = 0;
- edgePathEl.each(function (argument) {
+ edgePathEl.each(function(argument) {
var eleRef = this,
childNode = $(this).find("pattern");
- setTimeout(function (argument) {
+ setTimeout(function(argument) {
$(eleRef).find("defs").append(childNode);
}, 500);
});
},
- refreshGraphForIE: function ({ edgePathEl }) {
+ refreshGraphForIE: function({ edgePathEl }) {
var IEGraphRenderDone = 0;
- edgePathEl.each(function (argument) {
+ edgePathEl.each(function(argument) {
var childNode = $(this).find("marker");
$(this).find("marker").remove();
var eleRef = this;
++IEGraphRenderDone;
- setTimeout(function (argument) {
+ setTimeout(function(argument) {
$(eleRef).find("defs").append(childNode);
--IEGraphRenderDone;
if (IEGraphRenderDone === 0) {
@@ -67,9 +67,9 @@ const LineageUtils = {
* @param {[type]} options.edgePathEl [description]
* @return {[type]} [description]
*/
- dragNode: function ({ g, svg, guid, edgePathEl }) {
+ dragNode: function({ g, svg, guid, edgePathEl }) {
var dragHelper = {
- dragmove: function (el, d) {
+ dragmove: function(el, d) {
var node = select(el),
selectedNode = g.node(d),
prevX = selectedNode.x,
@@ -91,13 +91,13 @@ const LineageUtils = {
});
//LineageUtils.refreshGraphForIE({ edgePathEl: edgePathEl });
},
- translateEdge: function (e, dx, dy) {
- e.points.forEach(function (p) {
+ translateEdge: function(e, dx, dy) {
+ e.points.forEach(function(p) {
p.x = p.x + dx;
p.y = p.y + dy;
});
},
- calcPoints: function (e) {
+ calcPoints: function(e) {
var edge = g.edge(e.v, e.w),
tail = g.node(e.v),
head = g.node(e.w),
@@ -106,10 +106,10 @@ const LineageUtils = {
points.unshift(this.intersectRect(tail, points[0]));
points.push(this.intersectRect(head, points[points.length - 1]));
return line()
- .x(function (d) {
+ .x(function(d) {
return d.x;
})
- .y(function (d) {
+ .y(function(d) {
return d.y;
})
.curve(curveBasis)(points);
@@ -146,10 +146,10 @@ const LineageUtils = {
};
}
};
- var dragNodeHandler = drag().on("drag", function (d) {
+ var dragNodeHandler = drag().on("drag", function(d) {
dragHelper.dragmove.call(dragHelper, this, d);
}),
- dragEdgePathHandler = drag().on("drag", function (d) {
+ dragEdgePathHandler = drag().on("drag", function(d) {
dragHelper.translateEdge(g.edge(d.v, d.w), event.dx, event.dy);
var edgeObj = g.edge(d.v, d.w);
select(edgeObj.elem).select("path").attr("d", dragHelper.calcPoints(d));
@@ -158,16 +158,16 @@ const LineageUtils = {
dragNodeHandler(svg.selectAll("g.node"));
dragEdgePathHandler(svg.selectAll("g.edgePath"));
},
- zoomIn: function ({ svg, scaleFactor = 1.3 }) {
+ zoomIn: function({ svg, scaleFactor = 1.3 }) {
this.d3Zoom.scaleBy(svg.transition().duration(750), scaleFactor);
},
- zoomOut: function ({ svg, scaleFactor = 0.8 }) {
+ zoomOut: function({ svg, scaleFactor = 0.8 }) {
this.d3Zoom.scaleBy(svg.transition().duration(750), scaleFactor);
},
- zoom: function ({ svg, xa, ya, scale }) {
+ zoom: function({ svg, xa, ya, scale }) {
svg.transition().duration(750).call(this.d3Zoom.transform, zoomIdentity.translate(xa, ya).scale(scale));
},
- fitToScreen: function ({ svg }) {
+ fitToScreen: function({ svg }) {
var node = svg.node();
var bounds = node.getBBox();
@@ -197,14 +197,14 @@ const LineageUtils = {
* @param {[type]} options.onCenterZoomed [description]
* @return {[type]} [description]
*/
- centerNode: function ({ guid, g, svg, svgGroupEl, edgePathEl, width, height, fitToScreen, onCenterZoomed }) {
+ centerNode: function({ guid, g, svg, svgGroupEl, edgePathEl, width, height, fitToScreen, onCenterZoomed, isSelected }) {
this.d3Zoom = zoom();
svg.call(this.d3Zoom).on("dblclick.zoom", null);
// restrict events
let selectedNodeEl = svg.selectAll("g.nodes>g[id='" + guid + "']"),
- zoomListener = this.d3Zoom.scaleExtent([0.01, 50]).on("zoom", function () {
+ zoomListener = this.d3Zoom.scaleExtent([0.01, 50]).on("zoom", function() {
svgGroupEl.attr("transform", event.transform);
}),
x = null,
@@ -236,7 +236,13 @@ const LineageUtils = {
var xa = -(x * scale - width / 2),
ya = -(y * scale - height / 2);
this.zoom({ svg, xa, ya, scale });
- svg.transition().duration(750).call(this.d3Zoom.transform, zoomIdentity.translate(xa, ya).scale(scale));
+
+ if (!isSelected) {
+ svg.call(this.d3Zoom.transform, zoomIdentity.translate(xa, ya).scale(scale));
+ } else {
+ svg.transition().duration(750).call(this.d3Zoom.transform, zoomIdentity.translate(xa, ya).scale(scale));
+ }
+
if (onCenterZoomed) {
onCenterZoomed({ newScale: scale, newTranslate: [xa, ya], d3Zoom: this.d3Zoom, selectedNodeEl });
@@ -250,7 +256,7 @@ const LineageUtils = {
* @param {[type]} options.el [description]
* @return {[type]} [description]
*/
- getToolTipDirection: function ({ el }) {
+ getToolTipDirection: function({ el }) {
var width = select("body").node().getBoundingClientRect().width,
currentELWidth = select(el).node().getBoundingClientRect(),
direction = "e";
@@ -279,10 +285,10 @@ const LineageUtils = {
* @param {[type]} options.hoveredNode [description]
* @return {[type]} [description]
*/
- onHoverFade: function ({ svg, g, mouseenter, nodesToHighlight, hoveredNode }) {
+ onHoverFade: function({ svg, g, mouseenter, nodesToHighlight, hoveredNode }) {
var node = svg.selectAll(".node"),
path = svg.selectAll(".edgePath"),
- isConnected = function (a, b, o) {
+ isConnected = function(a, b, o) {
if (a === o || (b && b.length && b.indexOf(o) != -1)) {
return true;
}
@@ -292,14 +298,14 @@ const LineageUtils = {
var nextNode = g.successors(hoveredNode),
previousNode = g.predecessors(hoveredNode),
nodesToHighlight = nextNode.concat(previousNode);
- node.classed("hover-active-node", function (currentNode, i, nodes) {
+ node.classed("hover-active-node", function(currentNode, i, nodes) {
if (isConnected(hoveredNode, nodesToHighlight, currentNode)) {
return true;
} else {
return false;
}
});
- path.classed("hover-active-path", function (c) {
+ path.classed("hover-active-path", function(c) {
var _thisOpacity = c.v === hoveredNode || c.w === hoveredNode ? 1 : 0;
if (_thisOpacity) {
return true;
@@ -318,10 +324,10 @@ const LineageUtils = {
* @param {[type]} path [description]
* @return {[type]} [description]
*/
- getBaseUrl: function (url = window.location.pathname) {
+ getBaseUrl: function(url = window.location.pathname) {
return url.replace(/\/[\w-]+.(jsp|html)|\/+$/gi, "");
},
- getEntityIconPath: function ({ entityData, errorUrl, imgBasePath }) {
+ getEntityIconPath: function({ entityData, errorUrl, imgBasePath }) {
var iconBasePath = this.getBaseUrl() + (imgBasePath || "/img/entity-icon/");
if (entityData) {
let { typeName, serviceType, status, isProcess } = entityData;
@@ -348,7 +354,7 @@ const LineageUtils = {
if (errorUrl) {
// Check if the default img path has error, if yes then stop recursion.
- if (errorUrl.indexOf("table.png") > -1 || errorUrl.indexOf("process.png") > -1) {
+ if (errorUrl.indexOf("table.png") > -1) { //removed condition for default process image
return null;
}
var isErrorInTypeName = errorUrl && errorUrl.match("entity-icon/" + typeName + ".png|disabled/" + typeName + ".png") ? true : false;
@@ -369,15 +375,15 @@ const LineageUtils = {
}
}
},
- base64Encode: function (file, callback) {
+ base64Encode: function(file, callback) {
const reader = new FileReader();
reader.addEventListener("load", () => callback(reader.result));
reader.readAsDataURL(file);
},
- imgShapeRender: function (parent, bbox, node, { dagreD3, defsEl, imgBasePath, guid, isRankdirToBottom }) {
+ imgShapeRender: function(parent, bbox, node, { dagreD3, defsEl, imgBasePath, guid, isRankdirToBottom }) {
var that = this,
viewGuid = guid,
- imageIconPath = this.getEntityIconPath({ entityData: node, imgBasePath }),
+ imageIconPath = node.btnType ? "/img/entity-icon/expandBtn.svg" : this.getEntityIconPath({ entityData: node, imgBasePath }),
imgName = imageIconPath.split("/").pop();
if (this.imageObject === undefined) {
this.imageObject = {};
@@ -390,7 +396,7 @@ const LineageUtils = {
}
var shapeSvg = parent
.append("circle")
- .attr("fill", "url(#img_" + encodeURI(imgName) + ")")
+ .attr("fill", "url(#img_" + imgName + ")")
.attr("r", isRankdirToBottom ? "30px" : "24px")
.attr("data-stroke", node.id)
.attr("stroke-width", "2px")
@@ -401,90 +407,112 @@ const LineageUtils = {
if (node.isIncomplete === true) {
parent.attr("class", "node isIncomplete show");
parent
- .insert("foreignObject")
- .attr("x", "-25")
- .attr("y", "-25")
- .attr("width", "50")
- .attr("height", "50")
- .append("xhtml:div")
- .insert("i")
- .attr("class", "fa fa-hourglass-half");
+ .insert("rect")
+ .attr("x", "-5")
+ .attr("y", "-23")
+ .attr("width", "14")
+ .attr("height", "16")
+ .attr("fill", "url(#img_hourglass.svg)")
+ .attr("data-stroke", node.id)
+ .attr("stroke-width", "2px");
+
+ var patternConfigShellIcon = {
+ imgName: "hourglass.svg",
+ imageIconPath: "/img/entity-icon/hourglass.svg",
+ leftPosition: "0",
+ topPosition: "0",
+ width: "12",
+ height: "14"
+ };
+ svgPattern(patternConfigShellIcon);
}
+ var patternConfigEntityIcon = {
+ imgName: imgName,
+ imageIconPath: imageIconPath,
+ leftPosition: isRankdirToBottom ? "11" : "4",
+ topPosition: isRankdirToBottom ? "20" : currentNode ? "3" : "4",
+ width: "40",
+ height: "40"
+ };
+ svgPattern(patternConfigEntityIcon);
- if (defsEl.select('pattern[id="img_' + imgName + '"]').empty()) {
- defsEl
- .append("pattern")
- .attr("x", "0%")
- .attr("y", "0%")
- .attr("patternUnits", "objectBoundingBox")
- .attr("id", "img_" + imgName)
- .attr("width", "100%")
- .attr("height", "100%")
- .append("image")
- .attr("href", function (d) {
- var imgEl = this;
- if (node) {
- var getImageData = function (options) {
- var imagePath = options.imagePath,
- ajaxOptions = {
- url: imagePath,
- method: "GET",
- cache: true
- };
+ function svgPattern(patternConfig) {
+ if (defsEl.select('pattern[id="img_' + patternConfig.imgName + '"]').empty()) {
+ defsEl
+ .append("pattern")
+ .attr("x", "0%")
+ .attr("y", "0%")
+ .attr("patternUnits", "objectBoundingBox")
+ .attr("id", "img_" + patternConfig.imgName)
+ .attr("width", "100%")
+ .attr("height", "100%")
+ .append("image")
+ .attr("href", function(d) {
+ var imgEl = this;
+ if (node) {
+ var getImageData = function(options) {
+ var imagePath = options.imagePath,
+ ajaxOptions = {
+ url: imagePath,
+ method: "GET",
+ cache: true
+ };
- // if (platform.name !== "IE") {
- // ajaxOptions["mimeType"] = "text/plain; charset=x-user-defined";
- // }
- shapeSvg.attr("data-iconpath", imagePath);
- var xhr = new XMLHttpRequest();
- xhr.onreadystatechange = function () {
- if (xhr.readyState === 4) {
- if (xhr.status === 200) {
- if (platform.name !== "IE") {
- that.base64Encode(this.response, (url) => {
- that.imageObject[imageIconPath] = url;
- select(imgEl).attr("xlink:href", url);
- });
- } else {
- that.imageObject[imageIconPath] = imagePath;
- }
- if (imageIconPath !== shapeSvg.attr("data-iconpath")) {
- shapeSvg.attr("data-iconpathorigin", imageIconPath);
- }
- } else if (xhr.status === 404) {
- const imgPath = that.getEntityIconPath({ entityData: node, errorUrl: imagePath });
- if (imgPath === null) {
- const patternEL = select(imgEl.parentElement);
- patternEL.select("image").remove();
- patternEL
- .attr("patternContentUnits", "objectBoundingBox")
- .append("circle")
- .attr("r", "24px")
- .attr("fill", "#e8e8e8");
- } else {
- getImageData({
- imagePath: imgPath
- });
+ // if (platform.name !== "IE") {
+ // ajaxOptions["mimeType"] = "text/plain; charset=x-user-defined";
+ // }
+ shapeSvg.attr("data-iconpath", imagePath);
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === 4) {
+ if (xhr.status === 200) {
+ if (platform.name !== "IE") {
+ that.base64Encode(this.response, (url) => {
+ that.imageObject[patternConfig.imageIconPath] = url;
+ select(imgEl).attr("xlink:href", url);
+ });
+ } else {
+ that.imageObject[patternConfig.imageIconPath] = imagePath;
+ }
+ if (patternConfig.imageIconPath !== shapeSvg.attr("data-iconpath")) {
+ shapeSvg.attr("data-iconpathorigin", patternConfig.imageIconPath);
+ }
+ } else if (xhr.status === 404) {
+ const imgPath = that.getEntityIconPath({ entityData: node, errorUrl: imagePath });
+ if (imgPath === null) {
+ const patternEL = select(imgEl.parentElement);
+ patternEL.select("image").remove();
+ patternEL
+ .attr("patternContentUnits", "objectBoundingBox")
+ .append("circle")
+ .attr("r", "24px")
+ .attr("fill", "#e8e8e8");
+ } else {
+ getImageData({
+ imagePath: imgPath
+ });
+ }
}
}
- }
+ };
+ xhr.responseType = "blob";
+ xhr.open(ajaxOptions.method, ajaxOptions.url, true);
+ xhr.send(null);
};
- xhr.responseType = "blob";
- xhr.open(ajaxOptions.method, ajaxOptions.url, true);
- xhr.send(null);
- };
- getImageData({
- imagePath: imageIconPath
- });
- }
- })
- .attr("x", isRankdirToBottom ? "11" : "4")
- .attr("y", isRankdirToBottom ? "20" : currentNode ? "3" : "4")
- .attr("width", "40")
- .attr("height", "40");
+ getImageData({
+ imagePath: patternConfig.imageIconPath
+ });
+ }
+ })
+ .attr("x", patternConfig.leftPosition)
+ .attr("y", patternConfig.topPosition)
+ .attr("width", patternConfig.width)
+ .attr("height", patternConfig.height);
+ }
}
- node.intersect = function (point) {
+
+ node.intersect = function(point) {
return dagreD3.intersect.circle(node, currentNode ? that.nodeArrowDistance + 3 : that.nodeArrowDistance, point);
};
return shapeSvg;
@@ -494,7 +522,7 @@ const LineageUtils = {
* @param {[type]} {parent, id, edge, type, viewOptions [description]
* @return {[type]} [description]
*/
- arrowPointRender: function (parent, id, edge, type, { dagreD3 }) {
+ arrowPointRender: function(parent, id, edge, type, { dagreD3 }) {
var node = parent.node(),
parentNode = node ? node.parentNode : parent;
select(parentNode)
@@ -523,11 +551,11 @@ const LineageUtils = {
* @param {[type]} options.onExportLineage [description]
* @return {[type]} [description]
*/
- saveSvg: function ({ svg, width, height, downloadFileName, onExportLineage }) {
+ saveSvg: function({ svg, width, height, downloadFileName, onExportLineage }) {
var that = this,
svgClone = svg.clone(true).node(),
scaleFactor = 1;
- setTimeout(function () {
+ setTimeout(function() {
if (platform.name === "Firefox") {
svgClone.setAttribute("width", width);
svgClone.setAttribute("height", height);
@@ -570,15 +598,16 @@ const LineageUtils = {
if (platform.name === "Safari") {
svgBlob = new Blob([data], { type: "image/svg+xml" });
}
+ ctx.drawImage(img, 50, 50, canvas.width, canvas.height);
var url = DOMURL.createObjectURL(svgBlob);
- img.onload = function () {
+ img.onload = function() {
try {
var a = document.createElement("a");
a.download = downloadFileName;
document.body.appendChild(a);
ctx.drawImage(img, 50, 50, canvas.width, canvas.height);
- canvas.toBlob(function (blob) {
+ canvas.toBlob(function(blob) {
if (!blob) {
onExportLineage({ status: "failed", message: "There was an error in downloading Lineage!" });
return;
diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/src/index.js b/dashboardv2/public/js/external_lib/atlas-lineage/src/index.js
index 3ceb3d90a..0c4702237 100644
--- a/dashboardv2/public/js/external_lib/atlas-lineage/src/index.js
+++ b/dashboardv2/public/js/external_lib/atlas-lineage/src/index.js
@@ -45,6 +45,7 @@ export default class LineageHelper {
zoom: (arg) => this.zoom(arg),
fullScreen: (arg) => this.fullScreen(arg),
searchNode: (arg) => this.searchNode(arg),
+ displayFullName: (arg) => this.displayFullName(arg),
removeNodeSelection: (arg) => this.removeNodeSelection(arg),
getGraphOptions: () => this.graphOptions,
getNode: (guid, actual) => {
@@ -163,14 +164,36 @@ export default class LineageHelper {
zoom(opt = {}) {
LineageUtils.zoom({ ...this.graphOptions, ...opt });
}
+
+ displayFullName(opt = {}) {
+ var that = this;
+ this.g.nodes().forEach(function(v) {
+ var selectedNodeEl = that.svg.selectAll("g.nodes>g[id='" + v + "']"),
+ label = that.g.node(v).toolTipLabel;
+ if (opt.bLabelFullText == true)
+ selectedNodeEl.select('tspan').text(label);
+ else
+ selectedNodeEl.select('tspan').text(label.trunc(18));
+ });
+ if (this.selectedNode) {
+ this.searchNode({ guid: this.selectedNode });
+ }
+ }
+
/**
* [refresh Allows user to rerender the lineage]
* @return {[type]} [description]
*/
- refresh() {
+ refresh(options) {
this.clear();
this._initializeGraph();
this._initGraph({ refresh: true });
+ this.selectedNode = "";
+ if (options && options.compactLineageEnabled && options.filterObj) {
+ var isProcessHideCheck = options.filterObj.isProcessHideCheck,
+ isDeletedEntityHideCheck = options.filterObj.isDeletedEntityHideCheck;
+ this._AddFilterNotification(isProcessHideCheck, isDeletedEntityHideCheck);
+ }
}
/**
* [removeNodeSelection description]
@@ -185,23 +208,32 @@ export default class LineageHelper {
*/
searchNode({ guid, onSearchNode }) {
this.svg.selectAll(".serach-rect").remove();
+ this.svg.selectAll(".label").attr("stroke", "none");
+ this.selectedNode = guid;
this.centerAlign({
guid: guid,
- onCenterZoomed: function (opts) {
+ onCenterZoomed: function(opts) {
const { selectedNodeEl } = opts;
+ var oSelectedNode = selectedNodeEl.node().getBBox(),
+ rectWidth = oSelectedNode.width + 10,
+ rectXPos = oSelectedNode.x - 5;
selectedNodeEl.select(".label").attr("stroke", "#316132");
selectedNodeEl.select("circle").classed("wobble", true);
selectedNodeEl
.insert("rect", "circle")
.attr("class", "serach-rect")
- .attr("x", -50)
+ .attr("stroke", "#37bb9b")
+ .attr("stroke-width", "2.5px")
+ .attr("fill", "none")
+ .attr("x", rectXPos)
.attr("y", -27.5)
- .attr("width", 100)
- .attr("height", 55);
+ .attr("width", rectWidth)
+ .attr("height", 60);
if (onSearchNode && typeof onSearchNode === "function") {
onSearchNode(opts);
}
- }
+ },
+ isSelected: true
});
}
@@ -287,8 +319,7 @@ export default class LineageHelper {
// initlize the dagreD3 graphlib
this.g = new dagreD3.graphlib.Graph()
.setGraph(
- Object.assign(
- {
+ Object.assign({
nodesep: 50,
ranksep: 90,
rankdir: "LR",
@@ -301,7 +332,7 @@ export default class LineageHelper {
this.options.dagreOptions
)
)
- .setDefaultEdgeLabel(function () {
+ .setDefaultEdgeLabel(function() {
return {};
});
@@ -339,7 +370,7 @@ export default class LineageHelper {
if (this.options.setDataManually === true) {
return;
- } else if (this.options.data === undefined || (this.options.data && this.options.data.relations.length === 0)) {
+ } else if (this.options.data === undefined || (this.options.data && this.options.data.relations.length === 0 && _.isEmpty(this.options.data.guidEntityMap))) {
if (this.options.beforeRender) {
this.options.beforeRender();
}
@@ -402,8 +433,7 @@ export default class LineageHelper {
* @param {[type]} graphOptions [description]
* @return {[type]} [description]
*/
- _createGraph(
- {
+ _createGraph({
data = {},
imgBasePath,
isShowTooltip,
@@ -416,12 +446,12 @@ export default class LineageHelper {
getToolTipContent,
toolTipTitle
},
- graphOptions,
- { refresh }
+ graphOptions, { refresh }
) {
if (this.options.beforeRender) {
this.options.beforeRender();
}
+ this.selectedNode = "";
const that = this,
{ svg, g, width, height } = graphOptions,
isRankdirToBottom = this.options.dagreOptions && this.options.dagreOptions.rankdir === "tb";
@@ -435,7 +465,7 @@ export default class LineageHelper {
return;
}
- g.nodes().forEach(function (v) {
+ g.nodes().forEach(function(v) {
var node = g.node(v);
// Round the corners of the nodes
if (node) {
@@ -452,11 +482,11 @@ export default class LineageHelper {
// Create the renderer
var render = new dagreD3.render();
// Add our custom arrow (a hollow-point)
- render.arrows().arrowPoint = function () {
+ render.arrows().arrowPoint = function() {
return LineageUtils.arrowPointRender(...arguments, { ...graphOptions });
};
// Render custom img inside shape
- render.shapes().img = function () {
+ render.shapes().img = function() {
return LineageUtils.imgShapeRender(...arguments, {
...graphOptions,
isRankdirToBottom: isRankdirToBottom,
@@ -506,17 +536,18 @@ export default class LineageHelper {
if (isRankdirToBottom) {
return "translate(2,-20)";
}
- return "translate(2,-35)";
+ return "translate(2,-38)";
})
- .on("mouseenter", function (d) {
+ .attr("font-size", "10px")
+ .on("mouseenter", function(d) {
event.preventDefault();
select(this).classed("highlight", true);
})
- .on("mouseleave", function (d) {
+ .on("mouseleave", function(d) {
event.preventDefault();
select(this).classed("highlight", false);
})
- .on("click", function (d) {
+ .on("click", function(d) {
event.preventDefault();
if (onLabelClick && typeof onLabelClick === "function") {
onLabelClick({ clickedData: d });
@@ -526,12 +557,12 @@ export default class LineageHelper {
svgGroupEl
.selectAll("g.nodes g.node circle")
- .on("mouseenter", function (d, index, element) {
+ .on("mouseenter", function(d, index, element) {
that.activeNode = true;
var matrix = this.getScreenCTM().translate(+this.getAttribute("cx"), +this.getAttribute("cy"));
that.svg.selectAll(".node").classed("active", false);
select(this).classed("active", true);
- if (that._getValueFromUser(isShowTooltip)) {
+ if (that._getValueFromUser(isShowTooltip) && (d.indexOf("more") !== 0)) {
var direction = LineageUtils.getToolTipDirection({ el: this });
tooltip.direction(direction).show(d, this);
}
@@ -545,10 +576,10 @@ export default class LineageHelper {
...graphOptions
});
})
- .on("mouseleave", function (d) {
+ .on("mouseleave", function(d) {
that.activeNode = false;
var nodeEL = this;
- setTimeout(function (argument) {
+ setTimeout(function(argument) {
if (!(that.activeTip || that.activeNode)) {
select(nodeEL).classed("active", false);
if (that._getValueFromUser(isShowTooltip)) {
@@ -565,7 +596,7 @@ export default class LineageHelper {
...graphOptions
});
})
- .on("click", function (d) {
+ .on("click", function(d) {
if (event.defaultPrevented) return; // ignore drag
event.preventDefault();
tooltip.hide(d);
@@ -578,9 +609,9 @@ export default class LineageHelper {
// Bind event on edgePath
var edgePathEl = svgGroupEl.selectAll("g.edgePath");
- edgePathEl.selectAll("path.path").on("click", function (d) {
+ edgePathEl.selectAll("path.path").on("click", function(d) {
if (onPathClick && typeof onPathClick === "function") {
- var pathRelationObj = data.relations.find(function (obj) {
+ var pathRelationObj = data.relations.find(function(obj) {
if (obj.fromEntityId === d.v && obj.toEntityId === d.w) {
return true;
}
@@ -651,5 +682,16 @@ export default class LineageHelper {
span = container.append("span").style("color", "#fb4200");
span.append("i").classed("fa fa-long-arrow-right fa-fw", true);
span.append("span").html("Impact");
+
+ span = container.append("span").classed("notification hide", true).style("color", "#686868");
+ span.append("i").classed("fa fa-exclamation fa-fw", true);
+ span.append("span").html("Filtering hides all Expand buttons.");
+ }
+ _AddFilterNotification(isProcessHideCheck, isDeletedEntityHideCheck) {
+ if ((isProcessHideCheck || isDeletedEntityHideCheck)) {
+ $(this.options.legendsEl).find('.notification').removeClass('hide');
+ } else {
+ $(this.options.legendsEl).find('.notification').addClass('hide');
+ }
}
}
\ No newline at end of file
diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/src/styles/graph.scss b/dashboardv2/public/js/external_lib/atlas-lineage/src/styles/graph.scss
index ab1e82df3..2f1322765 100644
--- a/dashboardv2/public/js/external_lib/atlas-lineage/src/styles/graph.scss
+++ b/dashboardv2/public/js/external_lib/atlas-lineage/src/styles/graph.scss
@@ -26,17 +26,17 @@
//transition: opacity 0.3s linear;
- rect {
- stroke: $color_mountain_mist_approx;
- fill: $white;
- stroke-width: 1.5px;
-
- &.serach-rect {
- stroke: $color_keppel_approx;
- fill: transparent;
- stroke-width: 2.5px;
- }
- }
+ // rect {
+ // stroke: $color_mountain_mist_approx;
+ // fill: $white;
+ // stroke-width: 1.5px;
+
+ // &.serach-rect {
+ // stroke: $color_keppel_approx;
+ // fill: transparent;
+ // stroke-width: 2.5px;
+ // }
+ // }
.label {
fill: $color_suva_gray_approx;
@@ -104,7 +104,7 @@
}
.legends {
- > span {
+ >span {
margin-right: 8px;
font-family: $font_0;
}
@@ -156,10 +156,12 @@ svg.hover {
z-index: 999;
max-width: 300px; //Instead of the line below you could use @include border-radius($radius, $vertical-radius)
border-radius: 2px;
+ word-break: break-all;
.tip-inner-scroll {
overflow: auto;
max-height: 300px;
+
h5 {
margin: 7px 0px;
}
@@ -211,7 +213,7 @@ svg.hover {
}
}
-g.type-TK > rect {
+g.type-TK>rect {
fill: $color_bright_turquoise_approx;
}
diff --git a/dashboardv2/public/js/main.js b/dashboardv2/public/js/main.js
index 603e5ec3d..0994c1b02 100644
--- a/dashboardv2/public/js/main.js
+++ b/dashboardv2/public/js/main.js
@@ -298,6 +298,12 @@ require(['App',
Globals.isTasksEnabled = response['atlas.tasks.enabled'];
}
if (response['atlas.session.timeout.secs']) { Globals.idealTimeoutSeconds = response['atlas.session.timeout.secs']; }
+ if(response['atlas.lineage.on.demand.enabled'] !== undefined){
+ Globals.isLineageOnDemandEnabled = response['atlas.lineage.on.demand.enabled'];
+ }
+ if(response['atlas.lineage.on.demand.default.node.count'] !== undefined){
+ Globals.lineageNodeCount = response['atlas.lineage.on.demand.default.node.count'];
+ }
/* Atlas idealTimeout
redirectUrl: url to redirect after timeout
idealTimeLimit: timeout in seconds
diff --git a/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html b/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html
index 5f90b096e..30dd45d7f 100644
--- a/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html
+++ b/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html
@@ -90,10 +90,20 @@
<div class="pretty p-switch p-fill">
<input type="checkbox" class="pull-left" data-id="labelFullName" value="" id="labelFullName"/>
<div class="state p-primary">
- <label>Display fullname</label>
+ <label>Display full name</label>
</div>
</div>
</div>
+ {{#if compactLineageEnabled}}
+ <div class="showTooltip text-left col-sm-12">
+ <div class="nodeCount-container">
+ <label class="col-sm-8 no-padding">Nodes On Demand</label>
+ <div class="col-sm-4 no-padding">
+ <select data-id="selectNodeCount" class="form-control"></select>
+ </div>
+ </div>
+ </div>
+ {{/if}}
</div>
</div>
<div class="graph-button-group pull-right">
diff --git a/dashboardv2/public/js/utils/Globals.js b/dashboardv2/public/js/utils/Globals.js
index c30f840f7..d2ce1a90f 100644
--- a/dashboardv2/public/js/utils/Globals.js
+++ b/dashboardv2/public/js/utils/Globals.js
@@ -53,6 +53,10 @@ define(["require", "underscore"], function(require, _) {
Globals.isDebugMetricsEnabled = false;
Globals.isTasksEnabled = false;
Globals.idealTimeoutSeconds = 900;
+ Globals.isFullScreenView = false;
+ Globals.isLineageOnDemandEnabled = false;
+ Globals.lineageNodeCount = 3;
+ Globals.lineageDepth = 3;
return Globals;
});
\ No newline at end of file
diff --git a/dashboardv2/public/js/utils/Helper.js b/dashboardv2/public/js/utils/Helper.js
index f211bd055..0ba1b6c4e 100644
--- a/dashboardv2/public/js/utils/Helper.js
+++ b/dashboardv2/public/js/utils/Helper.js
@@ -17,10 +17,11 @@
*/
define(['require',
'utils/Utils',
+ 'utils/Globals',
'd3',
'marionette',
'jquery-ui'
-], function(require, Utils, d3) {
+], function(require, Utils, Globals, d3) {
'use strict';
_.mixin({
numberFormatWithComma: function(number) {
@@ -372,7 +373,13 @@ define(['require',
});
}
//For closing the modal on browsers navigation
- $(window).on('popstate', function(){
+ $(window).on('popstate', function() {
$('body').find('.modal-dialog .close').click();
+ //To close the full-screen mode in lineage on browsers navigation.
+ if (!Globals.isFullScreenView) {
+ $('#tab-lineage').removeClass("fullscreen-mode");
+ $("#r_lineageLayoutView").find('button[data-id="fullScreen-toggler"]').attr("data-original-title", "Full Screen").find("i").removeClass("fa-compress").addClass("fa-expand");
+ }
+ Globals.isFullScreenView = false;
});
})
\ No newline at end of file
diff --git a/dashboardv2/public/js/views/graph/LineageLayoutView.js b/dashboardv2/public/js/views/graph/LineageLayoutView.js
index e989c4719..ce7692535 100644
--- a/dashboardv2/public/js/views/graph/LineageLayoutView.js
+++ b/dashboardv2/public/js/views/graph/LineageLayoutView.js
@@ -52,6 +52,7 @@ define(['require',
checkHideProcess: "[data-id='checkHideProcess']",
checkDeletedEntity: "[data-id='checkDeletedEntity']",
selectDepth: 'select[data-id="selectDepth"]',
+ selectNodeCount: 'select[data-id="selectNodeCount"]',
filterToggler: '[data-id="filter-toggler"]',
settingToggler: '[data-id="setting-toggler"]',
searchToggler: '[data-id="search-toggler"]',
@@ -74,7 +75,8 @@ define(['require',
templateHelpers: function() {
return {
width: "100%",
- height: "100%"
+ height: "100%",
+ compactLineageEnabled: Globals.isLineageOnDemandEnabled
};
},
/** ui events hash */
@@ -83,6 +85,7 @@ define(['require',
events["click " + this.ui.checkHideProcess] = 'onCheckUnwantedEntity';
events["click " + this.ui.checkDeletedEntity] = 'onCheckUnwantedEntity';
events['change ' + this.ui.selectDepth] = 'onSelectDepthChange';
+ events['change ' + this.ui.selectNodeCount] = 'onSelectNodeCount';
events["click " + this.ui.filterToggler] = 'onClickFilterToggler';
events["click " + this.ui.boxClose] = 'toggleBoxPanel';
events["click " + this.ui.settingToggler] = 'onClickSettingToggler';
@@ -109,7 +112,7 @@ define(['require',
this.filterObj = {
isProcessHideCheck: false,
isDeletedEntityHideCheck: false,
- depthCount: ''
+ depthCount: Globals.lineageDepth
};
this.searchNodeObj = {
selectedNode: ''
@@ -117,16 +120,30 @@ define(['require',
this.labelFullText = false;
},
onRender: function() {
- var that = this;
+ var that = this,
+ nodeCountArray = _.uniq([3, 6, Globals.lineageNodeCount]);
+ this.initialQueryObj = {};
this.ui.searchToggler.prop("disabled", true);
- this.$graphButtonsEl = this.$(".graph-button-group button, select[data-id='selectDepth']")
- this.fetchGraphData();
+ this.$graphButtonsEl = this.$(".graph-button-group button, select[data-id='selectDepth']");
+ if (Globals.isLineageOnDemandEnabled) {
+ this.ui.resetLineage.attr("title", "Reset Lineage");
+ this.initialQueryObj[this.guid] = {
+ "direction": "BOTH",
+ "inputRelationsLimit": Globals.lineageNodeCount,
+ "outputRelationsLimit": Globals.lineageNodeCount,
+ "depth": Globals.lineageDepth,
+ }
+ }
+ this.fetchGraphData({ queryParam: this.initialQueryObj });
if (this.layoutRendered) {
this.layoutRendered();
}
if (this.processCheck) {
this.hideCheckForProcess();
}
+ if (this.entity.status === "DELETED") {
+ this.hideCheckForDeletedEntity();
+ }
//this.initializeGraph();
this.ui.selectDepth.select2({
data: _.sortBy([3, 6, 9, 12, 15, 18, 21]),
@@ -134,6 +151,13 @@ define(['require',
dropdownCssClass: "number-input",
multiple: false
});
+ this.ui.selectNodeCount.select2({
+ data: _.sortBy(nodeCountArray),
+ tags: true,
+ dropdownCssClass: "number-input",
+ multiple: false
+ });
+ this.ui.selectNodeCount.val(Globals.lineageNodeCount).trigger("change");
},
onShow: function() {
this.$('.fontLoader').show();
@@ -150,6 +174,7 @@ define(['require',
panel = $(e.target).parents('.tab-pane').first();
icon.toggleClass('fa-expand fa-compress');
if (icon.hasClass('fa-expand')) {
+ Globals.isFullScreenView = false;
icon.parent('button').attr("data-original-title", "Full Screen");
} else {
icon.parent('button').attr("data-original-title", "Default View");
@@ -165,17 +190,22 @@ define(['require',
onCheckUnwantedEntity: function(e) {
var that = this;
//this.initializeGraph();
+ this.searchNodeObj.selectedNode = "";
if ($(e.target).data("id") === "checkHideProcess") {
this.filterObj.isProcessHideCheck = e.target.checked;
} else {
this.filterObj.isDeletedEntityHideCheck = e.target.checked;
}
- this.LineageHelperRef.refresh();
+ this.renderLineageTypeSearch(this.data);
+ this.LineageHelperRef.refresh({ compactLineageEnabled: Globals.isLineageOnDemandEnabled, filterObj: this.filterObj });
},
toggleBoxPanel: function(options) {
var el = options && options.el,
nodeDetailToggler = options && options.nodeDetailToggler,
currentTarget = options.currentTarget;
+ if (options.nodeDetailToggler) {
+ this.ui.lineageTypeSearch.select2("close");
+ }
this.$el.find('.show-box-panel').removeClass('show-box-panel');
if (el && el.addClass) {
el.addClass('show-box-panel');
@@ -214,12 +244,33 @@ define(['require',
},
onSelectDepthChange: function(e, options) {
//this.initializeGraph();
- this.filterObj.depthCount = e.currentTarget.value;
+ Globals.lineageDepth = parseInt(e.currentTarget.value);
//legends property is added in queryParam to stop the legend getting added in lineage graph whenever dept is changed.
- this.fetchGraphData({ queryParam: { 'depth': this.filterObj.depthCount }, 'legends': false });
+ if (!Globals.isLineageOnDemandEnabled) {
+ this.fetchGraphData({ queryParam: { 'depth': Globals.lineageDepth }, 'legends': false });
+ }
+
+ if (Globals.isLineageOnDemandEnabled) {
+ this.initialQueryObj[this.guid].depth = Globals.lineageDepth;
+ this.fetchGraphData({ queryParam: this.initialQueryObj, 'legends': false })
+ }
+ },
+ onSelectNodeCount: function(e, options) {
+ Globals.lineageNodeCount = parseInt(e.target.value);
+ if (Globals.lineageNodeCount === 0) {
+ Utils.notifyWarn({
+ content: 'Value cannot be less than 1'
+ });
+ this.ui.selectNodeCount.val(3).trigger("change");
+ }
},
onClickResetLineage: function() {
- this.LineageHelperRef.refresh();
+ if (Globals.isLineageOnDemandEnabled) {
+ this.fetchGraphData({ queryParam: this.initialQueryObj, 'legends': false });
+ }
+ if (!Globals.isLineageOnDemandEnabled) {
+ this.LineageHelperRef.refresh();
+ }
this.searchNodeObj.selectedNode = "";
this.ui.lineageTypeSearch.data({ refresh: true }).val("").trigger("change");
this.ui.labelFullName.prop("checked", false);
@@ -270,13 +321,14 @@ define(['require',
}
_.extend(this.currentEntityData, _.pick(this.entity, 'attributes', 'guid', 'isIncomplete', 'status', 'typeName'));
//End
- this.collection.getLineage(this.guid, {
- queryParam: queryParam,
+ var dataObj = {
+ compactLineageEnabled: Globals.isLineageOnDemandEnabled,
success: function(data) {
if (that.isDestroyed) {
return;
}
data["legends"] = options ? options.legends : true;
+ that.lineageOnDemandPayload = data.lineageOnDemandPayload ? data.lineageOnDemandPayload : {};
// show only main part of lineage current entity is at bottom, so reverse is done
var relationsReverse = data.relations ? data.relations.reverse() : null,
lineageMaxRelationCount = 9000;
@@ -292,6 +344,10 @@ define(['require',
data.guidEntityMap[data.baseEntityGuid] = that.currentEntityData;
}
}
+ that.data = data;
+ var updatedData = that.updateLineageData(data);
+ _.extend(data.guidEntityMap, updatedData.plusBtnsObj);
+ data.relations = data.relations.concat(updatedData.plusBtnRelationsArray);
that.createGraph(data);
that.renderLineageTypeSearch(data);
},
@@ -302,7 +358,68 @@ define(['require',
that.$('.fontLoader').hide();
that.$('svg>g').show();
}
- })
+ };
+ Globals.isLineageOnDemandEnabled ? dataObj.data = queryParam : dataObj.queryParam = queryParam;
+
+ this.collection.getLineage(this.guid, dataObj)
+ },
+ updateLineageData: function(data) {
+ var that = this,
+ rawData = data,
+ plusBtnsObj = {},
+ plusBtnRelationsArray = [];
+ this.relationsOnDemand = data.relationsOnDemand ? data.relationsOnDemand : null;
+ this.lineageOnDemandPayload = data.lineageOnDemandPayload ? data.lineageOnDemandPayload : null;
+ if (this.relationsOnDemand) {
+ _.each(this.relationsOnDemand, function(values, nodeId) {
+ if (values.hasMoreInputs) {
+ var btnType = "Input",
+ moreInputBtnObj = that.createExpandButtonObj({ nodeId: nodeId, btnType: btnType });
+ plusBtnsObj[moreInputBtnObj.guid] = moreInputBtnObj;
+ plusBtnRelationsArray.push({ fromEntityId: moreInputBtnObj.guid, toEntityId: nodeId, relationshipId: 'dummy' });
+ }
+ if (values.hasMoreOutputs) {
+ var btnType = "Output",
+ moreOutputBtnObj = that.createExpandButtonObj({ nodeId: nodeId, btnType: btnType });
+ plusBtnsObj[moreOutputBtnObj.guid] = moreOutputBtnObj;
+ plusBtnRelationsArray.push({ fromEntityId: nodeId, toEntityId: moreOutputBtnObj.guid, relationshipId: 'dummy' });
+ }
+ });
+ return {
+ plusBtnsObj: plusBtnsObj,
+ plusBtnRelationsArray: plusBtnRelationsArray
+ }
+ }
+ },
+ generateAddButtonId: function(btnType) {
+ return btnType + Math.random().toString(16).slice(2)
+ },
+ createExpandButtonObj: function(options) {
+ var defaultObj = {
+ attributes: {
+ owner: '',
+ createTime: 0,
+ qualifiedName: 'PlusBtn',
+ name: 'PlusBtn',
+ description: ''
+ },
+ isExpandBtn: true,
+ classificationNames: [],
+ displayText: "Expand",
+ isIncomplete: false,
+ labels: [],
+ meaningNames: [],
+ meanings: [],
+ status: "ACTIVE",
+ typeName: "Table"
+ },
+ btnObj = Object.assign({}, defaultObj),
+ btnType = (options.btnType === "Input") ? "more-inputs" : "more-outputs",
+ btnId = this.generateAddButtonId(btnType);
+ btnObj.guid = btnId;
+ btnObj.parentNodeGuid = options.nodeId;
+ btnObj.btnType = options.btnType;
+ return btnObj;
},
createGraph: function(data) {
var that = this;
@@ -323,7 +440,6 @@ define(['require',
isShowHoverPath: function() { return that.ui.showOnlyHoverPath.prop('checked') },
isShowTooltip: function() { return that.ui.showTooltip.prop('checked') },
onPathClick: function(d) {
- console.log("Path Clicked");
if (d.pathRelationObj) {
var relationshipId = d.pathRelationObj.relationshipId;
require(['views/graph/PropagationPropertyModal'], function(PropagationPropertyModal) {
@@ -338,12 +454,21 @@ define(['require',
}
},
onNodeClick: function(d) {
+ if (d.clickedData.indexOf("more") >= 0) {
+ that.onExpandNodeClick({ guid: d.clickedData });
+ return;
+ }
that.onClickNodeToggler();
that.updateRelationshipDetails({ guid: d.clickedData });
that.calculateLineageDetailPanelHeight();
},
onLabelClick: function(d) {
var guid = d.clickedData;
+ Globals.isFullScreenView = true;
+ that.ui.lineageTypeSearch.select2("close");
+ if (guid.indexOf("more") >= 0) {
+ return;
+ }
if (that.guid == guid) {
Utils.notifyInfo({
html: true,
@@ -376,6 +501,55 @@ define(['require',
}
});
},
+ onExpandNodeClick: function(options) {
+ var parentNodeData = this.LineageHelperRef.getNode(options.guid);
+ this.updateQueryObject(parentNodeData.parentNodeGuid, parentNodeData.btnType);
+ },
+ updateQueryObject: function(parentId, btnType) {
+ var inputLimit = null,
+ outputLimit = null,
+ that = this,
+ queryParam;
+ if (_.has(that.lineageOnDemandPayload, parentId)) {
+ _.find(that.lineageOnDemandPayload, function(value, key) {
+ if (key === parentId) {
+ if (btnType === "Input") {
+ value.inputRelationsLimit = value.inputRelationsLimit + Globals.lineageNodeCount;
+ value.outputRelationsLimit = value.outputRelationsLimit;
+ }
+ if (btnType === "Output") {
+ value.inputRelationsLimit = value.inputRelationsLimit;
+ value.outputRelationsLimit = value.outputRelationsLimit + Globals.lineageNodeCount;
+ }
+ }
+ });
+ } else {
+ var relationCount = that.validateInputOutputLimit(parentId, btnType);
+ if (btnType === "Input") {
+ inputLimit = relationCount.inputRelationCount + Globals.lineageNodeCount;
+ outputLimit = relationCount.outputRelationCount;
+ }
+ if (btnType === "Output") {
+ inputLimit = relationCount.inputRelationCount;
+ outputLimit = relationCount.outputRelationCount + Globals.lineageNodeCount;
+ }
+ this.lineageOnDemandPayload[parentId] = { direction: "BOTH", inputRelationsLimit: inputLimit, outputRelationsLimit: outputLimit, depth: Globals.lineageDepth };
+ }
+ this.fetchGraphData({ queryParam: this.lineageOnDemandPayload, 'legends': false });
+ },
+ validateInputOutputLimit: function(parentId, btnType) {
+ var inputRelationCount, outputRelationCount;
+ for (var guid in this.relationsOnDemand) {
+ if (parentId === guid && (btnType === "Input" || btnType === "Output")) {
+ inputRelationCount = this.relationsOnDemand[guid].inputRelationsCount ? this.relationsOnDemand[guid].inputRelationsCount : Globals.lineageNodeCount;
+ outputRelationCount = this.relationsOnDemand[guid].outputRelationsCount ? this.relationsOnDemand[guid].outputRelationsCount : Globals.lineageNodeCount;
+ }
+ }
+ return {
+ inputRelationCount: inputRelationCount,
+ outputRelationCount: outputRelationCount
+ };
+ },
noLineage: function() {
this.$('.fontLoader').hide();
this.$('.depth-container').hide();
@@ -387,6 +561,10 @@ define(['require',
hideCheckForProcess: function() {
this.$('.hideProcessContainer').hide();
},
+ hideCheckForDeletedEntity: function() {
+ //This has been added to handle the scenario where hideDeletedEntityCheck should hide form filters when baseEntity is deleted.
+ this.$('.hideDeletedContainer').hide();
+ },
renderLineageTypeSearch: function(data) {
var that = this;
return new Promise(function(resolve, reject) {
@@ -395,7 +573,7 @@ define(['require',
if (!_.isEmpty(data)) {
_.each(data.guidEntityMap, function(obj, index) {
var nodeData = that.LineageHelperRef.getNode(obj.guid);
- if ((that.filterObj.isProcessHideCheck || that.filterObj.isDeletedEntityHideCheck) && nodeData && (nodeData.isProcess || nodeData.isDeleted)) {
+ if ((that.filterObj.isProcessHideCheck && obj && obj.isProcess) || (that.filterObj.isDeletedEntityHideCheck && obj && obj.isDeleted) || (Globals.isLineageOnDemandEnabled && obj && _.contains(["Input", "Output"], obj.btnType))) {
return;
}
typeStr += '<option value="' + obj.guid + '">' + obj.displayText + '</option>';
diff --git a/dashboardv3/public/img/entity-icon/expandBtn.svg b/dashboardv3/public/img/entity-icon/expandBtn.svg
new file mode 100644
index 000000000..88693e74b
--- /dev/null
+++ b/dashboardv3/public/img/entity-icon/expandBtn.svg
@@ -0,0 +1,24 @@
+<!--
+ * 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.
+ -->
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#4a90e2">
+ <g>
+ <path d="M12,2A10,10,0,1,0,22,12,10.011,10.011,0,0,0,12,2Zm0,18a8,8,0,1,1,8-8A8.009,8.009,0,0,1,12,20Z"/>
+ <polygon points="12 10.586 8.707 7.293 7.293 8.707 12 13.414 16.707 8.707 15.293 7.293 12 10.586"/>
+ <polygon points="12 14.586 8.707 11.293 7.293 12.707 12 17.414 16.707 12.707 15.293 11.293 12 14.586"/>
+ </g>
+</svg>
diff --git a/dashboardv3/public/js/collection/VLineageList.js b/dashboardv3/public/js/collection/VLineageList.js
index bda649220..4f980a737 100644
--- a/dashboardv3/public/js/collection/VLineageList.js
+++ b/dashboardv3/public/js/collection/VLineageList.js
@@ -42,7 +42,11 @@ define(['require',
dataType: 'json'
}, options);
- return this.constructor.nonCrudOperation.call(this, url, 'GET', options);
+ if (options.compactLineageEnabled) {
+ return this.constructor.nonCrudOperation.call(this, url, 'POST', options);
+ } else {
+ return this.constructor.nonCrudOperation.call(this, url, 'GET', options);
+ }
}
},
//Static Class Members
diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/dist/index.js b/dashboardv3/public/js/external_lib/atlas-lineage/dist/index.js
index b31ee4911..6a184ee6e 100644
--- a/dashboardv3/public/js/external_lib/atlas-lineage/dist/index.js
+++ b/dashboardv3/public/js/external_lib/atlas-lineage/dist/index.js
@@ -1 +1 @@
-!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("platform"),require("dagreD3")):"function"==typeof define&&define.amd?define(["platform","dagreD3"],e):"object"==typeof exports?exports.LineageHelper=e(require("platform"),require("dagreD3")):t.LineageHelper=e(t.platform,t.dagreD3)}(window,(function(t,e){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i. [...]
\ No newline at end of file
+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("platform"),require("dagreD3")):"function"==typeof define&&define.amd?define(["platform","dagreD3"],e):"object"==typeof exports?exports.LineageHelper=e(require("platform"),require("dagreD3")):t.LineageHelper=e(t.platform,t.dagreD3)}(window,(function(t,e){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i. [...]
\ No newline at end of file
diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/dist/styles.css b/dashboardv3/public/js/external_lib/atlas-lineage/dist/styles.css
index 2d7f9d9de..3bcce59e5 100644
--- a/dashboardv3/public/js/external_lib/atlas-lineage/dist/styles.css
+++ b/dashboardv3/public/js/external_lib/atlas-lineage/dist/styles.css
@@ -1,2 +1 @@
-.node{cursor:pointer}.node text{font-size:10px;font-family:sans-serif}.node .label{fill:#868686}.node .label.highlight{cursor:pointer;fill:#4a90e2;text-decoration:underline}.node .label.highlight tspan{font-weight:400}.node circle{-moz-transition:all 0.3s;-webkit-transition:all 0.3s;transition:all 0.3s;stroke-width:1.5px}.node circle.node-detail-highlight{stroke:#4a90e2;stroke-width:2px}.node circle.nodeImage.green:hover{stroke:#ffb203}.node circle.nodeImage.blue:hover{stroke:#4b91e2}.no [...]
-
+.node{cursor:pointer}.node text{font-size:10px;font-family:sans-serif}.node .label{fill:#868686}.node .label.highlight{cursor:pointer;fill:#4a90e2;text-decoration:underline}.node .label.highlight tspan{font-weight:400}.node circle{-moz-transition:all 0.3s;-webkit-transition:all 0.3s;transition:all 0.3s;stroke-width:1.5px}.node circle.node-detail-highlight{stroke:#4a90e2;stroke-width:2px}.node circle.nodeImage.green:hover{stroke:#ffb203}.node circle.nodeImage.blue:hover{stroke:#4b91e2}.no [...]
diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/DataUtils.js b/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/DataUtils.js
index 1255eb070..7d2acf4a7 100644
--- a/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/DataUtils.js
+++ b/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/DataUtils.js
@@ -19,343 +19,354 @@ import Enums from "../Enums";
import { curveBasis } from "d3-shape";
const DataUtils = {
- /**
- * [getBaseUrl description]
- * @param {[type]} url [description]
- * @return {[type]} [description]
- */
- getBaseUrl: function(url) {
- return url.replace(/\/[\w-]+.(jsp|html)|\/+$/gi, "");
- },
- /**
- * [getEntityIconPath description]
- * @param {[type]} options.entityData [description]
- * @param {Object} options.errorUrl } [description]
- * @return {[type]} [description]
- */
- getEntityIconPath: function({ entityData, errorUrl } = {}) {
- var serviceType,
- status,
- typeName,
- iconBasePath = this.getBaseUrl(window.location.pathname) + Globals.entityImgPath;
- if (entityData) {
- typeName = entityData.typeName;
- serviceType = entityData && entityData.serviceType;
- status = entityData && entityData.status;
- }
+ /**
+ * [getBaseUrl description]
+ * @param {[type]} url [description]
+ * @return {[type]} [description]
+ */
+ getBaseUrl: function(url) {
+ return url.replace(/\/[\w-]+.(jsp|html)|\/+$/gi, "");
+ },
+ /**
+ * [getEntityIconPath description]
+ * @param {[type]} options.entityData [description]
+ * @param {Object} options.errorUrl } [description]
+ * @return {[type]} [description]
+ */
+ getEntityIconPath: function({ entityData, errorUrl } = {}) {
+ var serviceType,
+ status,
+ typeName,
+ iconBasePath = this.getBaseUrl(window.location.pathname) + Globals.entityImgPath;
+ if (entityData) {
+ typeName = entityData.typeName;
+ serviceType = entityData && entityData.serviceType;
+ status = entityData && entityData.status;
+ }
- function getImgPath(imageName) {
- return iconBasePath + (Enums.entityStateReadOnly[status] ? "disabled/" + imageName : imageName);
- }
+ function getImgPath(imageName) {
+ return iconBasePath + (Enums.entityStateReadOnly[status] ? "disabled/" + imageName : imageName);
+ }
- function getDefaultImgPath() {
- if (entityData.isProcess) {
- if (Enums.entityStateReadOnly[status]) {
- return iconBasePath + "disabled/process.png";
- } else {
- return iconBasePath + "process.png";
- }
- } else {
- if (Enums.entityStateReadOnly[status]) {
- return iconBasePath + "disabled/table.png";
- } else {
- return iconBasePath + "table.png";
- }
- }
- }
+ function getDefaultImgPath() {
+ if (entityData.isProcess) {
+ if (Enums.entityStateReadOnly[status]) {
+ return iconBasePath + "disabled/process.png";
+ } else {
+ return iconBasePath + "process.png";
+ }
+ } else {
+ if (Enums.entityStateReadOnly[status]) {
+ return iconBasePath + "disabled/table.png";
+ } else {
+ return iconBasePath + "table.png";
+ }
+ }
+ }
- if (entityData) {
- if (errorUrl) {
- var isErrorInTypeName = errorUrl && errorUrl.match("entity-icon/" + typeName + ".png|disabled/" + typeName + ".png") ? true : false;
- if (serviceType && isErrorInTypeName) {
- var imageName = serviceType + ".png";
- return getImgPath(imageName);
- } else {
- return getDefaultImgPath();
- }
- } else if (entityData.typeName) {
- var imageName = entityData.typeName + ".png";
- return getImgPath(imageName);
- } else {
- return getDefaultImgPath();
- }
- }
- },
- /**
- * [isProcess description]
- * @param {[type]} options.typeName [description]
- * @param {[type]} options.superTypes [description]
- * @param {[type]} options.entityDef [description]
- * @return {Boolean} [description]
- */
- isProcess: function({ typeName, superTypes, entityDef }) {
- if (typeName == "Process") {
- return true;
- }
- return superTypes.indexOf("Process") > -1;
- },
- /**
- * [isDeleted description]
- * @param {[type]} node [description]
- * @return {Boolean} [description]
- */
- isDeleted: function(node) {
- if (node === undefined) {
- return;
- }
- return Enums.entityStateReadOnly[node.status];
- },
- isNodeToBeUpdated: function(node, filterObj) {
- var isProcessHideCheck = filterObj.isProcessHideCheck,
- isDeletedEntityHideCheck = filterObj.isDeletedEntityHideCheck;
- var returnObj = {
- isProcess: isProcessHideCheck && node.isProcess,
- isDeleted: isDeletedEntityHideCheck && node.isDeleted
- };
- returnObj["update"] = returnObj.isProcess || returnObj.isDeleted;
- return returnObj;
- },
- /**
- * [getServiceType description]
- * @param {[type]} options.typeName [description]
- * @param {[type]} options.entityDef [description]
- * @return {[type]} [description]
- */
- getServiceType: function({ typeName, entityDef }) {
- var serviceType = null;
- if (typeName) {
- if (entityDef) {
- serviceType = entityDef.serviceType || null;
- }
- }
- return serviceType;
- },
- /**
- * [getEntityDef description]
- * @param {[type]} options.typeName [description]
- * @param {[type]} options.entityDefCollection [description]
- * @return {[type]} [description]
- */
- getEntityDef: function({ typeName, entityDefCollection }) {
- var entityDef = null;
- if (typeName) {
- entityDef = entityDefCollection.find(function(obj) {
- return obj.name == typeName;
- });
- }
- return entityDef;
- },
- /**
- * [getNestedSuperTypes description]
- * @param {[type]} options.entityDef [description]
- * @param {[type]} options.entityDefCollection [description]
- * @return {[type]} [description]
- */
- getNestedSuperTypes: function({ entityDef, entityDefCollection }) {
- var data = entityDef,
- collection = entityDefCollection,
- superTypes = new Set();
+ if (entityData) {
+ if (errorUrl) {
+ var isErrorInTypeName = errorUrl && errorUrl.match("entity-icon/" + typeName + ".png|disabled/" + typeName + ".png") ? true : false;
+ if (serviceType && isErrorInTypeName) {
+ var imageName = serviceType + ".png";
+ return getImgPath(imageName);
+ } else {
+ return getDefaultImgPath();
+ }
+ } else if (entityData.typeName) {
+ var imageName = entityData.typeName + ".png";
+ return getImgPath(imageName);
+ } else {
+ return getDefaultImgPath();
+ }
+ }
+ },
+ /**
+ * [isProcess description]
+ * @param {[type]} options.typeName [description]
+ * @param {[type]} options.superTypes [description]
+ * @param {[type]} options.entityDef [description]
+ * @return {Boolean} [description]
+ */
+ isProcess: function({ typeName, superTypes, entityDef }) {
+ if (typeName == "Process") {
+ return true;
+ }
+ return superTypes.indexOf("Process") > -1;
+ },
+ /**
+ * [isDeleted description]
+ * @param {[type]} node [description]
+ * @return {Boolean} [description]
+ */
+ isDeleted: function(node) {
+ if (node === undefined) {
+ return;
+ }
+ return Enums.entityStateReadOnly[node.status];
+ },
+ isNodeToBeUpdated: function(node, filterObj) {
+ var isProcessHideCheck = filterObj.isProcessHideCheck,
+ isDeletedEntityHideCheck = filterObj.isDeletedEntityHideCheck;
+ var returnObj = {
+ isProcess: isProcessHideCheck && node.isProcess,
+ isDeleted: isDeletedEntityHideCheck && node.isDeleted
+ };
+ returnObj["update"] = returnObj.isProcess || returnObj.isDeleted;
+ if (node.label === "Expand") {
+ returnObj["update"] = true;
+ }
+ return returnObj;
+ },
+ /**
+ * [getServiceType description]
+ * @param {[type]} options.typeName [description]
+ * @param {[type]} options.entityDef [description]
+ * @return {[type]} [description]
+ */
+ getServiceType: function({ typeName, entityDef }) {
+ var serviceType = null;
+ if (typeName) {
+ if (entityDef) {
+ serviceType = entityDef.serviceType || null;
+ }
+ }
+ return serviceType;
+ },
+ /**
+ * [getEntityDef description]
+ * @param {[type]} options.typeName [description]
+ * @param {[type]} options.entityDefCollection [description]
+ * @return {[type]} [description]
+ */
+ getEntityDef: function({ typeName, entityDefCollection }) {
+ var entityDef = null;
+ if (typeName) {
+ entityDef = entityDefCollection.find(function(obj) {
+ return obj.name == typeName;
+ });
+ }
+ return entityDef;
+ },
+ /**
+ * [getNestedSuperTypes description]
+ * @param {[type]} options.entityDef [description]
+ * @param {[type]} options.entityDefCollection [description]
+ * @return {[type]} [description]
+ */
+ getNestedSuperTypes: function({ entityDef, entityDefCollection }) {
+ var data = entityDef,
+ collection = entityDefCollection,
+ superTypes = new Set();
- var getData = function(data, collection) {
- if (data) {
- if (data.superTypes && data.superTypes.length) {
- data.superTypes.forEach(function(superTypeName) {
- superTypes.add(superTypeName);
- var collectionData = collection.find(function(obj) {
- obj.name === superTypeName;
- });
- if (collectionData) {
- getData(collectionData, collection);
- }
- });
- }
- }
- };
- getData(data, collection);
- return Array.from(superTypes);
- },
- generateData: function({ data = {}, filterObj, entityDefCollection, g, guid, setGraphEdge, setGraphNode }) {
- return new Promise((resolve, reject) => {
- try {
- var relations = data.relations || {},
- guidEntityMap = data.guidEntityMap || {},
- isHideFilterOn = filterObj.isProcessHideCheck || filterObj.isDeletedEntityHideCheck,
- newHashMap = {},
- styleObj = {
- fill: "none",
- stroke: "#ffb203",
- width: 3
- },
- makeNodeData = (relationObj) => {
- if (relationObj) {
- if (relationObj.updatedValues) {
- return relationObj;
- }
- var obj = Object.assign(relationObj, {
- shape: "img",
- updatedValues: true,
- label: relationObj.displayText.trunc(18),
- toolTipLabel: relationObj.displayText,
- id: relationObj.guid,
- isLineage: true,
- isIncomplete: relationObj.isIncomplete,
- entityDef: this.getEntityDef({ typeName: relationObj.typeName, entityDefCollection })
- });
- obj["serviceType"] = this.getServiceType(obj);
- obj["superTypes"] = this.getNestedSuperTypes({
- ...obj,
- entityDefCollection: entityDefCollection
- });
- obj["isProcess"] = this.isProcess(obj);
- obj["isDeleted"] = this.isDeleted(obj);
- return obj;
- }
- },
- crateLineageRelationshipHashMap = function({ relations } = {}) {
- var newHashMap = {};
- relations.forEach(function(obj) {
- if (newHashMap[obj.fromEntityId]) {
- newHashMap[obj.fromEntityId].push(obj.toEntityId);
- } else {
- newHashMap[obj.fromEntityId] = [obj.toEntityId];
- }
- });
- return newHashMap;
- },
- getStyleObjStr = function(styleObj) {
- return "fill:" + styleObj.fill + ";stroke:" + styleObj.stroke + ";stroke-width:" + styleObj.width;
- },
- getNewToNodeRelationship = (toNodeGuid, filterObj) => {
- if (toNodeGuid && relationshipMap[toNodeGuid]) {
- var newRelationship = [];
- relationshipMap[toNodeGuid].forEach((guid) => {
- var nodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[guid]), filterObj);
- if (nodeToBeUpdated.update) {
- var newRelation = getNewToNodeRelationship(guid, filterObj);
- if (newRelation) {
- newRelationship = newRelationship.concat(newRelation);
- }
- } else {
- newRelationship.push(guid);
- }
- });
- return newRelationship;
- } else {
- return null;
- }
- },
- getToNodeRelation = (toNodes, fromNodeToBeUpdated, filterObj) => {
- var toNodeRelationship = [];
- toNodes.forEach((toNodeGuid) => {
- var toNodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[toNodeGuid]), filterObj);
- if (toNodeToBeUpdated.update) {
- // To node need to updated
- if (pendingFromRelationship[toNodeGuid]) {
- toNodeRelationship = toNodeRelationship.concat(pendingFromRelationship[toNodeGuid]);
- } else {
- var newToNodeRelationship = getNewToNodeRelationship(toNodeGuid, filterObj);
- if (newToNodeRelationship) {
- toNodeRelationship = toNodeRelationship.concat(newToNodeRelationship);
- }
- }
- } else {
- //when bothe node not to be updated.
- toNodeRelationship.push(toNodeGuid);
- }
- });
- return toNodeRelationship;
- },
- setNode = (guid) => {
- if (!g._nodes[guid]) {
- var nodeData = makeNodeData(guidEntityMap[guid]);
- setGraphNode(guid, nodeData);
- return nodeData;
- } else {
- return g._nodes[guid];
- }
- },
- setEdge = function(fromNodeGuid, toNodeGuid, opt = {}) {
- setGraphEdge(fromNodeGuid, toNodeGuid, {
- arrowhead: "arrowPoint",
- curve: curveBasis,
- style: getStyleObjStr(styleObj),
- styleObj: styleObj,
- ...opt
- });
- },
- setGraphData = function(fromEntityId, toEntityId) {
- setNode(fromEntityId);
- setNode(toEntityId);
- setEdge(fromEntityId, toEntityId);
- },
- pendingFromRelationship = {};
- if (isHideFilterOn) {
- var relationshipMap = crateLineageRelationshipHashMap(data);
- Object.keys(relationshipMap).forEach((fromNodeGuid) => {
- var toNodes = relationshipMap[fromNodeGuid],
- fromNodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[fromNodeGuid]), filterObj),
- toNodeList = getToNodeRelation(toNodes, fromNodeToBeUpdated, filterObj);
- if (fromNodeToBeUpdated.update) {
- if (pendingFromRelationship[fromNodeGuid]) {
- pendingFromRelationship[fromNodeGuid] = pendingFromRelationship[fromNodeGuid].concat(toNodeList);
- } else {
- pendingFromRelationship[fromNodeGuid] = toNodeList;
- }
- } else {
- toNodeList.forEach(function(toNodeGuid) {
- setGraphData(fromNodeGuid, toNodeGuid);
- });
- }
- });
- } else {
- relations.forEach(function(obj) {
- setGraphData(obj.fromEntityId, obj.toEntityId);
- });
- }
- if (g._nodes[guid]) {
- if (g._nodes[guid]) {
- g._nodes[guid]["isLineage"] = false;
- }
- this.findImpactNodeAndUpdateData({
- guid,
- g,
- setEdge,
- getStyleObjStr
- });
- }
- resolve(g);
- } catch (e) {
- reject(e);
- }
- });
- },
- findImpactNodeAndUpdateData: function({ guid, getStyleObjStr, g, setEdge }) {
- var that = this,
- traversedMap = {},
- styleObj = {
- fill: "none",
- stroke: "#fb4200",
- width: 3
- },
- traversed = function(toNodeList = {}, fromNodeGuid) {
- let toNodeKeyList = Object.keys(toNodeList);
- if (toNodeKeyList.length) {
- if (!traversedMap[fromNodeGuid]) {
- traversedMap[fromNodeGuid] = true;
- toNodeKeyList.forEach(function(toNodeGuid) {
- if (g._nodes[toNodeGuid]) {
- g._nodes[toNodeGuid]["isLineage"] = false;
- }
- setEdge(fromNodeGuid, toNodeGuid, {
- style: getStyleObjStr(styleObj),
- styleObj: styleObj
- });
- traversed(g._sucs[toNodeGuid], toNodeGuid);
- });
- }
- }
- };
- traversed(g._sucs[guid], guid);
- }
+ var getData = function(data, collection) {
+ if (data) {
+ if (data.superTypes && data.superTypes.length) {
+ data.superTypes.forEach(function(superTypeName) {
+ superTypes.add(superTypeName);
+ var collectionData = collection.find(function(obj) {
+ obj.name === superTypeName;
+ });
+ if (collectionData) {
+ getData(collectionData, collection);
+ }
+ });
+ }
+ }
+ };
+ getData(data, collection);
+ return Array.from(superTypes);
+ },
+ generateData: function({ data = {}, filterObj, entityDefCollection, g, guid, setGraphEdge, setGraphNode }) {
+ return new Promise((resolve, reject) => {
+ try {
+ var relations = data.relations || {},
+ guidEntityMap = data.guidEntityMap || {},
+ isHideFilterOn = filterObj.isProcessHideCheck || filterObj.isDeletedEntityHideCheck,
+ newHashMap = {},
+ styleObj = {
+ fill: "none",
+ stroke: "#ffb203",
+ width: 3
+ },
+ makeNodeData = (relationObj) => {
+ if (relationObj) {
+ if (relationObj.updatedValues) {
+ return relationObj;
+ }
+ var nodeLabel = relationObj.displayText ? relationObj.displayText : " ",
+ obj = Object.assign(relationObj, {
+ shape: "img",
+ updatedValues: true,
+ label: nodeLabel.trunc(18),
+ toolTipLabel: nodeLabel,
+ id: relationObj.guid,
+ isLineage: true,
+ isIncomplete: relationObj.isIncomplete,
+ entityDef: this.getEntityDef({ typeName: relationObj.typeName, entityDefCollection })
+ });
+ obj["serviceType"] = this.getServiceType(obj);
+ obj["superTypes"] = this.getNestedSuperTypes({
+ ...obj,
+ entityDefCollection: entityDefCollection
+ });
+ obj["isProcess"] = this.isProcess(obj);
+ obj["isDeleted"] = this.isDeleted(obj);
+ return obj;
+ }
+ },
+ crateLineageRelationshipHashMap = function({ relations } = {}) {
+ var newHashMap = {};
+ relations.forEach(function(obj) {
+ if (newHashMap[obj.fromEntityId]) {
+ newHashMap[obj.fromEntityId].push(obj.toEntityId);
+ } else {
+ newHashMap[obj.fromEntityId] = [obj.toEntityId];
+ }
+ });
+ return newHashMap;
+ },
+ getStyleObjStr = function(styleObj) {
+ return "fill:" + styleObj.fill + ";stroke:" + styleObj.stroke + ";stroke-width:" + styleObj.width;
+ },
+ getNewToNodeRelationship = (toNodeGuid, filterObj) => {
+ if (toNodeGuid && relationshipMap[toNodeGuid]) {
+ var newRelationship = [];
+ relationshipMap[toNodeGuid].forEach((guid) => {
+ var nodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[guid]), filterObj);
+ if (nodeToBeUpdated.update) {
+ var newRelation = getNewToNodeRelationship(guid, filterObj);
+ if (newRelation) {
+ newRelationship = newRelationship.concat(newRelation);
+ }
+ } else {
+ newRelationship.push(guid);
+ }
+ });
+ return newRelationship;
+ } else {
+ return null;
+ }
+ },
+ getToNodeRelation = (toNodes, fromNodeToBeUpdated, filterObj) => {
+ var toNodeRelationship = [];
+ toNodes.forEach((toNodeGuid) => {
+ var toNodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[toNodeGuid]), filterObj);
+ if (toNodeToBeUpdated.update) {
+ // To node need to updated
+ if (pendingFromRelationship[toNodeGuid]) {
+ toNodeRelationship = toNodeRelationship.concat(pendingFromRelationship[toNodeGuid]);
+ } else {
+ var newToNodeRelationship = getNewToNodeRelationship(toNodeGuid, filterObj);
+ if (newToNodeRelationship) {
+ toNodeRelationship = toNodeRelationship.concat(newToNodeRelationship);
+ }
+ }
+ } else {
+ //when bothe node not to be updated.
+ toNodeRelationship.push(toNodeGuid);
+ }
+ });
+ return toNodeRelationship;
+ },
+ setNode = (guid) => {
+ if (!g._nodes[guid]) {
+ var nodeData = makeNodeData(guidEntityMap[guid]);
+ setGraphNode(guid, nodeData);
+ return nodeData;
+ } else {
+ return g._nodes[guid];
+ }
+ },
+ setEdge = function(fromNodeGuid, toNodeGuid, opt = {}) {
+ setGraphEdge(fromNodeGuid, toNodeGuid, {
+ arrowhead: "arrowPoint",
+ curve: curveBasis,
+ style: getStyleObjStr(styleObj),
+ styleObj: styleObj,
+ ...opt
+ });
+ },
+ setGraphData = function(fromEntityId, toEntityId) {
+ setNode(fromEntityId);
+ setNode(toEntityId);
+ setEdge(fromEntityId, toEntityId);
+ },
+ pendingFromRelationship = {};
+ if (isHideFilterOn) {
+ var relationshipMap = crateLineageRelationshipHashMap(data);
+ Object.keys(relationshipMap).forEach((fromNodeGuid) => {
+ var toNodes = relationshipMap[fromNodeGuid],
+ fromNodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[fromNodeGuid]), filterObj),
+ toNodeList = getToNodeRelation(toNodes, fromNodeToBeUpdated, filterObj);
+ if (fromNodeToBeUpdated.update) {
+ if (pendingFromRelationship[fromNodeGuid]) {
+ pendingFromRelationship[fromNodeGuid] = pendingFromRelationship[fromNodeGuid].concat(toNodeList);
+ } else {
+ pendingFromRelationship[fromNodeGuid] = toNodeList;
+ }
+ } else {
+ toNodeList.forEach(function(toNodeGuid) {
+ setGraphData(fromNodeGuid, toNodeGuid);
+ });
+ }
+ });
+ } else {
+ if (relations.length) {
+ relations.forEach(function(obj) {
+ setGraphData(obj.fromEntityId, obj.toEntityId);
+ });
+ } else {
+ setNode(guid);
+ }
+ }
+ if (g._nodes[guid]) {
+ if (g._nodes[guid]) {
+ g._nodes[guid]["isLineage"] = false;
+ }
+ this.findImpactNodeAndUpdateData({
+ guid,
+ g,
+ setEdge,
+ getStyleObjStr
+ });
+ }
+ if (!g._nodes[guid]) {
+ setNode(guid);
+ }
+ resolve(g);
+ } catch (e) {
+ reject(e);
+ }
+ });
+ },
+ findImpactNodeAndUpdateData: function({ guid, getStyleObjStr, g, setEdge }) {
+ var that = this,
+ traversedMap = {},
+ styleObj = {
+ fill: "none",
+ stroke: "#fb4200",
+ width: 3
+ },
+ traversed = function(toNodeList = {}, fromNodeGuid) {
+ let toNodeKeyList = Object.keys(toNodeList);
+ if (toNodeKeyList.length) {
+ if (!traversedMap[fromNodeGuid]) {
+ traversedMap[fromNodeGuid] = true;
+ toNodeKeyList.forEach(function(toNodeGuid) {
+ if (g._nodes[toNodeGuid]) {
+ g._nodes[toNodeGuid]["isLineage"] = false;
+ }
+ setEdge(fromNodeGuid, toNodeGuid, {
+ style: getStyleObjStr(styleObj),
+ styleObj: styleObj
+ });
+ traversed(g._sucs[toNodeGuid], toNodeGuid);
+ });
+ }
+ }
+ };
+ traversed(g._sucs[guid], guid);
+ }
};
export default DataUtils;
\ No newline at end of file
diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/LineageUtils.js b/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/LineageUtils.js
index 448a95ae6..588e3ac67 100644
--- a/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/LineageUtils.js
+++ b/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/LineageUtils.js
@@ -31,25 +31,25 @@ const LineageUtils = {
* @type {Number}
*/
nodeArrowDistance: 24,
- refreshGraphForSafari: function (options) {
+ refreshGraphForSafari: function(options) {
var edgePathEl = options.edgeEl,
IEGraphRenderDone = 0;
- edgePathEl.each(function (argument) {
+ edgePathEl.each(function(argument) {
var eleRef = this,
childNode = $(this).find("pattern");
- setTimeout(function (argument) {
+ setTimeout(function(argument) {
$(eleRef).find("defs").append(childNode);
}, 500);
});
},
- refreshGraphForIE: function ({ edgePathEl }) {
+ refreshGraphForIE: function({ edgePathEl }) {
var IEGraphRenderDone = 0;
- edgePathEl.each(function (argument) {
+ edgePathEl.each(function(argument) {
var childNode = $(this).find("marker");
$(this).find("marker").remove();
var eleRef = this;
++IEGraphRenderDone;
- setTimeout(function (argument) {
+ setTimeout(function(argument) {
$(eleRef).find("defs").append(childNode);
--IEGraphRenderDone;
if (IEGraphRenderDone === 0) {
@@ -67,9 +67,9 @@ const LineageUtils = {
* @param {[type]} options.edgePathEl [description]
* @return {[type]} [description]
*/
- dragNode: function ({ g, svg, guid, edgePathEl }) {
+ dragNode: function({ g, svg, guid, edgePathEl }) {
var dragHelper = {
- dragmove: function (el, d) {
+ dragmove: function(el, d) {
var node = select(el),
selectedNode = g.node(d),
prevX = selectedNode.x,
@@ -91,13 +91,13 @@ const LineageUtils = {
});
//LineageUtils.refreshGraphForIE({ edgePathEl: edgePathEl });
},
- translateEdge: function (e, dx, dy) {
- e.points.forEach(function (p) {
+ translateEdge: function(e, dx, dy) {
+ e.points.forEach(function(p) {
p.x = p.x + dx;
p.y = p.y + dy;
});
},
- calcPoints: function (e) {
+ calcPoints: function(e) {
var edge = g.edge(e.v, e.w),
tail = g.node(e.v),
head = g.node(e.w),
@@ -106,10 +106,10 @@ const LineageUtils = {
points.unshift(this.intersectRect(tail, points[0]));
points.push(this.intersectRect(head, points[points.length - 1]));
return line()
- .x(function (d) {
+ .x(function(d) {
return d.x;
})
- .y(function (d) {
+ .y(function(d) {
return d.y;
})
.curve(curveBasis)(points);
@@ -146,10 +146,10 @@ const LineageUtils = {
};
}
};
- var dragNodeHandler = drag().on("drag", function (d) {
+ var dragNodeHandler = drag().on("drag", function(d) {
dragHelper.dragmove.call(dragHelper, this, d);
}),
- dragEdgePathHandler = drag().on("drag", function (d) {
+ dragEdgePathHandler = drag().on("drag", function(d) {
dragHelper.translateEdge(g.edge(d.v, d.w), event.dx, event.dy);
var edgeObj = g.edge(d.v, d.w);
select(edgeObj.elem).select("path").attr("d", dragHelper.calcPoints(d));
@@ -158,16 +158,16 @@ const LineageUtils = {
dragNodeHandler(svg.selectAll("g.node"));
dragEdgePathHandler(svg.selectAll("g.edgePath"));
},
- zoomIn: function ({ svg, scaleFactor = 1.3 }) {
+ zoomIn: function({ svg, scaleFactor = 1.3 }) {
this.d3Zoom.scaleBy(svg.transition().duration(750), scaleFactor);
},
- zoomOut: function ({ svg, scaleFactor = 0.8 }) {
+ zoomOut: function({ svg, scaleFactor = 0.8 }) {
this.d3Zoom.scaleBy(svg.transition().duration(750), scaleFactor);
},
- zoom: function ({ svg, xa, ya, scale }) {
+ zoom: function({ svg, xa, ya, scale }) {
svg.transition().duration(750).call(this.d3Zoom.transform, zoomIdentity.translate(xa, ya).scale(scale));
},
- fitToScreen: function ({ svg }) {
+ fitToScreen: function({ svg }) {
var node = svg.node();
var bounds = node.getBBox();
@@ -197,14 +197,14 @@ const LineageUtils = {
* @param {[type]} options.onCenterZoomed [description]
* @return {[type]} [description]
*/
- centerNode: function ({ guid, g, svg, svgGroupEl, edgePathEl, width, height, fitToScreen, onCenterZoomed }) {
+ centerNode: function({ guid, g, svg, svgGroupEl, edgePathEl, width, height, fitToScreen, onCenterZoomed, isSelected }) {
this.d3Zoom = zoom();
svg.call(this.d3Zoom).on("dblclick.zoom", null);
// restrict events
let selectedNodeEl = svg.selectAll("g.nodes>g[id='" + guid + "']"),
- zoomListener = this.d3Zoom.scaleExtent([0.01, 50]).on("zoom", function () {
+ zoomListener = this.d3Zoom.scaleExtent([0.01, 50]).on("zoom", function() {
svgGroupEl.attr("transform", event.transform);
}),
x = null,
@@ -236,7 +236,13 @@ const LineageUtils = {
var xa = -(x * scale - width / 2),
ya = -(y * scale - height / 2);
this.zoom({ svg, xa, ya, scale });
- svg.transition().duration(750).call(this.d3Zoom.transform, zoomIdentity.translate(xa, ya).scale(scale));
+
+ if (!isSelected) {
+ svg.call(this.d3Zoom.transform, zoomIdentity.translate(xa, ya).scale(scale));
+ } else {
+ svg.transition().duration(750).call(this.d3Zoom.transform, zoomIdentity.translate(xa, ya).scale(scale));
+ }
+
if (onCenterZoomed) {
onCenterZoomed({ newScale: scale, newTranslate: [xa, ya], d3Zoom: this.d3Zoom, selectedNodeEl });
@@ -250,7 +256,7 @@ const LineageUtils = {
* @param {[type]} options.el [description]
* @return {[type]} [description]
*/
- getToolTipDirection: function ({ el }) {
+ getToolTipDirection: function({ el }) {
var width = select("body").node().getBoundingClientRect().width,
currentELWidth = select(el).node().getBoundingClientRect(),
direction = "e";
@@ -279,10 +285,10 @@ const LineageUtils = {
* @param {[type]} options.hoveredNode [description]
* @return {[type]} [description]
*/
- onHoverFade: function ({ svg, g, mouseenter, nodesToHighlight, hoveredNode }) {
+ onHoverFade: function({ svg, g, mouseenter, nodesToHighlight, hoveredNode }) {
var node = svg.selectAll(".node"),
path = svg.selectAll(".edgePath"),
- isConnected = function (a, b, o) {
+ isConnected = function(a, b, o) {
if (a === o || (b && b.length && b.indexOf(o) != -1)) {
return true;
}
@@ -292,14 +298,14 @@ const LineageUtils = {
var nextNode = g.successors(hoveredNode),
previousNode = g.predecessors(hoveredNode),
nodesToHighlight = nextNode.concat(previousNode);
- node.classed("hover-active-node", function (currentNode, i, nodes) {
+ node.classed("hover-active-node", function(currentNode, i, nodes) {
if (isConnected(hoveredNode, nodesToHighlight, currentNode)) {
return true;
} else {
return false;
}
});
- path.classed("hover-active-path", function (c) {
+ path.classed("hover-active-path", function(c) {
var _thisOpacity = c.v === hoveredNode || c.w === hoveredNode ? 1 : 0;
if (_thisOpacity) {
return true;
@@ -318,10 +324,10 @@ const LineageUtils = {
* @param {[type]} path [description]
* @return {[type]} [description]
*/
- getBaseUrl: function (url = window.location.pathname) {
+ getBaseUrl: function(url = window.location.pathname) {
return url.replace(/\/[\w-]+.(jsp|html)|\/+$/gi, "");
},
- getEntityIconPath: function ({ entityData, errorUrl, imgBasePath }) {
+ getEntityIconPath: function({ entityData, errorUrl, imgBasePath }) {
var iconBasePath = this.getBaseUrl() + (imgBasePath || "/img/entity-icon/");
if (entityData) {
let { typeName, serviceType, status, isProcess } = entityData;
@@ -348,7 +354,7 @@ const LineageUtils = {
if (errorUrl) {
// Check if the default img path has error, if yes then stop recursion.
- if (errorUrl.indexOf("table.png") > -1 || errorUrl.indexOf("process.png") > -1) {
+ if (errorUrl.indexOf("table.png") > -1) { //removed condition for default process image
return null;
}
var isErrorInTypeName = errorUrl && errorUrl.match("entity-icon/" + typeName + ".png|disabled/" + typeName + ".png") ? true : false;
@@ -369,15 +375,15 @@ const LineageUtils = {
}
}
},
- base64Encode: function (file, callback) {
+ base64Encode: function(file, callback) {
const reader = new FileReader();
reader.addEventListener("load", () => callback(reader.result));
reader.readAsDataURL(file);
},
- imgShapeRender: function (parent, bbox, node, { dagreD3, defsEl, imgBasePath, guid, isRankdirToBottom }) {
+ imgShapeRender: function(parent, bbox, node, { dagreD3, defsEl, imgBasePath, guid, isRankdirToBottom }) {
var that = this,
viewGuid = guid,
- imageIconPath = this.getEntityIconPath({ entityData: node, imgBasePath }),
+ imageIconPath = node.btnType ? "/img/entity-icon/expandBtn.svg" : this.getEntityIconPath({ entityData: node, imgBasePath }),
imgName = imageIconPath.split("/").pop();
if (this.imageObject === undefined) {
this.imageObject = {};
@@ -390,7 +396,7 @@ const LineageUtils = {
}
var shapeSvg = parent
.append("circle")
- .attr("fill", "url(#img_" + encodeURI(imgName) + ")")
+ .attr("fill", "url(#img_" + imgName + ")")
.attr("r", isRankdirToBottom ? "30px" : "24px")
.attr("data-stroke", node.id)
.attr("stroke-width", "2px")
@@ -401,90 +407,112 @@ const LineageUtils = {
if (node.isIncomplete === true) {
parent.attr("class", "node isIncomplete show");
parent
- .insert("foreignObject")
- .attr("x", "-25")
- .attr("y", "-25")
- .attr("width", "50")
- .attr("height", "50")
- .append("xhtml:div")
- .insert("i")
- .attr("class", "fa fa-hourglass-half");
+ .insert("rect")
+ .attr("x", "-5")
+ .attr("y", "-23")
+ .attr("width", "14")
+ .attr("height", "16")
+ .attr("fill", "url(#img_hourglass.svg)")
+ .attr("data-stroke", node.id)
+ .attr("stroke-width", "2px");
+
+ var patternConfigShellIcon = {
+ imgName: "hourglass.svg",
+ imageIconPath: "/img/entity-icon/hourglass.svg",
+ leftPosition: "0",
+ topPosition: "0",
+ width: "12",
+ height: "14"
+ };
+ svgPattern(patternConfigShellIcon);
}
+ var patternConfigEntityIcon = {
+ imgName: imgName,
+ imageIconPath: imageIconPath,
+ leftPosition: isRankdirToBottom ? "11" : "4",
+ topPosition: isRankdirToBottom ? "20" : currentNode ? "3" : "4",
+ width: "40",
+ height: "40"
+ };
+ svgPattern(patternConfigEntityIcon);
- if (defsEl.select('pattern[id="img_' + imgName + '"]').empty()) {
- defsEl
- .append("pattern")
- .attr("x", "0%")
- .attr("y", "0%")
- .attr("patternUnits", "objectBoundingBox")
- .attr("id", "img_" + imgName)
- .attr("width", "100%")
- .attr("height", "100%")
- .append("image")
- .attr("href", function (d) {
- var imgEl = this;
- if (node) {
- var getImageData = function (options) {
- var imagePath = options.imagePath,
- ajaxOptions = {
- url: imagePath,
- method: "GET",
- cache: true
- };
+ function svgPattern(patternConfig) {
+ if (defsEl.select('pattern[id="img_' + patternConfig.imgName + '"]').empty()) {
+ defsEl
+ .append("pattern")
+ .attr("x", "0%")
+ .attr("y", "0%")
+ .attr("patternUnits", "objectBoundingBox")
+ .attr("id", "img_" + patternConfig.imgName)
+ .attr("width", "100%")
+ .attr("height", "100%")
+ .append("image")
+ .attr("href", function(d) {
+ var imgEl = this;
+ if (node) {
+ var getImageData = function(options) {
+ var imagePath = options.imagePath,
+ ajaxOptions = {
+ url: imagePath,
+ method: "GET",
+ cache: true
+ };
- // if (platform.name !== "IE") {
- // ajaxOptions["mimeType"] = "text/plain; charset=x-user-defined";
- // }
- shapeSvg.attr("data-iconpath", imagePath);
- var xhr = new XMLHttpRequest();
- xhr.onreadystatechange = function () {
- if (xhr.readyState === 4) {
- if (xhr.status === 200) {
- if (platform.name !== "IE") {
- that.base64Encode(this.response, (url) => {
- that.imageObject[imageIconPath] = url;
- select(imgEl).attr("xlink:href", url);
- });
- } else {
- that.imageObject[imageIconPath] = imagePath;
- }
- if (imageIconPath !== shapeSvg.attr("data-iconpath")) {
- shapeSvg.attr("data-iconpathorigin", imageIconPath);
- }
- } else if (xhr.status === 404) {
- const imgPath = that.getEntityIconPath({ entityData: node, errorUrl: imagePath });
- if (imgPath === null) {
- const patternEL = select(imgEl.parentElement);
- patternEL.select("image").remove();
- patternEL
- .attr("patternContentUnits", "objectBoundingBox")
- .append("circle")
- .attr("r", "24px")
- .attr("fill", "#e8e8e8");
- } else {
- getImageData({
- imagePath: imgPath
- });
+ // if (platform.name !== "IE") {
+ // ajaxOptions["mimeType"] = "text/plain; charset=x-user-defined";
+ // }
+ shapeSvg.attr("data-iconpath", imagePath);
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === 4) {
+ if (xhr.status === 200) {
+ if (platform.name !== "IE") {
+ that.base64Encode(this.response, (url) => {
+ that.imageObject[patternConfig.imageIconPath] = url;
+ select(imgEl).attr("xlink:href", url);
+ });
+ } else {
+ that.imageObject[patternConfig.imageIconPath] = imagePath;
+ }
+ if (patternConfig.imageIconPath !== shapeSvg.attr("data-iconpath")) {
+ shapeSvg.attr("data-iconpathorigin", patternConfig.imageIconPath);
+ }
+ } else if (xhr.status === 404) {
+ const imgPath = that.getEntityIconPath({ entityData: node, errorUrl: imagePath });
+ if (imgPath === null) {
+ const patternEL = select(imgEl.parentElement);
+ patternEL.select("image").remove();
+ patternEL
+ .attr("patternContentUnits", "objectBoundingBox")
+ .append("circle")
+ .attr("r", "24px")
+ .attr("fill", "#e8e8e8");
+ } else {
+ getImageData({
+ imagePath: imgPath
+ });
+ }
}
}
- }
+ };
+ xhr.responseType = "blob";
+ xhr.open(ajaxOptions.method, ajaxOptions.url, true);
+ xhr.send(null);
};
- xhr.responseType = "blob";
- xhr.open(ajaxOptions.method, ajaxOptions.url, true);
- xhr.send(null);
- };
- getImageData({
- imagePath: imageIconPath
- });
- }
- })
- .attr("x", isRankdirToBottom ? "11" : "4")
- .attr("y", isRankdirToBottom ? "20" : currentNode ? "3" : "4")
- .attr("width", "40")
- .attr("height", "40");
+ getImageData({
+ imagePath: patternConfig.imageIconPath
+ });
+ }
+ })
+ .attr("x", patternConfig.leftPosition)
+ .attr("y", patternConfig.topPosition)
+ .attr("width", patternConfig.width)
+ .attr("height", patternConfig.height);
+ }
}
- node.intersect = function (point) {
+
+ node.intersect = function(point) {
return dagreD3.intersect.circle(node, currentNode ? that.nodeArrowDistance + 3 : that.nodeArrowDistance, point);
};
return shapeSvg;
@@ -494,7 +522,7 @@ const LineageUtils = {
* @param {[type]} {parent, id, edge, type, viewOptions [description]
* @return {[type]} [description]
*/
- arrowPointRender: function (parent, id, edge, type, { dagreD3 }) {
+ arrowPointRender: function(parent, id, edge, type, { dagreD3 }) {
var node = parent.node(),
parentNode = node ? node.parentNode : parent;
select(parentNode)
@@ -523,11 +551,11 @@ const LineageUtils = {
* @param {[type]} options.onExportLineage [description]
* @return {[type]} [description]
*/
- saveSvg: function ({ svg, width, height, downloadFileName, onExportLineage }) {
+ saveSvg: function({ svg, width, height, downloadFileName, onExportLineage }) {
var that = this,
svgClone = svg.clone(true).node(),
scaleFactor = 1;
- setTimeout(function () {
+ setTimeout(function() {
if (platform.name === "Firefox") {
svgClone.setAttribute("width", width);
svgClone.setAttribute("height", height);
@@ -570,15 +598,16 @@ const LineageUtils = {
if (platform.name === "Safari") {
svgBlob = new Blob([data], { type: "image/svg+xml" });
}
+ ctx.drawImage(img, 50, 50, canvas.width, canvas.height);
var url = DOMURL.createObjectURL(svgBlob);
- img.onload = function () {
+ img.onload = function() {
try {
var a = document.createElement("a");
a.download = downloadFileName;
document.body.appendChild(a);
ctx.drawImage(img, 50, 50, canvas.width, canvas.height);
- canvas.toBlob(function (blob) {
+ canvas.toBlob(function(blob) {
if (!blob) {
onExportLineage({ status: "failed", message: "There was an error in downloading Lineage!" });
return;
diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/src/index.js b/dashboardv3/public/js/external_lib/atlas-lineage/src/index.js
index 3ceb3d90a..0c4702237 100644
--- a/dashboardv3/public/js/external_lib/atlas-lineage/src/index.js
+++ b/dashboardv3/public/js/external_lib/atlas-lineage/src/index.js
@@ -45,6 +45,7 @@ export default class LineageHelper {
zoom: (arg) => this.zoom(arg),
fullScreen: (arg) => this.fullScreen(arg),
searchNode: (arg) => this.searchNode(arg),
+ displayFullName: (arg) => this.displayFullName(arg),
removeNodeSelection: (arg) => this.removeNodeSelection(arg),
getGraphOptions: () => this.graphOptions,
getNode: (guid, actual) => {
@@ -163,14 +164,36 @@ export default class LineageHelper {
zoom(opt = {}) {
LineageUtils.zoom({ ...this.graphOptions, ...opt });
}
+
+ displayFullName(opt = {}) {
+ var that = this;
+ this.g.nodes().forEach(function(v) {
+ var selectedNodeEl = that.svg.selectAll("g.nodes>g[id='" + v + "']"),
+ label = that.g.node(v).toolTipLabel;
+ if (opt.bLabelFullText == true)
+ selectedNodeEl.select('tspan').text(label);
+ else
+ selectedNodeEl.select('tspan').text(label.trunc(18));
+ });
+ if (this.selectedNode) {
+ this.searchNode({ guid: this.selectedNode });
+ }
+ }
+
/**
* [refresh Allows user to rerender the lineage]
* @return {[type]} [description]
*/
- refresh() {
+ refresh(options) {
this.clear();
this._initializeGraph();
this._initGraph({ refresh: true });
+ this.selectedNode = "";
+ if (options && options.compactLineageEnabled && options.filterObj) {
+ var isProcessHideCheck = options.filterObj.isProcessHideCheck,
+ isDeletedEntityHideCheck = options.filterObj.isDeletedEntityHideCheck;
+ this._AddFilterNotification(isProcessHideCheck, isDeletedEntityHideCheck);
+ }
}
/**
* [removeNodeSelection description]
@@ -185,23 +208,32 @@ export default class LineageHelper {
*/
searchNode({ guid, onSearchNode }) {
this.svg.selectAll(".serach-rect").remove();
+ this.svg.selectAll(".label").attr("stroke", "none");
+ this.selectedNode = guid;
this.centerAlign({
guid: guid,
- onCenterZoomed: function (opts) {
+ onCenterZoomed: function(opts) {
const { selectedNodeEl } = opts;
+ var oSelectedNode = selectedNodeEl.node().getBBox(),
+ rectWidth = oSelectedNode.width + 10,
+ rectXPos = oSelectedNode.x - 5;
selectedNodeEl.select(".label").attr("stroke", "#316132");
selectedNodeEl.select("circle").classed("wobble", true);
selectedNodeEl
.insert("rect", "circle")
.attr("class", "serach-rect")
- .attr("x", -50)
+ .attr("stroke", "#37bb9b")
+ .attr("stroke-width", "2.5px")
+ .attr("fill", "none")
+ .attr("x", rectXPos)
.attr("y", -27.5)
- .attr("width", 100)
- .attr("height", 55);
+ .attr("width", rectWidth)
+ .attr("height", 60);
if (onSearchNode && typeof onSearchNode === "function") {
onSearchNode(opts);
}
- }
+ },
+ isSelected: true
});
}
@@ -287,8 +319,7 @@ export default class LineageHelper {
// initlize the dagreD3 graphlib
this.g = new dagreD3.graphlib.Graph()
.setGraph(
- Object.assign(
- {
+ Object.assign({
nodesep: 50,
ranksep: 90,
rankdir: "LR",
@@ -301,7 +332,7 @@ export default class LineageHelper {
this.options.dagreOptions
)
)
- .setDefaultEdgeLabel(function () {
+ .setDefaultEdgeLabel(function() {
return {};
});
@@ -339,7 +370,7 @@ export default class LineageHelper {
if (this.options.setDataManually === true) {
return;
- } else if (this.options.data === undefined || (this.options.data && this.options.data.relations.length === 0)) {
+ } else if (this.options.data === undefined || (this.options.data && this.options.data.relations.length === 0 && _.isEmpty(this.options.data.guidEntityMap))) {
if (this.options.beforeRender) {
this.options.beforeRender();
}
@@ -402,8 +433,7 @@ export default class LineageHelper {
* @param {[type]} graphOptions [description]
* @return {[type]} [description]
*/
- _createGraph(
- {
+ _createGraph({
data = {},
imgBasePath,
isShowTooltip,
@@ -416,12 +446,12 @@ export default class LineageHelper {
getToolTipContent,
toolTipTitle
},
- graphOptions,
- { refresh }
+ graphOptions, { refresh }
) {
if (this.options.beforeRender) {
this.options.beforeRender();
}
+ this.selectedNode = "";
const that = this,
{ svg, g, width, height } = graphOptions,
isRankdirToBottom = this.options.dagreOptions && this.options.dagreOptions.rankdir === "tb";
@@ -435,7 +465,7 @@ export default class LineageHelper {
return;
}
- g.nodes().forEach(function (v) {
+ g.nodes().forEach(function(v) {
var node = g.node(v);
// Round the corners of the nodes
if (node) {
@@ -452,11 +482,11 @@ export default class LineageHelper {
// Create the renderer
var render = new dagreD3.render();
// Add our custom arrow (a hollow-point)
- render.arrows().arrowPoint = function () {
+ render.arrows().arrowPoint = function() {
return LineageUtils.arrowPointRender(...arguments, { ...graphOptions });
};
// Render custom img inside shape
- render.shapes().img = function () {
+ render.shapes().img = function() {
return LineageUtils.imgShapeRender(...arguments, {
...graphOptions,
isRankdirToBottom: isRankdirToBottom,
@@ -506,17 +536,18 @@ export default class LineageHelper {
if (isRankdirToBottom) {
return "translate(2,-20)";
}
- return "translate(2,-35)";
+ return "translate(2,-38)";
})
- .on("mouseenter", function (d) {
+ .attr("font-size", "10px")
+ .on("mouseenter", function(d) {
event.preventDefault();
select(this).classed("highlight", true);
})
- .on("mouseleave", function (d) {
+ .on("mouseleave", function(d) {
event.preventDefault();
select(this).classed("highlight", false);
})
- .on("click", function (d) {
+ .on("click", function(d) {
event.preventDefault();
if (onLabelClick && typeof onLabelClick === "function") {
onLabelClick({ clickedData: d });
@@ -526,12 +557,12 @@ export default class LineageHelper {
svgGroupEl
.selectAll("g.nodes g.node circle")
- .on("mouseenter", function (d, index, element) {
+ .on("mouseenter", function(d, index, element) {
that.activeNode = true;
var matrix = this.getScreenCTM().translate(+this.getAttribute("cx"), +this.getAttribute("cy"));
that.svg.selectAll(".node").classed("active", false);
select(this).classed("active", true);
- if (that._getValueFromUser(isShowTooltip)) {
+ if (that._getValueFromUser(isShowTooltip) && (d.indexOf("more") !== 0)) {
var direction = LineageUtils.getToolTipDirection({ el: this });
tooltip.direction(direction).show(d, this);
}
@@ -545,10 +576,10 @@ export default class LineageHelper {
...graphOptions
});
})
- .on("mouseleave", function (d) {
+ .on("mouseleave", function(d) {
that.activeNode = false;
var nodeEL = this;
- setTimeout(function (argument) {
+ setTimeout(function(argument) {
if (!(that.activeTip || that.activeNode)) {
select(nodeEL).classed("active", false);
if (that._getValueFromUser(isShowTooltip)) {
@@ -565,7 +596,7 @@ export default class LineageHelper {
...graphOptions
});
})
- .on("click", function (d) {
+ .on("click", function(d) {
if (event.defaultPrevented) return; // ignore drag
event.preventDefault();
tooltip.hide(d);
@@ -578,9 +609,9 @@ export default class LineageHelper {
// Bind event on edgePath
var edgePathEl = svgGroupEl.selectAll("g.edgePath");
- edgePathEl.selectAll("path.path").on("click", function (d) {
+ edgePathEl.selectAll("path.path").on("click", function(d) {
if (onPathClick && typeof onPathClick === "function") {
- var pathRelationObj = data.relations.find(function (obj) {
+ var pathRelationObj = data.relations.find(function(obj) {
if (obj.fromEntityId === d.v && obj.toEntityId === d.w) {
return true;
}
@@ -651,5 +682,16 @@ export default class LineageHelper {
span = container.append("span").style("color", "#fb4200");
span.append("i").classed("fa fa-long-arrow-right fa-fw", true);
span.append("span").html("Impact");
+
+ span = container.append("span").classed("notification hide", true).style("color", "#686868");
+ span.append("i").classed("fa fa-exclamation fa-fw", true);
+ span.append("span").html("Filtering hides all Expand buttons.");
+ }
+ _AddFilterNotification(isProcessHideCheck, isDeletedEntityHideCheck) {
+ if ((isProcessHideCheck || isDeletedEntityHideCheck)) {
+ $(this.options.legendsEl).find('.notification').removeClass('hide');
+ } else {
+ $(this.options.legendsEl).find('.notification').addClass('hide');
+ }
}
}
\ No newline at end of file
diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/src/styles/graph.scss b/dashboardv3/public/js/external_lib/atlas-lineage/src/styles/graph.scss
index ab1e82df3..2f1322765 100644
--- a/dashboardv3/public/js/external_lib/atlas-lineage/src/styles/graph.scss
+++ b/dashboardv3/public/js/external_lib/atlas-lineage/src/styles/graph.scss
@@ -26,17 +26,17 @@
//transition: opacity 0.3s linear;
- rect {
- stroke: $color_mountain_mist_approx;
- fill: $white;
- stroke-width: 1.5px;
-
- &.serach-rect {
- stroke: $color_keppel_approx;
- fill: transparent;
- stroke-width: 2.5px;
- }
- }
+ // rect {
+ // stroke: $color_mountain_mist_approx;
+ // fill: $white;
+ // stroke-width: 1.5px;
+
+ // &.serach-rect {
+ // stroke: $color_keppel_approx;
+ // fill: transparent;
+ // stroke-width: 2.5px;
+ // }
+ // }
.label {
fill: $color_suva_gray_approx;
@@ -104,7 +104,7 @@
}
.legends {
- > span {
+ >span {
margin-right: 8px;
font-family: $font_0;
}
@@ -156,10 +156,12 @@ svg.hover {
z-index: 999;
max-width: 300px; //Instead of the line below you could use @include border-radius($radius, $vertical-radius)
border-radius: 2px;
+ word-break: break-all;
.tip-inner-scroll {
overflow: auto;
max-height: 300px;
+
h5 {
margin: 7px 0px;
}
@@ -211,7 +213,7 @@ svg.hover {
}
}
-g.type-TK > rect {
+g.type-TK>rect {
fill: $color_bright_turquoise_approx;
}
diff --git a/dashboardv3/public/js/main.js b/dashboardv3/public/js/main.js
index 008fbb222..b1aaec26b 100644
--- a/dashboardv3/public/js/main.js
+++ b/dashboardv3/public/js/main.js
@@ -327,6 +327,12 @@ require(['App',
Globals.isTasksEnabled = response['atlas.tasks.enabled'];
}
if (response['atlas.session.timeout.secs']) { Globals.idealTimeoutSeconds = response['atlas.session.timeout.secs']; }
+ if(response['atlas.lineage.on.demand.enabled'] !== undefined){
+ Globals.isLineageOnDemandEnabled = response['atlas.lineage.on.demand.enabled'];
+ }
+ if(response['atlas.lineage.on.demand.default.node.count'] !== undefined){
+ Globals.lineageNodeCount = response['atlas.lineage.on.demand.default.node.count'];
+ }
/* Atlas idealTimeout
redirectUrl: url to redirect after timeout
idealTimeLimit: timeout in seconds
diff --git a/dashboardv3/public/js/templates/graph/LineageLayoutView_tmpl.html b/dashboardv3/public/js/templates/graph/LineageLayoutView_tmpl.html
index 5f90b096e..30dd45d7f 100644
--- a/dashboardv3/public/js/templates/graph/LineageLayoutView_tmpl.html
+++ b/dashboardv3/public/js/templates/graph/LineageLayoutView_tmpl.html
@@ -90,10 +90,20 @@
<div class="pretty p-switch p-fill">
<input type="checkbox" class="pull-left" data-id="labelFullName" value="" id="labelFullName"/>
<div class="state p-primary">
- <label>Display fullname</label>
+ <label>Display full name</label>
</div>
</div>
</div>
+ {{#if compactLineageEnabled}}
+ <div class="showTooltip text-left col-sm-12">
+ <div class="nodeCount-container">
+ <label class="col-sm-8 no-padding">Nodes On Demand</label>
+ <div class="col-sm-4 no-padding">
+ <select data-id="selectNodeCount" class="form-control"></select>
+ </div>
+ </div>
+ </div>
+ {{/if}}
</div>
</div>
<div class="graph-button-group pull-right">
diff --git a/dashboardv3/public/js/utils/Globals.js b/dashboardv3/public/js/utils/Globals.js
index 5bbc71a69..9a51c4dc4 100644
--- a/dashboardv3/public/js/utils/Globals.js
+++ b/dashboardv3/public/js/utils/Globals.js
@@ -54,6 +54,10 @@ define(["require", "underscore"], function(require, _) {
Globals.isTasksEnabled = false;
Globals.advanceSearchData = {};
Globals.idealTimeoutSeconds = 900;
+ Globals.isFullScreenView = false;
+ Globals.isLineageOnDemandEnabled = false;
+ Globals.lineageNodeCount = 3;
+ Globals.lineageDepth = 3;
return Globals;
});
\ No newline at end of file
diff --git a/dashboardv3/public/js/utils/Helper.js b/dashboardv3/public/js/utils/Helper.js
index a242098b1..164beac57 100644
--- a/dashboardv3/public/js/utils/Helper.js
+++ b/dashboardv3/public/js/utils/Helper.js
@@ -17,11 +17,12 @@
*/
define(['require',
'utils/Utils',
+ 'utils/Globals',
'd3',
'marionette',
'jquery-ui',
'jstree'
-], function(require, Utils, d3) {
+], function(require, Utils, Globals, d3) {
'use strict';
_.mixin({
numberFormatWithComma: function(number) {
@@ -393,5 +394,11 @@ define(['require',
//For closing the modal on browsers navigation
$(window).on('popstate', function() {
$('body').find('.modal-dialog .close').click();
+ //To close the full-screen mode in lineage on browsers navigation.
+ if (!Globals.isFullScreenView) {
+ $('#tab-lineage').removeClass("fullscreen-mode");
+ $("#r_lineageLayoutView").find('button[data-id="fullScreen-toggler"]').attr("data-original-title", "Full Screen").find("i").removeClass("fa-compress").addClass("fa-expand");
+ }
+ Globals.isFullScreenView = false;
});
})
\ No newline at end of file
diff --git a/dashboardv3/public/js/views/graph/LineageLayoutView.js b/dashboardv3/public/js/views/graph/LineageLayoutView.js
index e989c4719..ce7692535 100644
--- a/dashboardv3/public/js/views/graph/LineageLayoutView.js
+++ b/dashboardv3/public/js/views/graph/LineageLayoutView.js
@@ -52,6 +52,7 @@ define(['require',
checkHideProcess: "[data-id='checkHideProcess']",
checkDeletedEntity: "[data-id='checkDeletedEntity']",
selectDepth: 'select[data-id="selectDepth"]',
+ selectNodeCount: 'select[data-id="selectNodeCount"]',
filterToggler: '[data-id="filter-toggler"]',
settingToggler: '[data-id="setting-toggler"]',
searchToggler: '[data-id="search-toggler"]',
@@ -74,7 +75,8 @@ define(['require',
templateHelpers: function() {
return {
width: "100%",
- height: "100%"
+ height: "100%",
+ compactLineageEnabled: Globals.isLineageOnDemandEnabled
};
},
/** ui events hash */
@@ -83,6 +85,7 @@ define(['require',
events["click " + this.ui.checkHideProcess] = 'onCheckUnwantedEntity';
events["click " + this.ui.checkDeletedEntity] = 'onCheckUnwantedEntity';
events['change ' + this.ui.selectDepth] = 'onSelectDepthChange';
+ events['change ' + this.ui.selectNodeCount] = 'onSelectNodeCount';
events["click " + this.ui.filterToggler] = 'onClickFilterToggler';
events["click " + this.ui.boxClose] = 'toggleBoxPanel';
events["click " + this.ui.settingToggler] = 'onClickSettingToggler';
@@ -109,7 +112,7 @@ define(['require',
this.filterObj = {
isProcessHideCheck: false,
isDeletedEntityHideCheck: false,
- depthCount: ''
+ depthCount: Globals.lineageDepth
};
this.searchNodeObj = {
selectedNode: ''
@@ -117,16 +120,30 @@ define(['require',
this.labelFullText = false;
},
onRender: function() {
- var that = this;
+ var that = this,
+ nodeCountArray = _.uniq([3, 6, Globals.lineageNodeCount]);
+ this.initialQueryObj = {};
this.ui.searchToggler.prop("disabled", true);
- this.$graphButtonsEl = this.$(".graph-button-group button, select[data-id='selectDepth']")
- this.fetchGraphData();
+ this.$graphButtonsEl = this.$(".graph-button-group button, select[data-id='selectDepth']");
+ if (Globals.isLineageOnDemandEnabled) {
+ this.ui.resetLineage.attr("title", "Reset Lineage");
+ this.initialQueryObj[this.guid] = {
+ "direction": "BOTH",
+ "inputRelationsLimit": Globals.lineageNodeCount,
+ "outputRelationsLimit": Globals.lineageNodeCount,
+ "depth": Globals.lineageDepth,
+ }
+ }
+ this.fetchGraphData({ queryParam: this.initialQueryObj });
if (this.layoutRendered) {
this.layoutRendered();
}
if (this.processCheck) {
this.hideCheckForProcess();
}
+ if (this.entity.status === "DELETED") {
+ this.hideCheckForDeletedEntity();
+ }
//this.initializeGraph();
this.ui.selectDepth.select2({
data: _.sortBy([3, 6, 9, 12, 15, 18, 21]),
@@ -134,6 +151,13 @@ define(['require',
dropdownCssClass: "number-input",
multiple: false
});
+ this.ui.selectNodeCount.select2({
+ data: _.sortBy(nodeCountArray),
+ tags: true,
+ dropdownCssClass: "number-input",
+ multiple: false
+ });
+ this.ui.selectNodeCount.val(Globals.lineageNodeCount).trigger("change");
},
onShow: function() {
this.$('.fontLoader').show();
@@ -150,6 +174,7 @@ define(['require',
panel = $(e.target).parents('.tab-pane').first();
icon.toggleClass('fa-expand fa-compress');
if (icon.hasClass('fa-expand')) {
+ Globals.isFullScreenView = false;
icon.parent('button').attr("data-original-title", "Full Screen");
} else {
icon.parent('button').attr("data-original-title", "Default View");
@@ -165,17 +190,22 @@ define(['require',
onCheckUnwantedEntity: function(e) {
var that = this;
//this.initializeGraph();
+ this.searchNodeObj.selectedNode = "";
if ($(e.target).data("id") === "checkHideProcess") {
this.filterObj.isProcessHideCheck = e.target.checked;
} else {
this.filterObj.isDeletedEntityHideCheck = e.target.checked;
}
- this.LineageHelperRef.refresh();
+ this.renderLineageTypeSearch(this.data);
+ this.LineageHelperRef.refresh({ compactLineageEnabled: Globals.isLineageOnDemandEnabled, filterObj: this.filterObj });
},
toggleBoxPanel: function(options) {
var el = options && options.el,
nodeDetailToggler = options && options.nodeDetailToggler,
currentTarget = options.currentTarget;
+ if (options.nodeDetailToggler) {
+ this.ui.lineageTypeSearch.select2("close");
+ }
this.$el.find('.show-box-panel').removeClass('show-box-panel');
if (el && el.addClass) {
el.addClass('show-box-panel');
@@ -214,12 +244,33 @@ define(['require',
},
onSelectDepthChange: function(e, options) {
//this.initializeGraph();
- this.filterObj.depthCount = e.currentTarget.value;
+ Globals.lineageDepth = parseInt(e.currentTarget.value);
//legends property is added in queryParam to stop the legend getting added in lineage graph whenever dept is changed.
- this.fetchGraphData({ queryParam: { 'depth': this.filterObj.depthCount }, 'legends': false });
+ if (!Globals.isLineageOnDemandEnabled) {
+ this.fetchGraphData({ queryParam: { 'depth': Globals.lineageDepth }, 'legends': false });
+ }
+
+ if (Globals.isLineageOnDemandEnabled) {
+ this.initialQueryObj[this.guid].depth = Globals.lineageDepth;
+ this.fetchGraphData({ queryParam: this.initialQueryObj, 'legends': false })
+ }
+ },
+ onSelectNodeCount: function(e, options) {
+ Globals.lineageNodeCount = parseInt(e.target.value);
+ if (Globals.lineageNodeCount === 0) {
+ Utils.notifyWarn({
+ content: 'Value cannot be less than 1'
+ });
+ this.ui.selectNodeCount.val(3).trigger("change");
+ }
},
onClickResetLineage: function() {
- this.LineageHelperRef.refresh();
+ if (Globals.isLineageOnDemandEnabled) {
+ this.fetchGraphData({ queryParam: this.initialQueryObj, 'legends': false });
+ }
+ if (!Globals.isLineageOnDemandEnabled) {
+ this.LineageHelperRef.refresh();
+ }
this.searchNodeObj.selectedNode = "";
this.ui.lineageTypeSearch.data({ refresh: true }).val("").trigger("change");
this.ui.labelFullName.prop("checked", false);
@@ -270,13 +321,14 @@ define(['require',
}
_.extend(this.currentEntityData, _.pick(this.entity, 'attributes', 'guid', 'isIncomplete', 'status', 'typeName'));
//End
- this.collection.getLineage(this.guid, {
- queryParam: queryParam,
+ var dataObj = {
+ compactLineageEnabled: Globals.isLineageOnDemandEnabled,
success: function(data) {
if (that.isDestroyed) {
return;
}
data["legends"] = options ? options.legends : true;
+ that.lineageOnDemandPayload = data.lineageOnDemandPayload ? data.lineageOnDemandPayload : {};
// show only main part of lineage current entity is at bottom, so reverse is done
var relationsReverse = data.relations ? data.relations.reverse() : null,
lineageMaxRelationCount = 9000;
@@ -292,6 +344,10 @@ define(['require',
data.guidEntityMap[data.baseEntityGuid] = that.currentEntityData;
}
}
+ that.data = data;
+ var updatedData = that.updateLineageData(data);
+ _.extend(data.guidEntityMap, updatedData.plusBtnsObj);
+ data.relations = data.relations.concat(updatedData.plusBtnRelationsArray);
that.createGraph(data);
that.renderLineageTypeSearch(data);
},
@@ -302,7 +358,68 @@ define(['require',
that.$('.fontLoader').hide();
that.$('svg>g').show();
}
- })
+ };
+ Globals.isLineageOnDemandEnabled ? dataObj.data = queryParam : dataObj.queryParam = queryParam;
+
+ this.collection.getLineage(this.guid, dataObj)
+ },
+ updateLineageData: function(data) {
+ var that = this,
+ rawData = data,
+ plusBtnsObj = {},
+ plusBtnRelationsArray = [];
+ this.relationsOnDemand = data.relationsOnDemand ? data.relationsOnDemand : null;
+ this.lineageOnDemandPayload = data.lineageOnDemandPayload ? data.lineageOnDemandPayload : null;
+ if (this.relationsOnDemand) {
+ _.each(this.relationsOnDemand, function(values, nodeId) {
+ if (values.hasMoreInputs) {
+ var btnType = "Input",
+ moreInputBtnObj = that.createExpandButtonObj({ nodeId: nodeId, btnType: btnType });
+ plusBtnsObj[moreInputBtnObj.guid] = moreInputBtnObj;
+ plusBtnRelationsArray.push({ fromEntityId: moreInputBtnObj.guid, toEntityId: nodeId, relationshipId: 'dummy' });
+ }
+ if (values.hasMoreOutputs) {
+ var btnType = "Output",
+ moreOutputBtnObj = that.createExpandButtonObj({ nodeId: nodeId, btnType: btnType });
+ plusBtnsObj[moreOutputBtnObj.guid] = moreOutputBtnObj;
+ plusBtnRelationsArray.push({ fromEntityId: nodeId, toEntityId: moreOutputBtnObj.guid, relationshipId: 'dummy' });
+ }
+ });
+ return {
+ plusBtnsObj: plusBtnsObj,
+ plusBtnRelationsArray: plusBtnRelationsArray
+ }
+ }
+ },
+ generateAddButtonId: function(btnType) {
+ return btnType + Math.random().toString(16).slice(2)
+ },
+ createExpandButtonObj: function(options) {
+ var defaultObj = {
+ attributes: {
+ owner: '',
+ createTime: 0,
+ qualifiedName: 'PlusBtn',
+ name: 'PlusBtn',
+ description: ''
+ },
+ isExpandBtn: true,
+ classificationNames: [],
+ displayText: "Expand",
+ isIncomplete: false,
+ labels: [],
+ meaningNames: [],
+ meanings: [],
+ status: "ACTIVE",
+ typeName: "Table"
+ },
+ btnObj = Object.assign({}, defaultObj),
+ btnType = (options.btnType === "Input") ? "more-inputs" : "more-outputs",
+ btnId = this.generateAddButtonId(btnType);
+ btnObj.guid = btnId;
+ btnObj.parentNodeGuid = options.nodeId;
+ btnObj.btnType = options.btnType;
+ return btnObj;
},
createGraph: function(data) {
var that = this;
@@ -323,7 +440,6 @@ define(['require',
isShowHoverPath: function() { return that.ui.showOnlyHoverPath.prop('checked') },
isShowTooltip: function() { return that.ui.showTooltip.prop('checked') },
onPathClick: function(d) {
- console.log("Path Clicked");
if (d.pathRelationObj) {
var relationshipId = d.pathRelationObj.relationshipId;
require(['views/graph/PropagationPropertyModal'], function(PropagationPropertyModal) {
@@ -338,12 +454,21 @@ define(['require',
}
},
onNodeClick: function(d) {
+ if (d.clickedData.indexOf("more") >= 0) {
+ that.onExpandNodeClick({ guid: d.clickedData });
+ return;
+ }
that.onClickNodeToggler();
that.updateRelationshipDetails({ guid: d.clickedData });
that.calculateLineageDetailPanelHeight();
},
onLabelClick: function(d) {
var guid = d.clickedData;
+ Globals.isFullScreenView = true;
+ that.ui.lineageTypeSearch.select2("close");
+ if (guid.indexOf("more") >= 0) {
+ return;
+ }
if (that.guid == guid) {
Utils.notifyInfo({
html: true,
@@ -376,6 +501,55 @@ define(['require',
}
});
},
+ onExpandNodeClick: function(options) {
+ var parentNodeData = this.LineageHelperRef.getNode(options.guid);
+ this.updateQueryObject(parentNodeData.parentNodeGuid, parentNodeData.btnType);
+ },
+ updateQueryObject: function(parentId, btnType) {
+ var inputLimit = null,
+ outputLimit = null,
+ that = this,
+ queryParam;
+ if (_.has(that.lineageOnDemandPayload, parentId)) {
+ _.find(that.lineageOnDemandPayload, function(value, key) {
+ if (key === parentId) {
+ if (btnType === "Input") {
+ value.inputRelationsLimit = value.inputRelationsLimit + Globals.lineageNodeCount;
+ value.outputRelationsLimit = value.outputRelationsLimit;
+ }
+ if (btnType === "Output") {
+ value.inputRelationsLimit = value.inputRelationsLimit;
+ value.outputRelationsLimit = value.outputRelationsLimit + Globals.lineageNodeCount;
+ }
+ }
+ });
+ } else {
+ var relationCount = that.validateInputOutputLimit(parentId, btnType);
+ if (btnType === "Input") {
+ inputLimit = relationCount.inputRelationCount + Globals.lineageNodeCount;
+ outputLimit = relationCount.outputRelationCount;
+ }
+ if (btnType === "Output") {
+ inputLimit = relationCount.inputRelationCount;
+ outputLimit = relationCount.outputRelationCount + Globals.lineageNodeCount;
+ }
+ this.lineageOnDemandPayload[parentId] = { direction: "BOTH", inputRelationsLimit: inputLimit, outputRelationsLimit: outputLimit, depth: Globals.lineageDepth };
+ }
+ this.fetchGraphData({ queryParam: this.lineageOnDemandPayload, 'legends': false });
+ },
+ validateInputOutputLimit: function(parentId, btnType) {
+ var inputRelationCount, outputRelationCount;
+ for (var guid in this.relationsOnDemand) {
+ if (parentId === guid && (btnType === "Input" || btnType === "Output")) {
+ inputRelationCount = this.relationsOnDemand[guid].inputRelationsCount ? this.relationsOnDemand[guid].inputRelationsCount : Globals.lineageNodeCount;
+ outputRelationCount = this.relationsOnDemand[guid].outputRelationsCount ? this.relationsOnDemand[guid].outputRelationsCount : Globals.lineageNodeCount;
+ }
+ }
+ return {
+ inputRelationCount: inputRelationCount,
+ outputRelationCount: outputRelationCount
+ };
+ },
noLineage: function() {
this.$('.fontLoader').hide();
this.$('.depth-container').hide();
@@ -387,6 +561,10 @@ define(['require',
hideCheckForProcess: function() {
this.$('.hideProcessContainer').hide();
},
+ hideCheckForDeletedEntity: function() {
+ //This has been added to handle the scenario where hideDeletedEntityCheck should hide form filters when baseEntity is deleted.
+ this.$('.hideDeletedContainer').hide();
+ },
renderLineageTypeSearch: function(data) {
var that = this;
return new Promise(function(resolve, reject) {
@@ -395,7 +573,7 @@ define(['require',
if (!_.isEmpty(data)) {
_.each(data.guidEntityMap, function(obj, index) {
var nodeData = that.LineageHelperRef.getNode(obj.guid);
- if ((that.filterObj.isProcessHideCheck || that.filterObj.isDeletedEntityHideCheck) && nodeData && (nodeData.isProcess || nodeData.isDeleted)) {
+ if ((that.filterObj.isProcessHideCheck && obj && obj.isProcess) || (that.filterObj.isDeletedEntityHideCheck && obj && obj.isDeleted) || (Globals.isLineageOnDemandEnabled && obj && _.contains(["Input", "Output"], obj.btnType))) {
return;
}
typeStr += '<option value="' + obj.guid + '">' + obj.displayText + '</option>';