@savantly/ngx-graphexp
Version:
Gremlin client [Tinkerpop] for an Angular app
1,360 lines (1,350 loc) • 97.2 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@savantly/gremlin-js'), require('rxjs/BehaviorSubject'), require('d3'), require('rxjs/Observable'), require('@angular/material'), require('@angular/common'), require('@angular/forms'), require('@angular/flex-layout')) :
typeof define === 'function' && define.amd ? define(['exports', '@angular/core', '@savantly/gremlin-js', 'rxjs/BehaviorSubject', 'd3', 'rxjs/Observable', '@angular/material', '@angular/common', '@angular/forms', '@angular/flex-layout'], factory) :
(factory((global.savantly = global.savantly || {}, global.savantly['ngx-graphexp'] = {}),global.ng.core,global.gremlinJs,global.Rx,global.d3,global.Rx,global.ng.material,global.ng.common,global.ng.forms,global.ng['flex-layout']));
}(this, (function (exports,core,gremlinJs,BehaviorSubject,d3,Observable,material,common,forms,flexLayout) { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed 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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
function __values(o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/** @enum {number} */
var GraphsonFormat = {
GraphSON1: 1,
GraphSON2: 2,
GraphSON3: 3,
};
GraphsonFormat[GraphsonFormat.GraphSON1] = "GraphSON1";
GraphsonFormat[GraphsonFormat.GraphSON2] = "GraphSON2";
GraphsonFormat[GraphsonFormat.GraphSON3] = "GraphSON3";
var KV = /** @class */ (function () {
function KV() {
}
return KV;
}());
var GraphexpService = /** @class */ (function () {
/**
* @param {?} options
*/
function GraphexpService(options) {
this.COMMUNICATION_METHOD = GraphsonFormat.GraphSON3;
this.graphInfoData = new BehaviorSubject.BehaviorSubject({});
this.nodeNames = new BehaviorSubject.BehaviorSubject([]);
this.nodeProperties = new BehaviorSubject.BehaviorSubject([]);
this.edgeProperties = new BehaviorSubject.BehaviorSubject([]);
this.node_limit_per_request = 50;
this.gremlinService = new gremlinJs.GremlinService(options);
}
/**
* @return {?}
*/
GraphexpService.prototype.queryGraphInfo = function () {
var _this = this;
var /** @type {?} */ gremlin_query_nodes = 'nodes = g.V().groupCount().by(label);';
var /** @type {?} */ gremlin_query_edges = 'edges = g.E().groupCount().by(label);';
var /** @type {?} */ gremlin_query_nodes_prop = 'nodesprop = g.V().valueMap().select(keys).groupCount();';
var /** @type {?} */ gremlin_query_edges_prop = 'edgesprop = g.E().valueMap().select(keys).groupCount();';
var /** @type {?} */ gremlinQuery = gremlin_query_nodes + gremlin_query_nodes_prop
+ gremlin_query_edges + gremlin_query_edges_prop
+ '[nodes.toList(),nodesprop.toList(),edges.toList(),edgesprop.toList()]';
this.executeQuery(gremlinQuery).then(function (response) {
_this.handleGraphInfo(response.data);
});
};
/**
* @param {?} field
* @param {?} value
* @return {?}
*/
GraphexpService.prototype.queryNodes = function (field, value) {
var _this = this;
var /** @type {?} */ input_string = value;
var /** @type {?} */ input_field = field;
var /** @type {?} */ filtered_string = input_string; // You may add .replace(/\W+/g, ''); to refuse any character not in the alphabet
if (filtered_string.length > 50) {
filtered_string = filtered_string.substring(0, 50); // limit string length
}
// Translate to Gremlin query
var /** @type {?} */ gremlin_query_nodes = null;
var /** @type {?} */ gremlin_query_edges = null;
var /** @type {?} */ gremlin_query = null;
if (input_string === '') {
gremlin_query_nodes = "nodes = g.V().limit(" + this.node_limit_per_request + ")";
gremlin_query_edges =
"edges = g.V().limit(" + this.node_limit_per_request + ").aggregate('node').outE().as('edge').inV().where(within('node')).select('edge')";
gremlin_query = gremlin_query_nodes + '\n' + gremlin_query_edges + '\n' + '[nodes.toList(),edges.toList()]';
}
else {
var /** @type {?} */ has_str = "has('" + input_field + "', '" + filtered_string + "')";
if (this.isInt(input_string)) {
has_str = "has('" + input_field + "', " + filtered_string + ")";
}
gremlin_query = 'g.V().' + has_str;
gremlin_query_nodes = 'nodes = g.V().' + has_str;
gremlin_query_edges = 'edges = g.V().' + has_str
+ ".aggregate('node').outE().as('edge').inV().where(within('node')).select('edge')";
gremlin_query = gremlin_query_nodes + '\n' + gremlin_query_edges + '\n' + '[nodes.toList(),edges.toList()]';
}
console.log(gremlin_query);
return new Promise(function (resolve, reject) {
_this.executeQuery(gremlin_query).then(function (response) {
resolve(_this.arrangeData(response.data));
}, function (error) { reject(error); });
});
};
/**
* @param {?} d
* @return {?}
*/
GraphexpService.prototype.getRelatedNodes = function (d) {
var _this = this;
var /** @type {?} */ id = d.id;
if (isNaN(id)) {
id = "'" + id + "'";
}
var /** @type {?} */ gremlin_query_nodes = "nodes = g.V(" + id + ").as('node').both().as('node').select(all,'node').inject(g.V(" + id + ")).unfold()";
var /** @type {?} */ gremlin_query_edges = "edges = g.V(" + id + ").bothE()";
var /** @type {?} */ gremlin_query = gremlin_query_nodes + "\n " + gremlin_query_edges + "\n[nodes.toList(),edges.toList()]";
return new Promise(function (resolve, reject) {
_this.executeQuery(gremlin_query).then(function (response) {
resolve(_this.arrangeData(response.data));
}, function (error) { reject(error); });
});
};
/**
* @param {?} label
* @param {?} properties
* @return {?}
*/
GraphexpService.prototype.createNode = function (label, properties) {
var _this = this;
var /** @type {?} */ promise = new Promise(function (resolve, reject) {
var /** @type {?} */ propString = '';
properties.forEach(function (kv) {
propString += ", '" + kv.key + "', '" + kv.value + "'";
});
var /** @type {?} */ gremlin = "vertex = graph.addVertex(label, '" + label + "'" + propString + ")";
console.log("executing query: " + gremlin);
_this.executeQuery(gremlin).then(function (response) {
resolve(response.data);
}, function (error) {
console.error(error);
reject(error);
});
});
return promise;
};
/**
* @param {?} item
* @return {?}
*/
GraphexpService.prototype.createLink = function (item) {
var _this = this;
var /** @type {?} */ properties = item.properties;
var /** @type {?} */ promise = new Promise(function (resolve, reject) {
var /** @type {?} */ gremlin = "edge = g.V(" + item.source + ").next().addEdge('" + item.label + "',g.V(" + item.target + ").next());";
console.log("executing query: " + gremlin);
_this.executeQuery(gremlin).then(function (response) {
resolve(response.data);
}, function (error) {
console.error(error);
reject(error);
});
});
return promise;
};
/**
* @param {?} gremlin
* @param {?=} bindings
* @return {?}
*/
GraphexpService.prototype.executeQuery = function (gremlin, bindings) {
var _this = this;
var /** @type {?} */ promise = new Promise(function (resolve, reject) {
var /** @type {?} */ query = _this.gremlinService.createQuery(gremlin, bindings);
query.onComplete = function (response) {
resolve(response);
};
_this.gremlinService.sendMessage(query);
});
return promise;
};
/**
* @param {?} data
* @return {?}
*/
GraphexpService.prototype.handleGraphInfo = function (data) {
if (this.COMMUNICATION_METHOD === GraphsonFormat.GraphSON3) {
data = this.graphson3to1(data);
}
var /** @type {?} */ nodeNames = [];
data[0].map(function (nameGroup) {
try {
for (var _a = __values(Object.keys(nameGroup)), _b = _a.next(); !_b.done; _b = _a.next()) {
var nameItem = _b.value;
nodeNames.push({ key: nameItem, value: nameGroup[nameItem] });
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
}
finally { if (e_1) throw e_1.error; }
}
var e_1, _c;
});
this.nodeNames.next(nodeNames);
this.graphInfoData.next(data);
this.nodeProperties.next(this.make_properties_list(data[1][0]));
this.edgeProperties.next(this.make_properties_list(data[3][0]));
};
/**
* @param {?} data
* @return {?}
*/
GraphexpService.prototype.graphson3to1 = function (data) {
// Convert data from graphSON v2 format to graphSON v1
if (!(Array.isArray(data) || ((typeof data === 'object') && (data !== null)))) {
return data;
}
if ('@type' in data) {
if (data['@type'] === 'g:List') {
data = data['@value'];
return this.graphson3to1(data);
}
else if (data['@type'] === 'g:Set') {
data = data['@value'];
return data;
}
else if (data['@type'] === 'g:Map') {
var /** @type {?} */ data_tmp = {};
for (var /** @type {?} */ i = 0; i < data['@value'].length; i += 2) {
var /** @type {?} */ data_key = data['@value'][i];
if ((typeof data_key === 'object') && (data_key !== null)) {
data_key = this.graphson3to1(data_key);
}
if (Array.isArray(data_key)) {
data_key = JSON.stringify(data_key).replace(/\'/g, ' ');
}
data_tmp[data_key] = this.graphson3to1(data['@value'][i + 1]);
}
data = data_tmp;
return data;
}
else {
data = data['@value'];
if ((typeof data === 'object') && (data !== null)) {
data = this.graphson3to1(data);
}
return data;
}
}
else if (Array.isArray(data) || ((typeof data === 'object') && (data !== null))) {
try {
for (var _a = __values(Object.keys(data)), _b = _a.next(); !_b.done; _b = _a.next()) {
var key = _b.value;
data[key] = this.graphson3to1(data[key]);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
}
finally { if (e_2) throw e_2.error; }
}
return data;
}
return data;
var e_2, _c;
};
/**
* @param {?} data
* @return {?}
*/
GraphexpService.prototype.arrangeData = function (data) {
if (this.COMMUNICATION_METHOD === GraphsonFormat.GraphSON3) {
data = this.graphson3to1(data);
return this.arrange_datav3(data);
}
else {
return this.arrange_datav2(data);
}
};
/**
* @param {?} data
* @return {?}
*/
GraphexpService.prototype.arrange_datav3 = function (data) {
var _this = this;
// Extract node and edges from the data returned for 'search' and 'click' request
// Create the graph object
var /** @type {?} */ nodes = [], /** @type {?} */ links = [];
try {
for (var _a = __values(Object.keys(data)), _b = _a.next(); !_b.done; _b = _a.next()) {
var key = _b.value;
data[key].forEach(function (item) {
if (!('inV' in item) && _this.idIndex(nodes, item.id) == null) {
// if vertex and not already in the list
item.type = 'vertex';
nodes.push(_this.extract_infov3(item));
}
if (('inV' in item) && _this.idIndex(links, item.id) == null) {
item.type = 'edge';
links.push(_this.extract_infov3(item));
}
});
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
}
finally { if (e_3) throw e_3.error; }
}
return { nodes: nodes, links: links };
var e_3, _c;
};
/**
* @param {?} data
* @return {?}
*/
GraphexpService.prototype.arrange_datav2 = function (data) {
// Extract node and edges from the data returned for 'search' and 'click' request
// Create the graph object
var /** @type {?} */ nodes = [], /** @type {?} */ links = [];
try {
for (var _a = __values(Object.keys(data)), _b = _a.next(); !_b.done; _b = _a.next()) {
var key = _b.value;
data[key].forEach(function (item) {
if (item.type === 'vertex' && this.idIndex(nodes, item.id) === null) {
// if vertex and not already in the list
nodes.push(this.extract_infov2(item));
}
if (item.type === 'edge' && this.idIndex(links, item.id) == null) {
links.push(this.extract_infov2(item));
}
});
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
}
finally { if (e_4) throw e_4.error; }
}
return { nodes: nodes, links: links };
var e_4, _c;
};
/**
* @param {?} data
* @return {?}
*/
GraphexpService.prototype.extract_infov2 = function (data) {
var /** @type {?} */ data_dic = { id: data.id, label: data.label, type: data.type, properties: {}, source: null, target: null };
var /** @type {?} */ prop_dic = data.properties;
for (var /** @type {?} */ key in prop_dic) {
if (prop_dic.hasOwnProperty(key)) {
data_dic.properties[key] = prop_dic[key];
}
}
if (data.type === 'edge') {
data_dic.source = data.outV;
data_dic.target = data.inV;
}
return data_dic;
};
/**
* @param {?} data
* @return {?}
*/
GraphexpService.prototype.extract_infov3 = function (data) {
var /** @type {?} */ data_dic = { id: data.id, label: data.label, type: data.type, properties: {}, source: null, target: null };
var /** @type {?} */ prop_dic = data.properties;
for (var /** @type {?} */ key in prop_dic) {
if (prop_dic.hasOwnProperty(key)) {
var /** @type {?} */ property = null;
if (data.type === 'vertex') {
// Extracting the Vertexproperties (properties of properties for vertices)
property = prop_dic[key];
property['summary'] = this.get_vertex_prop_in_list(prop_dic[key]).toString();
}
else {
property = prop_dic[key]['value'];
}
data_dic.properties[key] = property;
}
}
if (data.type === 'edge') {
data_dic.source = data.outV;
data_dic.target = data.inV;
}
return data_dic;
};
/**
* @param {?} vertexProperty
* @return {?}
*/
GraphexpService.prototype.get_vertex_prop_in_list = function (vertexProperty) {
var /** @type {?} */ prop_value_list = [];
try {
for (var _a = __values(Object.keys(vertexProperty)), _b = _a.next(); !_b.done; _b = _a.next()) {
var key = _b.value;
prop_value_list.push(vertexProperty[key]['value']);
}
}
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {
try {
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
}
finally { if (e_5) throw e_5.error; }
}
return prop_value_list;
var e_5, _c;
};
/**
* @param {?} list
* @param {?} elem
* @return {?}
*/
GraphexpService.prototype.idIndex = function (list, elem) {
// find the element in list with id equal to elem
// return its index or null if there is no
for (var /** @type {?} */ i = 0; i < list.length; i++) {
if (list[i].id === elem) {
return i;
}
}
return null;
};
/**
* @param {?} data
* @return {?}
*/
GraphexpService.prototype.make_properties_list = function (data) {
var /** @type {?} */ prop_dic = {};
try {
for (var _a = __values(Object.keys(data)), _b = _a.next(); !_b.done; _b = _a.next()) {
var prop_str = _b.value;
prop_str = prop_str.replace(/[\[\ \"\'\]]/g, ''); // get rid of symbols [,",',] and spaces
var /** @type {?} */ prop_list = prop_str.split(',');
for (var /** @type {?} */ prop_idx = 0; prop_idx < prop_list.length; prop_idx++) {
prop_dic[prop_list[prop_idx]] = 0;
}
}
}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
finally {
try {
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
}
finally { if (e_6) throw e_6.error; }
}
var /** @type {?} */ properties_list = [];
try {
for (var _d = __values(Object.getOwnPropertyNames(prop_dic)), _e = _d.next(); !_e.done; _e = _d.next()) {
var key = _e.value;
properties_list.push(key);
}
}
catch (e_7_1) { e_7 = { error: e_7_1 }; }
finally {
try {
if (_e && !_e.done && (_f = _d.return)) _f.call(_d);
}
finally { if (e_7) throw e_7.error; }
}
return properties_list;
var e_6, _c, e_7, _f;
};
/**
* @param {?} value
* @return {?}
*/
GraphexpService.prototype.isInt = function (value) {
return !isNaN(value) &&
!isNaN(parseInt(value, 10));
};
/**
* @param {?} edge
* @return {?}
*/
GraphexpService.prototype.updateSelection = function (edge) {
console.log('graphexpService#updateSelection: edge selected: ' + edge.id);
};
return GraphexpService;
}());
GraphexpService.decorators = [
{ type: core.Injectable },
];
/** @nocollapse */
GraphexpService.ctorParameters = function () { return [
null,
]; };
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var GraphConfig = /** @class */ (function () {
function GraphConfig() {
this.enableEdit = true;
this.nodeLabels = [];
this.linkLabels = [];
this.numberOfLayers = 3;
this.format = GraphsonFormat.GraphSON3;
// Physics
this.force_strength = -600;
this.link_strength = 0.2;
this.force_x_strength = 0.1;
this.force_y_strength = 0.1;
// Nodes
this.default_node_size = 15;
this.default_stroke_width = 2;
this.default_node_color = '#80E810';
this.active_node_margin = 6;
this.active_node_margin_opacity = 0.3;
// Edges
this.default_edge_stroke_width = 3;
this.default_edge_color = '#CCC';
this.edge_label_color = '#111';
this.colorPalette = d3.scaleOrdinal(d3.schemeCategory20);
}
return GraphConfig;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var D3Node = /** @class */ (function () {
/**
* @param {?=} options
*/
function D3Node(options) {
this.properties = {};
Object.assign(this, options);
}
/**
* @param {?} key
* @param {?} value
* @return {?}
*/
D3Node.prototype.addProperty = function (key, value) {
this.properties[key] = value;
};
/**
* @param {?} key
* @return {?}
*/
D3Node.prototype.removeProperty = function (key) {
delete this.properties[key];
};
return D3Node;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var GraphLayers = /** @class */ (function () {
/**
* @param {?} graphViz
*/
function GraphLayers(graphViz) {
this.graphViz = graphViz;
// Submodule that handles layers of visualization
this.old_Nodes = [];
this.old_Links = [];
this._Nodes = [];
this._Links = [];
}
/**
* @return {?}
*/
GraphLayers.prototype.depth = function () {
return this.config.numberOfLayers;
};
Object.defineProperty(GraphLayers.prototype, "config", {
/**
* @return {?}
*/
get: function () {
return this.graphViz.config;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphLayers.prototype, "nodes", {
/**
* @return {?}
*/
get: function () {
return this._Nodes;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphLayers.prototype, "links", {
/**
* @return {?}
*/
get: function () {
return this._Links;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphLayers.prototype, "_svg", {
/**
* @return {?}
*/
get: function () {
return this.graphViz.graphRoot;
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
GraphLayers.prototype.push_layers = function () {
// old links and nodes become older
// and are moved to the next deeper layer
for (var /** @type {?} */ k = this.config.numberOfLayers; k > 0; k--) {
var /** @type {?} */ kp = k - 1;
this._svg.selectAll('.old_edge' + kp).classed('old_edge' + k, true);
this._svg.selectAll('.old_node' + kp).classed('old_node' + k, true);
this._svg.selectAll('.old_edgepath' + kp).classed('old_edgepath' + k, true);
this._svg.selectAll('.old_edgelabel' + kp).classed('old_edgelabel' + k, true);
}
};
/**
* @return {?}
*/
GraphLayers.prototype.clear_old = function () {
this.old_Nodes = [];
this.old_Links = [];
};
/**
* @param {?} d
* @return {?}
*/
GraphLayers.prototype.update_data = function (d) {
// Save the data
var /** @type {?} */ previous_nodes = this._svg.selectAll('g').filter('.active_node');
var /** @type {?} */ previous_nodes_data = previous_nodes.data();
this.old_Nodes = this.updateAdd(this.old_Nodes, previous_nodes_data);
var /** @type {?} */ previous_links = this._svg.selectAll('.active_edge');
var /** @type {?} */ previous_links_data = previous_links.data();
this.old_Links = this.updateAdd(this.old_Links, previous_links_data);
// handle the pinned nodes
var /** @type {?} */ pinned_Nodes = this._svg.selectAll('g').filter('.pinned');
var /** @type {?} */ pinned_nodes_data = pinned_Nodes.data();
// get the node data and merge it with the pinned nodes
this._Nodes = d.nodes;
this._Nodes = this.updateAdd(this._Nodes, pinned_nodes_data);
// add coordinates to the new active nodes that already existed in the previous step
this._Nodes = this.transfer_coordinates(this._Nodes, this.old_Nodes);
// retrieve the links between nodes and pinned nodes
this._Links = d.links.concat(previous_links_data); // first gather the links
this._Links = this.find_active_links(this._Links, this._Nodes); // then find the ones that are between active nodes
};
/**
* @param {?} array1
* @param {?} array2
* @return {?}
*/
GraphLayers.prototype.updateAdd = function (array1, array2) {
// Update lines of array1 with the ones of array2 when the elements' id match
// and add elements of array2 to array1 when they do not exist in array1
var /** @type {?} */ arraytmp = array2.slice(0);
var /** @type {?} */ removeValFromIndex = [];
array1.forEach(function (d, index, thearray) {
for (var /** @type {?} */ i = 0; i < arraytmp.length; i++) {
if (d.id === arraytmp[i].id) {
thearray[index] = arraytmp[i];
removeValFromIndex.push(i);
}
}
});
// remove the already updated values (in reverse order, not to mess up the indices)
removeValFromIndex.sort();
for (var /** @type {?} */ i = removeValFromIndex.length - 1; i >= 0; i--) {
arraytmp.splice(removeValFromIndex[i], 1);
}
return array1.concat(arraytmp);
};
/**
* @param {?} list_of_links
* @param {?} active_nodes
* @return {?}
*/
GraphLayers.prototype.find_active_links = function (list_of_links, active_nodes) {
// find the links in the list_of_links that are between the active nodes and discard the others
var /** @type {?} */ active_links = [];
list_of_links.forEach(function (row) {
for (var /** @type {?} */ i = 0; i < active_nodes.length; i++) {
for (var /** @type {?} */ j = 0; j < active_nodes.length; j++) {
if (active_nodes[i].id === row.source.id && active_nodes[j].id === row.target.id) {
var /** @type {?} */ L_data = new D3Node(row);
L_data.source = row.source.id;
L_data.target = row.target.id;
active_links = active_links.concat(L_data);
}
else if (active_nodes[i].id === row.source && active_nodes[j].id === row.target) {
var /** @type {?} */ L_data = row;
active_links = active_links.concat(L_data);
}
}
}
});
// the active links are in active_links but there can be some duplicates
// remove duplicates links
var /** @type {?} */ dic = {};
for (var /** @type {?} */ i = 0; i < active_links.length; i++) {
dic[active_links[i].id] = active_links[i]; // this will remove the duplicate links (with same id)
}
var /** @type {?} */ list_of_active_links = [];
try {
for (var _a = __values(Object.keys(dic)), _b = _a.next(); !_b.done; _b = _a.next()) {
var key = _b.value;
list_of_active_links.push(dic[key]);
}
}
catch (e_8_1) { e_8 = { error: e_8_1 }; }
finally {
try {
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
}
finally { if (e_8) throw e_8.error; }
}
return list_of_active_links;
var e_8, _c;
};
/**
* @param {?} Nodes
* @param {?} old_Nodes
* @return {?}
*/
GraphLayers.prototype.transfer_coordinates = function (Nodes, old_Nodes) {
// Transfer coordinates from old_nodes to the new nodes with the same id
for (var /** @type {?} */ i = 0; i < old_Nodes.length; i++) {
for (var /** @type {?} */ j = 0; j < Nodes.length; j++) {
if (Nodes[j].id === old_Nodes[i].id) {
Nodes[j].x = old_Nodes[i].x;
Nodes[j].y = old_Nodes[i].y;
Nodes[j].fx = old_Nodes[i].x;
Nodes[j].fy = old_Nodes[i].y;
Nodes[j].vx = old_Nodes[i].vx;
Nodes[j].vy = old_Nodes[i].vy;
}
}
}
return Nodes;
};
/**
* @param {?} elem_class
* @param {?} elem_class_old
* @return {?}
*/
GraphLayers.prototype.remove_duplicates = function (elem_class, elem_class_old) {
var _this = this;
// Remove all the duplicate nodes and edges among the old_nodes and old_edges.
// A node or an edge can not be on several layers at the same time.
d3.selectAll(elem_class).each(function (d) {
var /** @type {?} */ ID = d.id;
for (var /** @type {?} */ n = 0; n < _this.config.numberOfLayers; n++) {
var /** @type {?} */ list_old_elements = d3.selectAll(elem_class_old + n);
// list_old_nodes_data = list_old_nodes.data();
list_old_elements.each(function (od) {
if (od.id === ID) {
d3.select(_this).remove();
// console.log('Removed!!')
}
});
}
});
};
return GraphLayers;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var GraphShapes = /** @class */ (function () {
/**
* @param {?} graphSONFormat
* @param {?} graph_viz
* @param {?} graphexpService
*/
function GraphShapes(graphSONFormat, graph_viz, graphexpService) {
this.graphSONFormat = graphSONFormat;
this.graph_viz = graph_viz;
this.graphexpService = graphexpService;
// https://github.com/wbkd/d3-extended
d3.selection.prototype.moveToFront = function () {
// move the selection to the front
return this.each(function () {
this.parentNode.appendChild(this);
});
};
d3.selection.prototype.moveToBack = function () {
// move the selection to the back
return this.each(function () {
var /** @type {?} */ firstChild = this.parentNode.firstChild;
if (firstChild) {
this.parentNode.insertBefore(this, firstChild);
}
});
};
}
/**
* @param {?} nb_layers
* @return {?}
*/
GraphShapes.prototype.decorate_old_elements = function (nb_layers) {
var _loop_1 = function (k) {
d3.selectAll('.old_edge' + k)
.style('opacity', function () {
return 0.8 * (1 - k / nb_layers);
});
d3.selectAll('.old_node' + k)
.style('opacity', function () {
return 0.8 * (1 - k / nb_layers);
});
d3.selectAll('.old_edgelabel' + k)
.style('opacity', function () {
return 0.8 * (1 - k / nb_layers);
});
};
// Decrease the opacity of nodes and edges when they get old
for (var /** @type {?} */ k = 0; k < nb_layers; k++) {
_loop_1(/** @type {?} */ k);
}
};
/**
* @param {?} value
* @return {?}
*/
GraphShapes.prototype.show_names = function (value) {
var /** @type {?} */ text_to_show = d3.selectAll('.text_details');
if (value) {
text_to_show.style('visibility', 'visible');
}
else {
text_to_show.style('visibility', 'hidden');
}
};
return GraphShapes;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var GraphLinks = /** @class */ (function () {
/**
* @param {?} graphViz
*/
function GraphLinks(graphViz) {
this.graphViz = graphViz;
}
Object.defineProperty(GraphLinks.prototype, "config", {
/**
* @return {?}
*/
get: function () {
return this.graphViz.config;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphLinks.prototype, "graphRoot", {
/**
* @return {?}
*/
get: function () {
return this.graphViz.graphRoot;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphLinks.prototype, "linkModels", {
/**
* @return {?}
*/
get: function () {
return this.graphViz.linkModels;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphLinks.prototype, "nodeModels", {
/**
* @return {?}
*/
get: function () {
return this.graphViz.nodeModels;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphLinks.prototype, "selectLinks", {
/**
* @return {?}
*/
get: function () {
return this.graphViz.selectLinks;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphLinks.prototype, "selectEdgePaths", {
/**
* @return {?}
*/
get: function () {
return this.graphViz.selectEdgePaths;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphLinks.prototype, "selectEdgeLabels", {
/**
* @return {?}
*/
get: function () {
return this.graphViz.selectEdgeLabels;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphLinks.prototype, "selectGraphNodes", {
/**
* @return {?}
*/
get: function () {
return this.graphViz.selectGraphNodes;
},
enumerable: true,
configurable: true
});
/**
* @param {?} arrangedData
* @return {?}
*/
GraphLinks.prototype.update = function (arrangedData) {
// links not active anymore are classified old_links
this.selectLinks.exit().classed('old_edge0', true).classed('active_edge', false);
this.selectEdgePaths.exit().classed('old_edgepath0', true).classed('active_edgepath', false);
this.selectEdgeLabels.exit().classed('old_edgelabel0', true).classed('active_edgelabel', false);
// handling active links associated to the data
var /** @type {?} */ edgepaths_e = this.selectEdgePaths.enter(), /** @type {?} */ edgelabels_e = this.selectEdgeLabels.enter(), /** @type {?} */ link_e = this.selectLinks.enter();
var /** @type {?} */ decor_out = this.decorate(link_e, edgepaths_e, edgelabels_e);
var /** @type {?} */ links = decor_out[0], /** @type {?} */ edgepaths = decor_out[1], /** @type {?} */ edgelabels = decor_out[2];
// previous links plus new links are merged
links.merge(this.selectLinks);
edgepaths.merge(this.selectEdgePaths);
edgelabels.merge(this.selectEdgeLabels);
};
/**
* @return {?}
*/
GraphLinks.prototype.tick = function () {
this.selectLinks
.attr('x1', function (d) {
return d.source.x;
})
.attr('y1', function (d) {
return d.source.y;
})
.attr('x2', function (d) {
return d.target.x;
})
.attr('y2', function (d) {
return d.target.y;
});
this.selectEdgePaths.attr('d', function (d) {
return 'M ' + d.source.x + ' ' + d.source.y + ' L ' + d.target.x + ' ' + d.target.y;
});
this.selectEdgeLabels.attr('transform', function (d) {
if (d.target.x < d.source.x) {
var /** @type {?} */ bbox = this.getBBox();
var /** @type {?} */ rx = bbox.x + bbox.width / 2;
var /** @type {?} */ ry = bbox.y + bbox.height / 2;
return 'rotate(180 ' + rx + ' ' + ry + ')';
}
else {
return 'rotate(0)';
}
});
};
/**
* @param {?} d
* @return {?}
*/
GraphLinks.prototype.getStrokeWidth = function (d) {
if ('stroke_width' in d) {
return d.stroke_width;
}
else {
return this.config.default_edge_stroke_width;
}
};
/**
* @param {?} d
* @return {?}
*/
GraphLinks.prototype.getEdgeText = function (d) {
if ('text' in d) {
return d.text;
}
else {
return d.properties.weight;
}
};
/**
* @param {?} d
* @return {?}
*/
GraphLinks.prototype.getEdgeColor = function (d) {
if ('color' in d) {
return d.color;
}
else {
return this.config.default_edge_color;
}
};
/**
* @param {?} edges
* @param {?} edgepaths
* @param {?} edgelabels
* @return {?}
*/
GraphLinks.prototype.decorate = function (edges, edgepaths, edgelabels) {
var _this = this;
var /** @type {?} */ edges_deco = edges.append('line').attr('class', 'edge').classed('active_edge', true)
.attr('source_ID', function (d) {
return d.source;
})
.attr('target_ID', function (d) {
return d.target;
})
.attr('ID', function (d) {
return d.id;
});
this.createMarkers(edges_deco);
// Attach the arrows
edges_deco.attr('marker-end', function (d) {
return 'url(#marker_' + d.id + ')';
})
.attr('stroke-width', function (d) { return _this.getStrokeWidth(d); })
.append('title').text(function (d) {
return d.properties.weight;
});
// Attach the edge labels
var /** @type {?} */ e_label = this.createEdgeLabels(edgepaths, edgelabels);
var /** @type {?} */ edgepaths_deco = e_label[0];
var /** @type {?} */ edgelabels_deco = e_label[1];
edgelabels_deco.append('textPath')
.attr('class', 'edge_text')
.attr('href', function (d, i) {
return '#edgepath' + d.id;
})
.style('text-anchor', 'middle')
.style('pointer-events', 'none')
.attr('startOffset', '50%')
.text(function (d) {
return d.label;
});
// Attach the edge actions
this.attachEdgeEvents(edges_deco);
// Add property info if checkbox checked
this.addEnabledProperties('edges', edgelabels_deco);
return [edges_deco, edgepaths_deco, edgelabels_deco];
};
/**
* @param {?} id
* @return {?}
*/
GraphLinks.prototype.nodeModelById = function (id) {
// return data associated to the node with id 'id'
for (var /** @type {?} */ node in this.nodeModels) {
// console.log(_Nodes[node])
if (this.nodeModels[node].id === id) {
return this.nodeModels[node];
}
}
};
/**
* @param {?} edge_in
* @return {?}
*/
GraphLinks.prototype.createMarkers = function (edge_in) {
var _this = this;
var /** @type {?} */ edge_data = edge_in.data();
var /** @type {?} */ arrow_data = this.graphRoot.selectAll('.arrow').data();
var /** @type {?} */ data = arrow_data.concat(edge_data);
this.graphRoot.selectAll('.arrow')
.data(data)
.enter()
.append('marker')
.attr('class', 'arrow')
.attr('id', function (d) { return 'marker_' + d.id; })
.attr('markerHeight', 5)
.attr('markerWidth', 5)
.attr('markerUnits', 'strokeWidth')
.attr('orient', 'auto')
.attr('refX', function (d) {
var /** @type {?} */ node = _this.nodeModelById(d.target);
return _this.graphViz.graphNodes.getNodeSize(node) + _this.graphViz.graphNodes.getNodeStrokeWidth(node);
})
.attr('refY', 0)
.attr('viewBox', '0 -5 10 10')
.append('svg:path')
.attr('d', 'M0,-5L10,0L0,5')
.style('fill', function (d) { return _this.getEdgeColor(d); });
};
/**
* @param {?} item
* @param {?} selected_items
* @return {?}
*/
GraphLinks.prototype.addEnabledProperties = function (item, selected_items) {
// Add text from a property if the checkbox is checked on the sidebar
var /** @type {?} */ item_properties = [];
for (var /** @type {?} */ prop_idx = 0; prop_idx < item_properties.length; prop_idx++) {
var /** @type {?} */ prop_name = item_properties[prop_idx];
var /** @type {?} */ prop_id_nb = prop_idx;
this.graphViz.attachEnabledProperties(selected_items, prop_name, prop_id_nb, item);
}
};
/**
* @param {?} edgepaths
* @param {?} edgelabels
* @return {?}
*/
GraphLinks.prototype.createEdgeLabels = function (edgepaths, edgelabels) {
var /** @type {?} */ edgepaths_deco = edgepaths.append('path')
.attr('class', 'edgepath').classed('active_edgepath', true)
.attr('fill-opacity', 0)
.attr('stroke-opacity', 0)
.attr('id', function (d, i) {
return 'edgepath' + d.id;
})
.attr('ID', function (d) {
return d.id;
})
.style('pointer-events', 'none');
var /** @type {?} */ edgelabels_deco = edgelabels.append('text')
.attr('dy', -3)
.style('pointer-events', 'none')
.attr('class', 'edgelabel').classed('active_edgelabel', true)
.attr('id', function (d, i) {
return 'edgelabel' + d.id;
})
.attr('ID', function (d) {
return d.id;
})
.attr('font-size', 10)
.attr('fill', this.config.edge_label_color);
return [edgepaths_deco, edgelabels_deco];
};
/**
* @param {?} edge
* @return {?}
*/
GraphLinks.prototype.attachEdgeEvents = function (edge) {
edge.on('mouseover', function (theEdge, index, elements) {
console.log('mouse over!!');
var /** @type {?} */ line = elements[index];
d3.select(line).selectAll('.text_details').style('visibility', 'visible');
})
.on('mouseout', function (theEdge, index, elements) {
var /** @type {?} */ line = elements[index];
d3.select(line).selectAll('.text_details').style('visibility', 'hidden');
})
.on('click', function (theEdge, index, elements) {
console.log('edge clicked!');
});
};
return GraphLinks;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var GraphNodes = /** @class */ (function () {
/**
* @param {?} graphViz
*/
function GraphNodes(graphViz) {
this.graphViz = graphViz;
this.connectionCreated = new BehaviorSubject.BehaviorSubject(null);
}
Object.defineProperty(GraphNodes.prototype, "config", {
/**
* @return {?}
*/
get: function () {
return this.graphViz.config;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphNodes.prototype, "graphRoot", {
/**
* @return {?}
*/
get: function () {
return this.graphViz.graphRoot;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphNodes.prototype, "nodeModels", {
/**
* @return {?}
*/
get: function () {
return this.graphViz.nodeModels;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphNodes.prototype, "simulation", {
/**
* @return {?}
*/
get: function () {
return this.graphViz.simulation;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphNodes.prototype, "isShifted", {
/**
* @return {?}
*/
get: function () {
return window.event['shiftKey'] === true;
},
enumerable: true,
configurable: true
});
Object.defineProperty(GraphNodes.prototype, "graphNodes", {
/**
* get all active nodes in the graph
* @return {?}
*/
get: function () {
return this.graphViz.selectGraphNodes;
},
enumerable: true,
configurable: true
});
/**
* @param {?} relativeNode
* @return {?}
*/
GraphNodes.prototype.mouseXY = function (relativeNode) {
var /** @type {?} */ xy = d3.mouse(relativeNode);
return {
x: xy[0],
y: xy[1]
};
};
/**
* for each tick
* @return {?}
*/
GraphNodes.prototype.tick = function () {
this.graphNodes
.attr('transform', function (d) {
return "translate(" + d.x + ", " + d.y + ")";
});
};
/**
* update the node data in the graph
* @param {?} arrangedData
* @return {?}
*/
GraphNodes.prototype.update = function (arrangedData) {
console.log('GraphNodes#update');
// old nodes not active any more are tagged
this.graphNodes.exit().classed('old_node0', true).classed('active_node', false);
// nodes associated to the data are constructed
var /** @type {?} */ nodes = this.graphNodes.enter();
// add node decoration
var /** @type {?} */ node_deco = this.decorateNodes(nodes);
nodes = node_deco.merge(nodes);
};
/**
* @param {?} node
* @return {?}
*/
GraphNodes.prototype.decorateNodes = function (node) {
var _this = this;
var /** @type {?} */ _self = this;
var /** @type {?} */ node_deco = node.append('g')
.attr('class', 'active_node').attr('ID', function (d) {
return d.id;
})
.classed('node', true);
// Attach the event listener
this.attachNodeEvents(node_deco);
node_deco.moveToFront();
// Create the circle shape
var /** @type {?} */ node_base_circle = node_deco.append('circle').classed('base_circle', true)
.attr('r', function (d) { return _this.getNodeSize(d); })
.style('stroke-width', function (d) { return _this.getNodeStrokeWidth(d); })
.style('stroke', 'black')
.attr('fill', function (d) { return _this.getNodeColor(d); });
node_base_circle.append('title').text(function (d) { return _this.getNodeText(d); });
// Add the text to the nodes
node_deco.append('text').classed('text_details', true)
.attr('x', function (d) {
return _this.config.default_node_size + 2;
})
.text(function (d) { return _this.getNodeText(d); })
.style('visibility', 'hidden');
node_deco.append('text').classed('text_details', true)
.attr('x', function (d) {
return _this.config.default_node_size + 4;
})
.attr('y', this.config.default_node_size)
.text(function (d) { return _this.getNodeSubText(d); })
.style('visibility', 'hidden');
// Add the node pin
var /** @type {?} */