UNPKG

@savantly/ngx-graphexp

Version:

Gremlin client [Tinkerpop] for an Angular app

1,360 lines (1,350 loc) 97.2 kB
(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 {?} */