1259 lines
60 KiB
JavaScript
1259 lines
60 KiB
JavaScript
"use strict";
|
|
(function () {
|
|
'use strict';
|
|
angular.module('assetModule')
|
|
.directive('graphicalCi', ['$timeout', '$window', 'browser', 'ciExplorerModel', 'systemAlertService',
|
|
'i18nService', '$filter', '$modal', '$state',
|
|
function ($timeout, $window, browser, ciExplorerModel, systemAlertService, i18nService, $filter, $modal, $state) {
|
|
return {
|
|
restrict: 'E',
|
|
replace: true,
|
|
scope: {
|
|
rootCi: '='
|
|
},
|
|
templateUrl: 'views/asset/graphical-ci.html',
|
|
link: function (scope, element) {
|
|
var iconList = [{
|
|
"name": "BMC_PROTOCOLENDPOINT",
|
|
"label": "Protocol Endpoint"
|
|
},
|
|
{
|
|
"name": "BMC_NTDOMAIN",
|
|
"label": "NT Domain"
|
|
},
|
|
{
|
|
"name": "BMC_CONNECTIVITYGROUP",
|
|
"label": "Connectivity Collection"
|
|
},
|
|
{
|
|
"name": "BMC_CONNECTIVITYSEGMENT",
|
|
"label": "Connectivity Segment"
|
|
},
|
|
{
|
|
"name": "BMC_IPCONNECTIVITYSUBNET",
|
|
"label": "IP Connectivity Subnet"
|
|
},
|
|
{
|
|
"name": "BMC_IPXCONNECTIVITYNETWORK",
|
|
"label": "IPX Connectivity Network"
|
|
},
|
|
{
|
|
"name": "BMC_LNSGROUP",
|
|
"label": "LNs Collection"
|
|
},
|
|
{
|
|
"name": "BMC_NETWORKPORT",
|
|
"label": "Network Port"
|
|
},
|
|
{
|
|
"name": "BMC_LAN",
|
|
"label": "Local Area Network (LAN)"
|
|
},
|
|
{
|
|
"name": "BMC_WAN",
|
|
"label": "Wide Area Network (WAN)"
|
|
},
|
|
{
|
|
"name": "BMC_COMMUNICATIONENDPOINT",
|
|
"label": "Communication Endpoint"
|
|
},
|
|
{
|
|
"name": "BMC_IPENDPOINT",
|
|
"label": "IP Endpoint"
|
|
},
|
|
{
|
|
"name": "BMC_LANENDPOINT",
|
|
"label": "LAN Endpoint"
|
|
},
|
|
{
|
|
"name": "BMC_ADMINDOMAIN",
|
|
"label": "Admin Domain"
|
|
},
|
|
{
|
|
"name": "BMC_CLUSTER",
|
|
"label": "Cluster"
|
|
},
|
|
{
|
|
"name": "BMC_BUSINESSSERVICE",
|
|
"label": "Business Service"
|
|
},
|
|
{
|
|
"name": "BMC_APPLICATION",
|
|
"label": "Application"
|
|
},
|
|
{
|
|
"name": "BMC_OPERATINGSYSTEM",
|
|
"label": "Operating System"
|
|
},
|
|
{
|
|
"name": "BMC_APPLICATIONINFRASTRUCTURE",
|
|
"label": "Application Infrastructure"
|
|
},
|
|
{
|
|
"name": "BMC_DATABASE",
|
|
"label": "Database"
|
|
},
|
|
{
|
|
"name": "BMC_DISKPARTITION",
|
|
"label": "Disk Partition"
|
|
},
|
|
{
|
|
"name": "BMC_FILESYSTEM",
|
|
"label": "File System"
|
|
},
|
|
{
|
|
"name": "BMC_SHARE",
|
|
"label": "Share"
|
|
},
|
|
{
|
|
"name": "BMC.CORE:BMC_RASD",
|
|
"label": "Resource Allocation Setting Data"
|
|
},
|
|
{
|
|
"name": "BMC.CORE:BMC_VIRTUALSYSTEMSETTINGDATA",
|
|
"label": "Virtual System Setting Data"
|
|
},
|
|
{
|
|
"name": "BMC_PATCH",
|
|
"label": "Patch"
|
|
},
|
|
{
|
|
"name": "BMC_PRODUCT",
|
|
"label": "Product"
|
|
},
|
|
{
|
|
"name": "BMC_APPLICATIONSYSTEM",
|
|
"label": "Application System"
|
|
},
|
|
{
|
|
"name": "BMC_APPLICATIONSERVICE",
|
|
"label": "Application Service"
|
|
},
|
|
{
|
|
"name": "BMC_BIOS",
|
|
"label": "BIOS Element"
|
|
},
|
|
{
|
|
"name": "BMC_SOFTWARESERVER",
|
|
"label": "Software Server"
|
|
},
|
|
{
|
|
"name": "BMC_SYSTEMSOFTWARE",
|
|
"label": "System Software"
|
|
},
|
|
{
|
|
"name": "BMC_VIRTUALSYSTEMENABLER",
|
|
"label": "Virtual System Enabler"
|
|
},
|
|
{
|
|
"name": "BMC_PACKAGE",
|
|
"label": "Package"
|
|
},
|
|
{
|
|
"name": "BMC_DATABASESTORAGE",
|
|
"label": "Database Storage"
|
|
},
|
|
{
|
|
"name": "BMC_LOCALFILESYSTEM",
|
|
"label": "Local File System"
|
|
},
|
|
{
|
|
"name": "BMC_REMOTEFILESYSTEM",
|
|
"label": "Remote File System"
|
|
},
|
|
{
|
|
"name": "BMC_CARD",
|
|
"label": "Card"
|
|
},
|
|
{
|
|
"name": "BMC_CHASSIS",
|
|
"label": "Chassis"
|
|
},
|
|
{
|
|
"name": "BMC_RACK",
|
|
"label": "Rack"
|
|
},
|
|
{
|
|
"name": "BMC_HARDWAREPACKAGE",
|
|
"label": "Hardware Package"
|
|
},
|
|
{
|
|
"name": "BMC_KEYBOARD",
|
|
"label": "Keyboard"
|
|
},
|
|
{
|
|
"name": "BMC_MEDIA",
|
|
"label": "Media"
|
|
},
|
|
{
|
|
"name": "BMC_MEMORY",
|
|
"label": "Memory"
|
|
},
|
|
{
|
|
"name": "BMC_MONITOR",
|
|
"label": "Monitor"
|
|
},
|
|
{
|
|
"name": "BMC_POINTINGDEVICE",
|
|
"label": "Pointing Device"
|
|
},
|
|
{
|
|
"name": "BMC_PROCESSOR",
|
|
"label": "Processor"
|
|
},
|
|
{
|
|
"name": "BMC_UPS",
|
|
"label": "UPS"
|
|
},
|
|
{
|
|
"name": "BMC_SYSTEMRESOURCE",
|
|
"label": "System Resource"
|
|
},
|
|
{
|
|
"name": "BMC.CORE:BMC_RESOURCEPOOL",
|
|
"label": "Resource Pool"
|
|
},
|
|
{
|
|
"name": "BMC_CDROMDRIVE",
|
|
"label": "CDROM Drive"
|
|
},
|
|
{
|
|
"name": "BMC_DISKDRIVE",
|
|
"label": "Disk Drive"
|
|
},
|
|
{
|
|
"name": "BMC_FLOPPYDRIVE",
|
|
"label": "Floppy Drive"
|
|
},
|
|
{
|
|
"name": "BMC_TAPEDRIVE",
|
|
"label": "Tape Drive"
|
|
},
|
|
{
|
|
"name": "BMC_HARDWARESYSTEMCOMPONENT",
|
|
"label": "Hardware System Component"
|
|
},
|
|
{
|
|
"name": "BMC.CORE:BMC_BUSINESSPROCESS",
|
|
"label": "Business Process"
|
|
},
|
|
{
|
|
"name": "BMC_TRANSACTION",
|
|
"label": "Transaction"
|
|
},
|
|
{
|
|
"name": "BMC_DOCUMENT",
|
|
"label": "Document"
|
|
},
|
|
{
|
|
"name": "BMC_ACCOUNT",
|
|
"label": "Account"
|
|
},
|
|
{
|
|
"name": "BMC_ACTIVITY",
|
|
"label": "Activity"
|
|
},
|
|
{
|
|
"name": "BMC_PHYSICALLOCATION",
|
|
"label": "Physical Location"
|
|
},
|
|
{
|
|
"name": "BMC_ROLE",
|
|
"label": "Role"
|
|
},
|
|
{
|
|
"name": "BMC.CORE:BMC_CONCRETECOLLECTION",
|
|
"label": "Concrete Collection"
|
|
},
|
|
{
|
|
"name": "BMC_LOGICALSYSTEMCOMPONENT",
|
|
"label": "Logical System Component"
|
|
},
|
|
{
|
|
"name": "BMC_SERVICEOFFERINGINSTANCE",
|
|
"label": "Service Offering Instance"
|
|
}
|
|
];
|
|
var graphPan = element.find('.pan-area'), initialZoom = 1.5, minimumZoom = 0.1, zoomStep = 0.2, tappedBeforeNode = null, selectedNode = null, edgeCache = [], displayCiLimit = 100, removedUpstreamEdges = null, modalInstance;
|
|
scope.state = {};
|
|
scope.model = ciExplorerModel;
|
|
ciExplorerModel.reset(true);
|
|
scope.$watch('rootCi', function (rootCi) {
|
|
if (!rootCi || !getInstanceId(rootCi) || scope.initialized)
|
|
return;
|
|
var cy = scope.cy = cytoscape({
|
|
container: graphPan[0],
|
|
style: generateGraphStyles(),
|
|
elements: {
|
|
nodes: [buildNode(rootCi)]
|
|
},
|
|
layout: {
|
|
name: 'dagre',
|
|
fit: false
|
|
},
|
|
boxSelectionEnabled: false,
|
|
wheelSensitivity: 0.2,
|
|
selectionType: 'single',
|
|
zoom: initialZoom,
|
|
ready: function () {
|
|
$timeout(function () {
|
|
cy.center();
|
|
});
|
|
}
|
|
});
|
|
scope.initialized = true;
|
|
cy.on('tap', function (event) {
|
|
var tappedNowNode = event.cyTarget;
|
|
$timeout(function () { tappedBeforeNode = null; }, 300);
|
|
if (tappedBeforeNode === tappedNowNode) {
|
|
tappedNowNode.trigger('doubleTap');
|
|
tappedBeforeNode = null;
|
|
}
|
|
else {
|
|
tappedBeforeNode = tappedNowNode;
|
|
}
|
|
});
|
|
cy.on('doubleTap', function (event) {
|
|
toggleNode(event.cyTarget);
|
|
});
|
|
cy.on('select', 'node', function (event) {
|
|
var node = event.cyTarget;
|
|
if (!isGroupNode(node) && !isLargeNode(node)) {
|
|
var icon = node.data('icon');
|
|
node.removeClass(icon);
|
|
node.addClass(getSelectedIcon(icon));
|
|
selectedNode = node;
|
|
}
|
|
});
|
|
cy.on('unselect', 'node', function (event) {
|
|
var node = event.cyTarget;
|
|
if (!isGroupNode(node) && !isLargeNode(node)) {
|
|
var icon = node.data('icon');
|
|
node.removeClass(getSelectedIcon(icon));
|
|
node.addClass(icon);
|
|
selectedNode = null;
|
|
}
|
|
});
|
|
cy.on('mouseover', 'node', function (event) {
|
|
var node = event.cyTarget;
|
|
node.data('hover', true);
|
|
});
|
|
cy.on('mouseout', 'node', function (event) {
|
|
var node = event.cyTarget;
|
|
node.data('hover', false);
|
|
});
|
|
});
|
|
scope.openAsset = function (asset) {
|
|
$state.go('asset', {
|
|
assetId: asset.reconciliationId,
|
|
assetClassId: asset.classId
|
|
});
|
|
};
|
|
scope.changeZoomLevel = function (zoomType) {
|
|
var currentZoom = scope.cy.zoom();
|
|
if (zoomType === 'in') {
|
|
currentZoom += zoomStep;
|
|
}
|
|
else if (zoomType === 'out') {
|
|
currentZoom -= zoomStep;
|
|
}
|
|
currentZoom = Math.max(minimumZoom, currentZoom);
|
|
scope.cy.zoom(currentZoom);
|
|
scope.cy.center(getVisibleElements());
|
|
};
|
|
scope.resetCanvas = function () {
|
|
layout();
|
|
};
|
|
scope.enableBoxSelection = function () {
|
|
scope.cy.boxSelectionEnabled(true);
|
|
};
|
|
scope.viewParents = function () {
|
|
if (!scope.rootCi.parentsLoaded) {
|
|
loadParents(scope.rootCi);
|
|
}
|
|
else if (scope.rootCi.parentsShown) {
|
|
hideParents();
|
|
}
|
|
else {
|
|
showParents();
|
|
}
|
|
};
|
|
scope.expandAll = function () {
|
|
var nodes = filterNodes(scope.cy.nodes());
|
|
setExpanded(nodes, true);
|
|
nodes.show();
|
|
showParents();
|
|
filterGroupNodes(scope.cy.nodes()).hide();
|
|
layout();
|
|
};
|
|
scope.collapseAll = function () {
|
|
filterNodes(scope.cy.nodes()).hide();
|
|
filterGroupNodes(scope.cy.nodes()).show();
|
|
getNodeByCi(scope.rootCi).show();
|
|
hideParents();
|
|
layout();
|
|
};
|
|
scope.previewSelected = function () {
|
|
if (!selectedNode)
|
|
return;
|
|
modalInstance = $modal.open({
|
|
templateUrl: 'views/change/ci-relation-preview.html',
|
|
windowClass: 'action-blade',
|
|
size: 'lg',
|
|
controller: ['$scope', function ($scope) {
|
|
$scope.assetIdsObject = buildAssetIdObject(selectedNode.data('ci'));
|
|
}]
|
|
});
|
|
};
|
|
scope.$on('$stateChangeStart', function () {
|
|
if (modalInstance) {
|
|
modalInstance.dismiss();
|
|
}
|
|
});
|
|
scope.$on('$destroy', function () {
|
|
console.log('graphicalCi: unbind events');
|
|
scope.cy.removeListener('tap');
|
|
scope.cy.removeListener('doubletap');
|
|
scope.cy.removeListener('select');
|
|
scope.cy.removeListener('unselect');
|
|
scope.cy.removeListener('mouseover');
|
|
scope.cy.removeListener('mouseout');
|
|
});
|
|
scope.hardReset = function () {
|
|
scope.rootCi.relationsLoaded = false;
|
|
scope.rootCi.parentsLoaded = false;
|
|
scope.rootCi.parentsShown = false;
|
|
ciExplorerModel.reset();
|
|
removeAllElements();
|
|
addRootNode();
|
|
};
|
|
scope.reloadAllRelationships = function () {
|
|
if (!scope.cy)
|
|
return;
|
|
var relationsLoaded = scope.rootCi.relationsLoaded, parentsLoaded = scope.rootCi.parentsLoaded, assets = getAssetsByLevel();
|
|
scope.hardReset();
|
|
scope.rootCi.relationsLoaded = relationsLoaded;
|
|
if (parentsLoaded) {
|
|
loadParents(scope.rootCi).then(function () {
|
|
reloadRelations(assets);
|
|
});
|
|
}
|
|
else {
|
|
reloadRelations(assets);
|
|
}
|
|
};
|
|
function getAssetsByLevel() {
|
|
var nodesByLevel = getNodesByLevel(), assets = [];
|
|
_.each(nodesByLevel, function (level) {
|
|
_.each(level.nodes, function (node) {
|
|
var asset = node.data('ci');
|
|
if (asset) {
|
|
assets.push(asset);
|
|
}
|
|
});
|
|
});
|
|
return assets;
|
|
}
|
|
function reloadRelations(assets) {
|
|
var asset;
|
|
while (asset = assets.shift()) {
|
|
var node = getNodeByCi(asset);
|
|
if (node.length > 0 && asset.relationsLoaded) {
|
|
asset.relationsLoaded = false;
|
|
node.data('ci', asset);
|
|
loadRelations(asset).then(function () {
|
|
reloadRelations(assets);
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
function toggleNode(node) {
|
|
if (isParentNode(node)) {
|
|
return;
|
|
}
|
|
else if (isGroupNode(node)) {
|
|
expandGroupNode(node);
|
|
}
|
|
else if (isLargeNode(node)) {
|
|
expandLargeNode(node);
|
|
}
|
|
else {
|
|
var localRootCi = node.data('ci'), visibleOutgoerNodes = filterVisibleOutgoerNodes(node);
|
|
if (isGroupNode(visibleOutgoerNodes)) {
|
|
expandGroupNode(visibleOutgoerNodes);
|
|
localRootCi.expanded = true;
|
|
}
|
|
else {
|
|
if (!localRootCi.relationsLoaded) {
|
|
loadRelations(localRootCi);
|
|
return;
|
|
}
|
|
if (localRootCi.expanded) {
|
|
hideRelations(localRootCi);
|
|
}
|
|
else {
|
|
showRelations(localRootCi);
|
|
}
|
|
layout(localRootCi);
|
|
localRootCi.expanded = !localRootCi.expanded;
|
|
}
|
|
}
|
|
}
|
|
function expandGroupNode(node) {
|
|
node.hide();
|
|
var nodes = node.data('nodes');
|
|
setExpanded(nodes, true);
|
|
nodes.show();
|
|
layout();
|
|
}
|
|
function expandLargeNode(node) {
|
|
var totalCount = node.data('totalCount');
|
|
if (totalCount > displayCiLimit) {
|
|
displayLargeNodeAlert();
|
|
}
|
|
else if (totalCount === 0) {
|
|
node.remove();
|
|
}
|
|
}
|
|
function displayLargeNodeAlert() {
|
|
systemAlertService.modal({
|
|
title: i18nService.getLocalizedString('common.notification.asset.explorer.title'),
|
|
text: i18nService.getLocalizedString('common.notification.asset.explorer.largeNode.message'),
|
|
buttons: [{ text: i18nService.getLocalizedString('common.labels.ok') }]
|
|
});
|
|
}
|
|
function addRootNode() {
|
|
scope.cy.add([buildNode(scope.rootCi)]);
|
|
layout(scope.rootCi);
|
|
}
|
|
function loadRelations(localRootCi) {
|
|
return ciExplorerModel.displayRelations(localRootCi).then(function (result) {
|
|
localRootCi.relationsLoaded = true;
|
|
var displayedCis = _.where(result.relatedCis, {
|
|
realObject: {
|
|
isChild: true
|
|
}
|
|
}), totalCount = result.totalCount - (result.relatedCis.length - displayedCis.length);
|
|
localRootCi.expanded = true;
|
|
var nodes = [], edges = [], largeNode = getNodeById(getLargeNodeId(localRootCi)), removeLargeNode = largeNode.length === 0 ? true : totalCount !== 0;
|
|
if (totalCount <= displayCiLimit && removeLargeNode) {
|
|
largeNode.remove();
|
|
_.each(displayedCis, function (ci) {
|
|
nodes.push(buildNode(ci));
|
|
var edge = buildEdgeByCi(localRootCi, ci);
|
|
if (edge) {
|
|
edges.push(edge);
|
|
}
|
|
if (isParentAndChild(ci)) {
|
|
edge = buildEdgeByCi(ci, localRootCi, true);
|
|
if (edge) {
|
|
edges.push(edge);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
if (largeNode.length === 0) {
|
|
largeNode = scope.cy.add(buildLargeNode(localRootCi, totalCount));
|
|
}
|
|
largeNode.data('label', getGroupNodeTitle(totalCount));
|
|
largeNode.data('totalCount', totalCount);
|
|
var edge = buildEdgeByNode(getNodeByCi(localRootCi), largeNode);
|
|
if (edge) {
|
|
edges.push(edge);
|
|
}
|
|
}
|
|
scope.cy.add(nodes);
|
|
scope.cy.add(edges);
|
|
updateGroupNodes();
|
|
layout(localRootCi);
|
|
});
|
|
}
|
|
function loadParents(localRootCi) {
|
|
return ciExplorerModel.displayRelations(localRootCi).then(function (result) {
|
|
localRootCi.parentsLoaded = true;
|
|
var parents = _.where(result.relatedCis, {
|
|
realObject: {
|
|
isParent: true
|
|
}
|
|
});
|
|
var nodes = [], edges = [];
|
|
_.each(parents, function (parent) {
|
|
nodes.push(buildParentNode(parent));
|
|
var edge = buildEdgeByCi(parent, localRootCi, true);
|
|
if (edge) {
|
|
edges.push(edge);
|
|
}
|
|
});
|
|
scope.cy.add(nodes);
|
|
scope.cy.add(edges);
|
|
updateGroupNodes();
|
|
parentsShown(true);
|
|
layout(localRootCi);
|
|
});
|
|
}
|
|
function hideParents() {
|
|
filterParentNodes(scope.cy.nodes().roots()).hide();
|
|
parentsShown(false);
|
|
layout();
|
|
}
|
|
function showParents() {
|
|
filterParentNodes(scope.cy.nodes().roots()).show();
|
|
parentsShown(true);
|
|
layout();
|
|
}
|
|
function parentsShown(value) {
|
|
if (scope.rootCi.parentsLoaded) {
|
|
scope.rootCi.parentsShown = value;
|
|
}
|
|
}
|
|
function updateGroupNodes() {
|
|
var nodesByLevel = getNodesByLevel();
|
|
if (nodesByLevel.length <= 1) {
|
|
return;
|
|
}
|
|
var setNodeCount = function (largeNode) {
|
|
totalNodeCount += largeNode.data('totalCount');
|
|
};
|
|
for (var level = 1; level < nodesByLevel.length; level++) {
|
|
var nodes = nodesByLevel[level].nodes;
|
|
var groupNodes = nodesByLevel[level].groupNodes;
|
|
if (groupNodes.length === 0) {
|
|
groupNodes = scope.cy.add(buildGroupNode(level, nodes.length));
|
|
groupNodes.hide();
|
|
}
|
|
var largeNodes = filterLargeNodes(nodes), totalNodeCount = nodes.length - largeNodes.length;
|
|
_.each(largeNodes, setNodeCount);
|
|
groupNodes.data('label', getGroupNodeTitle(totalNodeCount));
|
|
groupNodes.data('nodes', nodes);
|
|
connectNodes(nodesByLevel[level - 1].allNodes, groupNodes);
|
|
connectNodes(nodesByLevel[level - 1].groupNodes, nodes);
|
|
}
|
|
}
|
|
function getNodesByLevel() {
|
|
removeUpstreamEdges();
|
|
var i = 1, nodes = [], visitedNodes = {}, currentLevel = getNodeByCi(scope.rootCi);
|
|
var setNodes = function (node) {
|
|
var nodeId = node.data('id');
|
|
node.data('level', i);
|
|
if (!visitedNodes[nodeId]) {
|
|
currentLevelUnvisited[nodeId] = node;
|
|
visitedNodes[nodeId] = node;
|
|
}
|
|
};
|
|
var getCurentLevelUnvisitedNodes = function (node) {
|
|
var nodeId = node.data('id');
|
|
return !!currentLevelUnvisited[nodeId];
|
|
};
|
|
while (currentLevel.length != 0) {
|
|
var currentLevelUnvisited = {};
|
|
_.each(currentLevel, setNodes);
|
|
currentLevelUnvisited = currentLevel.filterFn(getCurentLevelUnvisitedNodes);
|
|
if (currentLevelUnvisited.length > 0) {
|
|
nodes.push({
|
|
allNodes: currentLevelUnvisited,
|
|
nodes: filterNodes(currentLevelUnvisited),
|
|
groupNodes: filterGroupNodes(currentLevelUnvisited)
|
|
});
|
|
}
|
|
currentLevel = filterAllNodes(currentLevelUnvisited.outgoers());
|
|
i++;
|
|
}
|
|
restoreUpstreamEdges();
|
|
return nodes;
|
|
}
|
|
function getVisibleElements() {
|
|
return scope.cy.elements().filter(':visible');
|
|
}
|
|
function filterVisibleElements(elements) {
|
|
return elements.filter(':visible');
|
|
}
|
|
function filterVisibleOutgoerNodes(node) {
|
|
return filterVisibleElements(node.outgoers().filter('node'));
|
|
}
|
|
function filterAllNodes(nodes) {
|
|
return nodes.filter('node');
|
|
}
|
|
function filterNodes(nodes) {
|
|
return nodes.filter('node').filterFn(function (ele) {
|
|
return !isGroupNode(ele);
|
|
});
|
|
}
|
|
function filterGroupNodes(nodes) {
|
|
return nodes.filter('node').filterFn(function (ele) {
|
|
return isGroupNode(ele);
|
|
});
|
|
}
|
|
function isGroupNode(element) {
|
|
return element.hasClass("group-node");
|
|
}
|
|
function filterLargeNodes(nodes) {
|
|
return nodes.filter('node').filterFn(function (ele) {
|
|
return isLargeNode(ele);
|
|
});
|
|
}
|
|
function isLargeNode(element) {
|
|
return element.hasClass("large-node");
|
|
}
|
|
function connectNodes(sourceNodes, targetNodes) {
|
|
_.each(sourceNodes, function (sourceNode) {
|
|
_.each(targetNodes, function (targetNode) {
|
|
var edge = buildEdgeByNode(sourceNode, targetNode);
|
|
if (edge) {
|
|
scope.cy.add(edge);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
function showRelations(localRootCi) {
|
|
removeUpstreamEdges();
|
|
var node = getNodeByCi(localRootCi);
|
|
filterNodes(node.outgoers()).show();
|
|
restoreUpstreamEdges();
|
|
}
|
|
function hideRelations(localRootCi) {
|
|
removeUpstreamEdges();
|
|
var node = getNodeByCi(localRootCi);
|
|
setExpanded(filterNodes(node.successors()), false);
|
|
filterAllNodes(node.successors()).hide();
|
|
restoreUpstreamEdges();
|
|
}
|
|
function setExpanded(nodes, expanded) {
|
|
_.each(nodes, function (node) {
|
|
node.data('ci').expanded = expanded;
|
|
});
|
|
}
|
|
function removeAllElements() {
|
|
scope.cy.elements().remove();
|
|
edgeCache = [];
|
|
}
|
|
function layout(localRootCi) {
|
|
var visibleElements = getVisibleElements();
|
|
visibleElements.layout({
|
|
name: 'dagre',
|
|
fit: false,
|
|
ready: function () {
|
|
$timeout(function () {
|
|
if (localRootCi) {
|
|
var centerNode = getNodeByCi(localRootCi);
|
|
scope.cy.center(centerNode);
|
|
}
|
|
else {
|
|
scope.cy.fit(visibleElements);
|
|
if (scope.cy.zoom() > initialZoom) {
|
|
scope.cy.zoom(initialZoom);
|
|
}
|
|
scope.cy.center(visibleElements);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
function getNodeByCi(ci) {
|
|
return getNodeById(getInstanceId(ci));
|
|
}
|
|
function getNodeById(nodeId) {
|
|
return scope.cy.$("#" + nodeId);
|
|
}
|
|
function buildNode(ci) {
|
|
var icon = getIcon(ci);
|
|
return {
|
|
group: 'nodes',
|
|
data: {
|
|
id: getInstanceId(ci),
|
|
ci: ci,
|
|
label: getName(ci),
|
|
shortLabel: getShortName(ci),
|
|
icon: icon
|
|
},
|
|
classes: icon
|
|
};
|
|
}
|
|
function buildParentNode(ci) {
|
|
var node = buildNode(ci);
|
|
node.data.isParent = true;
|
|
return node;
|
|
}
|
|
function filterParentNodes(nodes) {
|
|
return nodes.filter('node').filterFn(function (ele) {
|
|
return isParentNode(ele);
|
|
});
|
|
}
|
|
function isParentNode(element) {
|
|
return element.data("isParent") && element.incomers().length === 0;
|
|
}
|
|
function isParentAndChild(asset) {
|
|
return asset.realObject ? asset.realObject.isParent && asset.realObject.isChild : false;
|
|
}
|
|
function buildLargeNode(parentCi, nodeCount) {
|
|
return {
|
|
group: 'nodes',
|
|
data: {
|
|
id: getLargeNodeId(parentCi),
|
|
ci: {},
|
|
parentCi: parentCi,
|
|
label: getGroupNodeTitle(nodeCount),
|
|
totalCount: nodeCount
|
|
},
|
|
classes: 'large-node collapsed-node'
|
|
};
|
|
}
|
|
function buildGroupNode(level, nodeCount) {
|
|
return {
|
|
group: 'nodes',
|
|
data: {
|
|
id: getGroupNodeId(level),
|
|
label: getGroupNodeTitle(nodeCount)
|
|
},
|
|
classes: "group-node collapsed-node"
|
|
};
|
|
}
|
|
function getGroupNodeId(level) {
|
|
return "groupNode__" + level;
|
|
}
|
|
function getLargeNodeId(ci) {
|
|
return getInstanceId(ci) + '_large';
|
|
}
|
|
function getGroupNodeTitle(nodeCount) {
|
|
return $filter('i18n')('asset.explorer.relatives.count', nodeCount);
|
|
}
|
|
function buildEdgeById(sourceId, targetId, isUpstream) {
|
|
var edgeId = sourceId + targetId;
|
|
if (edgeCache[edgeId]) {
|
|
return null;
|
|
}
|
|
var maxInteger = 2147483647, sourceNode = getNodeById(sourceId), targetNode = getNodeById(targetId), sourceLevel = sourceNode.data('level') || maxInteger, targetLevel = targetNode.data('level') || maxInteger;
|
|
isUpstream = !!isUpstream;
|
|
if (sourceLevel > targetLevel) {
|
|
isUpstream = true;
|
|
}
|
|
var edge = {
|
|
group: "edges",
|
|
data: {
|
|
source: sourceId,
|
|
target: targetId,
|
|
isUpstream: isUpstream
|
|
}
|
|
};
|
|
edgeCache[edgeId] = edge;
|
|
return edge;
|
|
}
|
|
function buildEdgeByCi(sourceCi, targetCi, isUpstream) {
|
|
return buildEdgeById(getInstanceId(sourceCi), getInstanceId(targetCi), isUpstream);
|
|
}
|
|
function buildEdgeByNode(sourceNode, targetNode, isUpstream) {
|
|
return buildEdgeById(sourceNode.data('id'), targetNode.data('id'), isUpstream);
|
|
}
|
|
function buildAssetIdObject(ci) {
|
|
return {
|
|
assetId: ci.reconciliationId || ci.realObject.reconciliationId,
|
|
assetClassId: ci.classId || ci.realObject.classId
|
|
};
|
|
}
|
|
function getInstanceId(ci) {
|
|
return ci.instanceId || (ci.realObject && ci.realObject.instanceId);
|
|
}
|
|
function getIcon(ci) {
|
|
var subtype = iconSubtype(ci.classId);
|
|
if (subtype) {
|
|
return subtype.toLowerCase().replace(' ', '');
|
|
}
|
|
else {
|
|
var defaultAssetType = "other", type = ci.assetType || (ci.realObject && ci.realObject.assetType) || defaultAssetType;
|
|
return type.toLowerCase().replace(' ', '');
|
|
}
|
|
}
|
|
function iconSubtype(type) {
|
|
for (var i = 0; i < iconList.length; i++) {
|
|
if (iconList[i].name === type) {
|
|
return iconList[i].label;
|
|
}
|
|
}
|
|
}
|
|
function getSelectedIcon(icon) {
|
|
return icon + "-selected selected";
|
|
}
|
|
function getName(ci) {
|
|
return scope.model.getAssetName(ci) + getNameSuffix(ci);
|
|
}
|
|
function getShortName(ci) {
|
|
return scope.model.getAssetDisplayName(ci) + getNameSuffix(ci);
|
|
}
|
|
function getNameSuffix(ci) {
|
|
return scope.rootCi === ci ? ' [' + $filter('i18n')('asset.explorer.root') + ']' : '';
|
|
}
|
|
function removeUpstreamEdges() {
|
|
if (removedUpstreamEdges)
|
|
return;
|
|
removedUpstreamEdges = scope.cy.edges('edge[?isUpstream]');
|
|
removedUpstreamEdges.remove();
|
|
}
|
|
function restoreUpstreamEdges() {
|
|
if (!removedUpstreamEdges)
|
|
return;
|
|
removedUpstreamEdges.restore();
|
|
removedUpstreamEdges = null;
|
|
}
|
|
function generateGraphStyles() {
|
|
var styleChain = cytoscape.stylesheet()
|
|
.selector('node[?hover]')
|
|
.css({
|
|
'content': 'data(label)'
|
|
})
|
|
.selector('node[!hover]')
|
|
.css({
|
|
'content': 'data(shortLabel)'
|
|
})
|
|
.selector('node')
|
|
.css({
|
|
'background-fit': "cover",
|
|
'font-size': 8,
|
|
'shape': 'rectangle',
|
|
'background-opacity': 0,
|
|
'text-valign': 'bottom',
|
|
'text-wrap': 'wrap',
|
|
'text-max-width': 80
|
|
})
|
|
.selector('node.selected')
|
|
.css({
|
|
'background-fit': "cover",
|
|
'font-size': 8,
|
|
'shape': 'rectangle',
|
|
'background-opacity': 0,
|
|
'text-valign': 'bottom'
|
|
})
|
|
.selector('.big-node')
|
|
.css({
|
|
width: 35,
|
|
height: 35
|
|
})
|
|
.selector('.small-node')
|
|
.css({
|
|
'height': 20,
|
|
'width': 20,
|
|
'background-fit': 'cover',
|
|
'content': 'data(label)',
|
|
'font-size': 5,
|
|
'background-opacity': 0,
|
|
'text-valign': 'bottom'
|
|
})
|
|
.selector('edge')
|
|
.css({
|
|
'width': 0.3,
|
|
'line-color': '#666666',
|
|
'target-arrow-shape': 'triangle'
|
|
})
|
|
.selector('.group-node')
|
|
.css({
|
|
'shape': 'roundrectangle'
|
|
})
|
|
.selector('.collapsed-node')
|
|
.css({
|
|
'content': 'data(label)',
|
|
'color': '#2bb5dc',
|
|
'background-color': '#2bb5dc',
|
|
'background-opacity': 0.5,
|
|
'background-image': 'none',
|
|
'border-width': 0.2,
|
|
'font-size': 10,
|
|
'text-valign': 'center',
|
|
'word-wrap': 'break-word',
|
|
'height': 40,
|
|
'width': 100
|
|
})
|
|
.selector('.expanded-node')
|
|
.css({
|
|
'content': '',
|
|
'background-color': '#2bb5dc',
|
|
'background-opacity': 0.2,
|
|
'background-image': 'none',
|
|
'border-width': 0.2
|
|
})
|
|
.selector('.large-node')
|
|
.css({
|
|
'shape': 'roundrectangle',
|
|
'background-color': '#89c341'
|
|
})
|
|
.selector('.hidden-node')
|
|
.css({
|
|
'visibility': 'hidden'
|
|
})
|
|
.selector('.expand-button')
|
|
.css({
|
|
'height': '30px',
|
|
'width': '75px'
|
|
});
|
|
if (browser.isIE) {
|
|
styleChain
|
|
.selector('node')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/generic_ci.png'
|
|
})
|
|
.selector('node.selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/generic_ci_selected.png'
|
|
})
|
|
.selector('.businessservice')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/service.png'
|
|
})
|
|
.selector('.businessservice-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/service_selected.png'
|
|
})
|
|
.selector('.collapsed-node')
|
|
.css({
|
|
'background-image': 'none'
|
|
})
|
|
.selector('.expanded-node')
|
|
.css({
|
|
'background-image': 'none'
|
|
})
|
|
.selector('.application')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/application.png'
|
|
})
|
|
.selector('.application-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/application_selected.png'
|
|
})
|
|
.selector('.cluster')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/cluster.png'
|
|
})
|
|
.selector('.cluster-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/cluster_selected.png'
|
|
})
|
|
.selector('.computersystem')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/computer_system.png'
|
|
})
|
|
.selector('.computersystem-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/computer_system_selected.png'
|
|
})
|
|
.selector('.database')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/database.png'
|
|
})
|
|
.selector('.database-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/database_selected.png'
|
|
})
|
|
.selector('.filesystem')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/file_system.png'
|
|
})
|
|
.selector('.filesystem-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/file_system_selected.png'
|
|
})
|
|
.selector('.group')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/group.png'
|
|
})
|
|
.selector('.group-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/group_selected.png'
|
|
})
|
|
.selector('.media')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/media.png'
|
|
})
|
|
.selector('.media-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/media_selected.png'
|
|
})
|
|
.selector('.network')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/network.png'
|
|
})
|
|
.selector('.network-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/network_selected.png'
|
|
})
|
|
.selector('.people')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/people.png'
|
|
})
|
|
.selector('.people-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/people_selected.png'
|
|
})
|
|
.selector('.resource')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/resource.png'
|
|
})
|
|
.selector('.resource-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/resource_selected.png'
|
|
})
|
|
.selector('.service')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/service.png'
|
|
})
|
|
.selector('.service-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/service_selected.png'
|
|
})
|
|
.selector('.software')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/software.png'
|
|
})
|
|
.selector('.software-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/software_selected.png'
|
|
})
|
|
.selector('.ups')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/ups.png'
|
|
})
|
|
.selector('.ups-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/ups_selected.png'
|
|
})
|
|
.selector('.collapsed-node')
|
|
.css({
|
|
'background-image': 'none'
|
|
});
|
|
}
|
|
else {
|
|
styleChain
|
|
.selector('node')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/generic_ci.svg'
|
|
})
|
|
.selector('node.selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/generic_ci_selected.svg'
|
|
})
|
|
.selector('.businessservice')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/service.png'
|
|
})
|
|
.selector('.businessservice-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/service_selected.png'
|
|
})
|
|
.selector('.collapsed-node')
|
|
.css({
|
|
'background-image': 'none'
|
|
})
|
|
.selector('.expanded-node')
|
|
.css({
|
|
'background-image': 'none'
|
|
})
|
|
.selector('.application')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/application.svg'
|
|
})
|
|
.selector('.application-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/application_selected.svg'
|
|
})
|
|
.selector('.cluster')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/cluster.svg'
|
|
})
|
|
.selector('.cluster-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/cluster_selected.svg'
|
|
})
|
|
.selector('.computersystem')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/computer_system.svg'
|
|
})
|
|
.selector('.computersystem-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/computer_system_selected.svg'
|
|
})
|
|
.selector('.database')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/database.svg'
|
|
})
|
|
.selector('.database-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/database_selected.svg'
|
|
})
|
|
.selector('.filesystem')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/file_system.svg'
|
|
})
|
|
.selector('.filesystem-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/file_system_selected.svg'
|
|
})
|
|
.selector('.group')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/group.svg'
|
|
})
|
|
.selector('.group-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/group_selected.svg'
|
|
})
|
|
.selector('.media')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/media.svg'
|
|
})
|
|
.selector('.media-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/media_selected.svg'
|
|
})
|
|
.selector('.network')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/network.svg'
|
|
})
|
|
.selector('.network-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/network_selected.svg'
|
|
})
|
|
.selector('.people')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/people.svg'
|
|
})
|
|
.selector('.people-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/people_selected.svg'
|
|
})
|
|
.selector('.resource')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/resource.svg'
|
|
})
|
|
.selector('.resource-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/resource_selected.svg'
|
|
})
|
|
.selector('.service')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/service.svg'
|
|
})
|
|
.selector('.service-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/service_selected.svg'
|
|
})
|
|
.selector('.software')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/software.svg'
|
|
})
|
|
.selector('.software-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/software_selected.svg'
|
|
})
|
|
.selector('.ups')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/ups.svg'
|
|
})
|
|
.selector('.ups-selected')
|
|
.css({
|
|
'background-image': 'styles/img/ci-type-icons/ups_selected.svg'
|
|
});
|
|
}
|
|
return styleChain;
|
|
}
|
|
}
|
|
};
|
|
}]);
|
|
}());
|