UNPKG

@savantly/ngx-gremlin

Version:

Gremlin client [Tinkerpop] for an Angular app

2,531 lines 97.6 kB
import * as tslib_1 from "tslib";
import { Injectable, Component, Inject, Input, ViewEncapsulation, NgModule } from '@angular/core';
import { GremlinService } from '@savantly/gremlin-js';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { scaleOrdinal, schemeCategory20, zoom, event, forceSimulation, forceManyBody, forceLink, forceCenter, forceY, forceX, select, selectAll, selection, mouse, drag, range } from 'd3';
import { Observable } from 'rxjs/Observable';
import { MatDialogRef, MAT_DIALOG_DATA, MatDialog, MatSidenavModule, MatButtonModule, MatIconModule, MatFormFieldModule, MatInputModule, MatListModule, MatSelectModule, MatCheckboxModule, MatToolbarModule, MatSliderModule, MatDialogModule } from '@angular/material';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { FlexLayoutModule } from '@angular/flex-layout';
/**
 * @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 GraphexpService = /** @class */ (function () {
    /**
     * @param {?} options
     */
    function GraphexpService(options) {
        this.COMMUNICATION_METHOD = GraphsonFormat.GraphSON3;
        this.graphInfoData = new BehaviorSubject({});
        this.nodeNames = new BehaviorSubject([]);
        this.nodeProperties = new BehaviorSubject([]);
        this.edgeProperties = new BehaviorSubject([]);
        this.node_limit_per_request = 50;
        this.gremlinService = new 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 = tslib_1.__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 = tslib_1.__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 = tslib_1.__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 = tslib_1.__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 = tslib_1.__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 = tslib_1.__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 = tslib_1.__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: 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 = scaleOrdinal(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 = tslib_1.__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.
        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 = selectAll(elem_class_old + n);
                // list_old_nodes_data = list_old_nodes.data();
                list_old_elements.each(function (od) {
                    if (od.id === ID) {
                        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
        selection.prototype.moveToFront = function () {
            // move the selection to the front
            return this.each(function () {
                this.parentNode.appendChild(this);
            });
        };
        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) {
            selectAll('.old_edge' + k)
                .style('opacity', function () {
                return 0.8 * (1 - k / nb_layers);
            });
            selectAll('.old_node' + k)
                .style('opacity', function () {
                return 0.8 * (1 - k / nb_layers);
            });
            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 = 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];
            select(line).selectAll('.text_details').style('visibility', 'visible');
        })
            .on('mouseout', function (theEdge, index, elements) {
            var /** @type {?} */ line = elements[index];
            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(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 = 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 {?} */ node_pin = node_deco.append('circle').classed('Pin', true)
            .attr('r', function (d) {
            return _this.config.default_node_size / 2;
        })
            .attr('transform', function (d) {
            return 'translate(' + (_this.config.default_node_size * 3 / 4) + ',' + (-_this.config.default_node_size * 3 / 4) + ')';
        })
            .attr('fill', this.config.default_node_color)
            .moveToBack()
            .style('visibility', 'hidden');
        node_pin.on('click', function (d) {
            _self.pinIt(this, d);
        });
        // spot the active node and draw additional circle around it
        /* TODO: make active node different
            if (with_active_node) {
              d3.selectAll('.active_node').each((d) => {
                if (d.id === with_active_node) {
                  const n_radius = Number(d3.select(this).select('.base_circle').attr('r')) + this.active_node_margin;
                  d3.select(this)
                    .append('circle').classed('focus_node', true)
                    .attr('r', n_radius)
                    .attr('fill', this.node_color)
                    .attr('opacity', this.active_node_margin_opacity)
                    .moveToBack();
                }
              });
            }
             */
        return node_deco;
    };
    /**
     * @param {?} node
     * @return {?}
     */
    GraphNodes.prototype.attachNodeEvents = function (node) {
        var _this = this;
        var /** @type {?} */ _self = this;
        node.call(drag()
            .on('start', function (d) {
            if (_self.isShifted) {
                _self.dragConnectionStarted(d);
            }
            else {
                _self.dragNodeStarted(d);
            }
        })
            .on('drag', function (d) {
            if (_self.isShifted) {
                _self.draggingConnection(d);
            }
            else {
                _self.draggingNode(d);
            }
        })
            .on('end', function (ev) {
            if (_this.isShifted) {
                _this.dragConnectionEnded(ev);
            }
            else {
                _this.dragNodeEnded(ev);
            }
        }));
        node.on('click', function (ev) { _this.clicked(ev); })
            .on('mouseover', function () {
            select(this).select('.Pin').style('visibility', 'visible');
            select(this).selectAll('.text_details').style('visibility', 'visible');
        })
            .on('mouseout', function () {
            var /** @type {?} */ chosen_node = select(this);
            if (!chosen_node.classed('pinned')) {
                select(this).select('.Pin').style('visibility', 'hidden');
            }
            if (!this.show_name) {
                select(this).selectAll('.text_details').style('visibility', 'hidden');
            }
        });
    };
    /**
     * @param {?} node_id
     * @return {?}
     */
    GraphNodes.prototype.getConnectedEdgesByNodeId = function (node_id) {
        // Return the in and out edges of node with id 'node_id'
        var /** @type {?} */ connected_edges = selectAll('.edge').filter(function (item) {
            if (item.source === node_id || item.source.id === node_id) {
                return item;
            }
            else if (item.target === node_id || item.target.id === node_id) {
                return item;
            }
        });
        return connected_edges;
    };
    /**
     * @param {?} d
     * @return {?}
     */
    GraphNodes.prototype.dragConnectionStarted = function (d) {
        this.mouseDownNode = d;
    };
    /**
     * @param {?} d
     * @return {?}
     */
    GraphNodes.prototype.dragNodeStarted = function (d) {
        if (!event.active) {
            this.simulation.alphaTarget(0.3).restart();
        }
        d.fx = d.x;
        d.fy = d.y;
    };
    /**
     * @param {?} d
     * @return {?}
     */
    GraphNodes.prototype.draggingConnection = function (d) {
        // reposition dragged directed edge
        if (!this.mouseDownNode) {
            return;
        }
        var /** @type {?} */ dragLine = this.graphViz.dragLine.classed('hidden', false);
        var /** @type {?} */ transform = this.graphRoot.attr('transform');
        this.graphViz.dragLine
            .attr('d', "M " + d.x + "," + d.y + " L " + event.x + ", " + event.y)
            .attr('transform', transform);
        console.log('dragging new connection');
    };
    /**
     * @param {?} d
     * @return {?}
     */
    GraphNodes.prototype.draggingNode = function (d) {
        var /** @type {?} */ connected_edges = this.getConnectedEdgesByNodeId(d.id);
        var /** @type {?} */ f_connected_edges = connected_edges.filter('*:not(.active_edge)');
        if (f_connected_edges._groups[0].length === 0) {
            d.fx = event.x;
            d.fy = event.y;
        }
        else {
            f_connected_edges
                .style('stroke-width', function () {
                return parseInt(select(this).attr('stroke-width'), 10) + 2;
            })
                .style('stroke-opacity', 1)
                .classed('blocking', true);
        }
    };
    /**
     * @param {?} d
     * @return {?}
     */
    GraphNodes.prototype.dragConnectionEnded = function (d) {
        var /** @type {?} */ target = event.sourceEvent.toElement;
        this.graphViz.dragLine.classed('hidden', true);
        console.log("connecting to: " + target);
        this.connectionCreated.next({
            source: this.mouseDownNode,
            target: select(target).data()[0]
        });
    };
    /**
     * @param {?} d
     * @return {?}
     */
    GraphNodes.prototype.dragNodeEnded = function (d) {
        if (!event.active) {
            this.simulation.alphaTarget(0);
        }
        selectAll('.blocking')
            .style('stroke-width', function () {
            return select(this).attr('stroke-width');
        })
            .style('stroke-opacity', function () {
            return select(this).attr('stroke-opacity');
        })
            .classed('blocking', false);
        // d.fx = null;
        // d.fy = null;
    };
    /**
     * @param {?} d
     * @return {?}
     */
    GraphNodes.prototype.clicked = function (d) {
        select('.focus_node').remove();
        // TODO: wire up 'freeze' button
        // const input = document.getElementById('freeze-in');
        // const isChecked = input.checked;
        // if (isChecked) {
        //  infobox.display_info(d);
        // } else {
        this.simulation.stop();
        // remove the oldest links and nodes
        var /** @type {?} */ stop_layer = this.graphViz.graphLayers.depth() - 1;
        this.graphRoot.selectAll('.old_node' + stop_layer).remove();
        this.graphRoot.selectAll('.old_edge' + stop_layer).remove();
        this.graphRoot.selectAll('.old_edgepath' + stop_layer).remove();
        this.graphRoot.selectAll('.old_edgelabel' + stop_layer).remove();
        this.graphViz.displayInfo(d);
        this.graphViz.loadRelatedNodes(d);
        console.log('node clicked');
    };
    /**
     * @param {?} elem
     * @param {?} data
     * @return {?}
     */
    GraphNodes.prototype.pinIt = function (elem, data) {
        var _this = this;
        event.stopPropagation();
        var /** @type {?} */ node_pin = select(elem);
        var /** @type {?} */ pinned_node = select(elem.parentNode);
        if (!pinned_node.empty() && pinned_node.classed('active_node')) {
            if (!pinned_node.classed('pinned')) {
                pinned_node.classed('pinned', true);
                console.log('Pinned!');
                node_pin.attr('fill', '#000');
                pinned_node.moveToFront();
            }
            else {
                pinned_node.classed('pinned', false);
                console.log('Unpinned!');
                node_pin.attr('fill', function () { return _this.getNodeColor(data); });
            }
        }
    };
    /**
     * @param {?} prop_name
     * @return {?}
     */
    GraphNodes.prototype.colorize = function (prop_name) {
        var _this = this;
        // Color the nodes according the value of the property 'prop_name'
        var /** @type {?} */ node_code_color = null;
        var /** @type {?} */ value_list = selectAll('.node').data();
        if (prop_name === 'none') {
            selectAll('.base_circle').style('fill', function (d) {
                return _this.getNodeColor(d);
            });
            selectAll('.Pin').style('fill', function (d) {
                return _this.getNodeColor(d);
            });
        }
        else if (prop_name === 'label') {
            var /** @type {?} */ value_set = new Set(value_list.map(function (d) {
                return d.label;
            }));
            node_code_color = scaleOrdinal().domain(value_set).range(range(0, value_set.size));
            selectAll('.base_circle').style('fill', function (d) {
                return _this.config.colorPalette(node_code_color(d.label));
            });
            selectAll('.Pin').style('fill', function (d) {
                return _this.config.colorPalette(node_code_color(d.label));
            });
        }
        else {
            var /** @type {?} */ value_set = new Set(value_list.map(function (d) {
                if (typeof d.properties[prop_name] !== 'undefined') {
                    return d.properties[prop_name][0].value;
                }
            }));
            node_code_color = scaleOrdinal().domain(value_set).range(range(0, value_set.size));
            selectAll('.base_circle').style('fill', function (d) {
                if (typeof d.properties[prop_name] !== 'undefined') {
                    return _this.config.colorPalette(node_code_color(d.properties[prop_name][0].value));
                }
                return _this.getNodeColor(d);
            });
            selectAll('.Pin').style('fill', function (d) {
                if (typeof d.properties[prop_name] !== 'undefined') {
                    return _this.config.colorPalette(node_code_color(d.properties[prop_name][0].value));
                }
                return _this.getNodeColor(d);
            });
        }
    };
    /**
     * @param {?} d
     * @return {?}
     */
    GraphNodes.prototype.getNodeSize = function (d) {
        if ('size' in d) {
            return d.size;
        }
        else {
            return this.config.default_node_size;
        }
    };
    /**
     * @param {?} d
     * @return {?}
     */
    GraphNodes.prototype.getNodeStrokeWidth = function (d) {
        if ('stroke_width' in d) {
            return d.stroke_width;
        }
        else {
            return this.config.default_stroke_width;
        }
    };
    /**
     * @param {?} d
     * @return {?}
     */
    GraphNodes.prototype.getNodeColor = function (d) {
        return this.config.default_node_color;
        /*
            if (colored_prop !== 'none') {
              if (colored_prop === 'label') {
                return this.color_palette(node_code_color(d.label));
              } else if (typeof d.properties[colored_prop] !== 'undefined') {
                if (this.graphSONFormat === GraphsonFormat.GraphSON3) {
                  return this.color_palette(node_code_color(d.properties[colored_prop]['summary']));
                } else {
                  return this.color_palette(node_code_color(d.properties[colored_prop][0].value));
                }
              } else if ('color' in d.properties) {
                return d.properties.color[0].value;
              } else {
                return this.default_node_color;
              }
            } else if ('color' in d.properties) {
              return d.properties.color[0].value;
            } else {
              return this.default_node_color;
            } */
    };
    /**
     * @param {?} d
     * @return {?}
     */
    GraphNodes.prototype.getNodeTitle = function (d) {
        if ('node_title' in d) {
            return d.node_title;
        }
        else {
            return d.label;
        }
    };
    /**
     * @param {?} d
     * @return {?}
     */
    GraphNodes.prototype.getNodeText = function (d) {
        if ('node_text' in d) {
            return d.node_text;
        }
        else {
            return d.id;
        }
    };
    /**
     * @param {?} d
     * @return {?}
     */
    GraphNodes.prototype.getNodeSubText = function (d) {
        if ('node_subtext' in d) {
            return d.node_subtext;
        }
        else {
            return d.label;
        }
    };
    return GraphNodes;
}());
/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes} checked by tsc
 */
var GraphViz = /** @class */ (function () {
    /**
     * @param {?} graphexpService
     * @param {?} _config
     */
    function GraphViz(graphexpService, _config) {
        this.graphexpService = graphexpService;
        this._config = _config;
        this._graphWidth = 0;
        this._graphHeight = 0;
        this._simulation = {};
        this.state = {
            shiftNodeDrag: false
        };
        this.selectedNode = new BehaviorSubject(null);
        this.createNodeEvent = new BehaviorSubject(null);
    }
    Object.defineProperty(GraphViz.prototype, "config", {
        /**
         * @return {?}
         */
        get: function () {
            return this._config;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(GraphViz.prototype, "simulation", {
        /**
         * @return {?}
         */
        get: function () {
            return this._simulation;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(GraphViz.prototype, "graphRoot", {
        /**
         * @return {?}
         */
        get: function () {
            return this._graphRoot;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(GraphViz.prototype, "nodeModels", {
        /**
         * @return {?}
         */
        get: function () {
            return this._graphLayers.nodes;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(GraphViz.prototype, "graphLayers", {
        /**
         * @return {?}
         */
        get: function () {
            return this._graphLayers;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(GraphViz.prototype, "graphNodes", {
        /**
         * @return {?}
         */
        get: function () {
            return this._graphNodes;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(GraphViz.prototype, "linkModels", {
        /**
         * @return {?}
         */
        get: function () {
            return this._graphLayers._Links;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(GraphViz.prototype, "selectLinks", {
        /**
         * @return {?}
         */
        get: function () {
            var /** @type {?} */ all_links = this.graphRoot.selectAll('.active_edge')
                .data(this.linkModels, function (n) {
                return n.id;
            });
            return all_links;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(GraphViz.prototype, "selectEdgePaths", {
        /**
         * @return {?}
         */
        get: function () {
            var /** @type {?} */ all_edgepaths = this.graphRoot.selectAll('.active_edgepath')
                .data(this.linkModels, function (n) {
                return n.id;
            });
            return all_edgepaths;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(GraphViz.prototype, "selectEdgeLabels", {
        /**
         * @return {?}
         */
        get: function () {
            var /** @type {?} */ all_edgelabels = this.graphRoot.selectAll('.active_edgelabel')
                .data(this.linkModels, function (n) {
                return n.id;
            });
            return all_edgelabels;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(GraphViz.prototype, "selectGraphNodes", {
        /**
         * get all active nodes in the graph
         * @return {?}
         */
        get: function () {
            // Existing active nodes
            var /** @type {?} */ allNodes = this.graphRoot.selectAll('g').filter('.active_node')
                .data(this.nodeModels, function (n) {
                return n.id;
            });
            return allNodes;
        },
        enumerable: true,
        configurable: true
    });
    /**
     * @return {?}
     */
    GraphViz.prototype.clear = function () {
        console.log(this._simulation);
        if (Object.keys(this._simulation).length !== 0) {
            this._simulation.stop();
            this._simulation.nodes([]);
            this._simulation.force('link').links([]);
        }
        this._graphRoot.selectAll('*').remove();
        this.nodeModels.length = 0, this.linkModels.length = 0;
        this._graphLayers.clear_old();
        this._simulation = {};
    };
    /**
     * @param {?} svg
     * @return {?}
     */
    GraphViz.prototype.addzoom = function (svg) {
        var _this = this;
        // Add zoom to the svg object
        svg.append('rect')
            .attr('width', this._graphWidth).attr('height', this._graphHeight)
            .style('fill', 'none').style('pointer-events', 'all')
            .call(zoom().scaleExtent([1 / 2, 4]).on('zoom', function () {
            _this._graphRoot.attr('transform', event.transform);
        }));
    };
    /**
     * @param {?} center_f
     * @return {?}
     */
    GraphViz.prototype.simulationStart = function (center_f) {
        var /** @type {?} */ force_x, /** @type {?} */ force_y;
        this.
            _simulation = forceSimulation()
            .force('charge', forceManyBody().strength(this._config.force_strength))
            .force('link', forceLink().strength(this._config.link_strength).id(function (d) {
            return d.id;
        }));
        if (center_f === 1) {
            force_y = this._config.force_x_strength;
            force_x = this._config.force_y_strength;
            this._simulation.force('center', forceCenter(this._graphWidth / 2, this._graphHeight / 2));
        }
        else {
            force_y = 0;
            force_x = 0;
        }
        this._simulation.force('y', forceY().strength(function (d) {
            return force_y;
        }))
            .force('x', forceX().strength(function (d) {
            return force_x;
        }));
        return this._simulation;
    };
    /**
     * @param {?} arrangedData
     * @param {?} center_f
     * @param {?} with_active_node
     * @return {?}
     */
    GraphViz.prototype.refreshData = function (arrangedData, center_f, with_active_node) {
        var _this = this;
        // Main visualization function
        var /** @type {?} */ svg_graph = this.graphRoot;
        this._graphLayers.push_layers();
        this._graphLayers.update_data(arrangedData);
        this._graphLinks.update(arrangedData);
        this._graphNodes.update(arrangedData);
        // Additional clean up
        this._graphShapes.decorate_old_elements(this._graphLayers.depth());
        svg_graph.selectAll('g').filter('.pinned').moveToFront();
        this._graphLayers.remove_duplicates('.active_node', '.old_node');
        this._graphLayers.remove_duplicates('.active_edge', '.old_edge');
        this._graphLayers.remove_duplicates('.active_edgepath', '.old_edgepath');
        this._graphLayers.remove_duplicates('.active_edgelabel', '.old_edgelabel');
        // Force simulation simulation model and paramers Associate the simulation with the data
        this._simulation = this.simulationStart(center_f);
        this._simulation.nodes(this.nodeModels).on('tick', function () {
            _this._graphNodes.tick();
            _this._graphLinks.tick();
        });
        this._simulation.force('link').links(this.linkModels);
        this._simulation.alphaTarget(0);
    };
    /**
     * @param {?} prop
     * @return {?}
     */
    GraphViz.prototype.displayShapeProperty = function (prop) {
        var /** @type {?} */ prop_id = prop.id;
        var /** @type {?} */ prop_id_nb = prop.getAttribute('id_nb');
        var /** @type {?} */ prop_name = prop_id.slice(prop_id.indexOf('_') + 1);
        var /** @type {?} */ item = prop_id.slice(0, prop_id.indexOf('_'));
        console.log(prop_id, item);
        if (select('#' + prop_id).property('checked')) {
            var /** @type {?} */ elements_text = void 0;
            if (item === 'nodes') {
                elements_text = selectAll('.node');
            }
            else if (item === 'edges') {
                elements_text = selectAll('.edgelabel');
            }
            this.attachEnabledProperties(elements_text, prop_name, prop_id_nb, item);
        }
        else {
            if (item === 'nodes') {
                selectAll('.node').select('.' + prop_id).remove();
            }
            else if (item === 'edges') {
                selectAll('.edgelabel').select('.' + prop_id).remove();
            }
        }
    };
    /**
     * @param {?} graph_objects
     * @param {?} prop_name
     * @param {?} prop_id_nb
     * @param {?} item
     * @return {?}
     */
    GraphViz.prototype.attachEnabledProperties = function (graph_objects, prop_name, prop_id_nb, item) {
        var _this = this;
        var /** @type {?} */ elements_text;
        var /** @type {?} */ text_base_offset = 10;
        var /** @type {?} */ text_offset = 10;
        var /** @type {?} */ prop_id = item + '_' + prop_name;
        if (item === 'nodes') {
            elements_text = graph_objects.append('text').style('pointer-events', 'none');
        }
        else if (item === 'edges') {
            elements_text = graph_objects.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', '70%');
            prop_id_nb = prop_id_nb + 1;
        }
        else {
            console.log('Bad item name.');
            return 1;
        }
        elements_text.classed('prop_details', true).classed(prop_id, true)
            .attr('dy', function (d) {
            return _this._graphNodes.getNodeSize(d) + text_base_offset + text_offset * parseInt(prop_id_nb, 10);
        })
            .text(function (d) {
            return _this.getPropertyValue(d, prop_name, item);
        });
    };
    /**
     * @param {?} d
     * @param {?} prop_name
     * @param {?} item
     * @return {?}
     */
    GraphViz.prototype.getPropertyValue = function (d, prop_name, item) {
        if (prop_name in d.properties) {
            if (item === 'nodes') {
                if (this._config.format === GraphsonFormat.GraphSON3) {
                    return d.properties[prop_name]['summary'];
                }
                else if (this._config.format === GraphsonFormat.GraphSON1) {
                    return d.properties[prop_name][0].value;
                }
            }
            else if (item === 'edges') {
                console.log(d.properties[prop_name]);
                return d.properties[prop_name];
            }
        }
        else {
            return '';
        }
    };
    /**
     * @param {?} data
     * @return {?}
     */
    GraphViz.prototype.colorize = function (data) {
        this._graphNodes.colorize(data);
    };
    /**
     * @param {?} data
     * @return {?}
     */
    GraphViz.prototype.displayInfo = function (data) {
        this.selectedNode.next(data);
    };
    /**
     * @param {?} d
     * @return {?}
     */
    GraphViz.prototype.loadRelatedNodes = function (d) {
        var _this = this;
        this.graphexpService.getRelatedNodes(d).then(function (arrangedData) {
            _this.refreshData(arrangedData, 1, null);
            _this.displayInfo(d);
        });
    };
    /**
     * @param {?} svg
     * @return {?}
     */
    GraphViz.prototype.addSvgDefinitions = function (svg) {
        // define arrow markers for graph links
        var /** @type {?} */ defs = svg.append('svg:defs');
        defs.append('svg:marker')
            .attr('id', 'end-arrow')
            .attr('viewBox', '0 -5 10 10')
            .attr('refX', '32')
            .attr('markerWidth', 5)
            .attr('markerHeight', 5)
            .attr('orient', 'auto')
            .append('svg:path')
            .attr('d', 'M0,-5L10,0L0,5');
        // define arrow markers for leading arrow
        defs.append('svg:marker')
            .attr('id', 'mark-end-arrow')
            .attr('viewBox', '0 -5 10 10')
            .attr('refX', 7)
            .attr('markerWidth', 5)
            .attr('markerHeight', 5)
            .attr('orient', 'auto')
            .append('svg:path')
            .attr('d', 'M0,-5L10,0L0,5');
    };
    /**
     * @param {?} label
     * @return {?}
     */
    GraphViz.prototype.init = function (label) {
        var _this = this;
        this._graphLayers = new GraphLayers(this);
        this._graphShapes = new GraphShapes(this._config.format, this, this.graphexpService);
        // GraphNodes class init
        this._graphNodes = new GraphNodes(this);
        this.connectionCreated = new Observable(function (observer) {
            _this._graphNodes.connectionCreated.subscribe(function (val) {
                if (val != null) {
                    observer.next(val);
                    console.log("connection created: " + val.source.id + " -> " + val.target.id);
                }
            });
        });
        this._graphLinks = new GraphLinks(this);
        var /** @type {?} */ svg = select(label).select('svg');
        var /** @type {?} */ width = +select(label).node().getBoundingClientRect().width;
        var /** @type {?} */ height = +select(label).node().getBoundingClientRect().height;
        this._graphWidth = width;
        this._graphHeight = height;
        // displayed when dragging between nodes
        this.dragLine = svg.append('svg:path')
            .attr('class', 'link drag-line hidden')
            .attr('d', 'M0,0L0,0')
            .style('marker-end', 'url(#mark-end-arrow)');
        svg.attr('width', this._graphWidth).attr('height', this._graphHeight);
        this.addSvgDefinitions(svg);
        this.addzoom(svg);
        // Finally create a root g node for all the nodes/links
        this._graphRoot = svg.append('g');
    };
    return GraphViz;
}());
/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes} checked by tsc
 */
var LinkEditComponent = /** @class */ (function () {
    /**
     * @param {?} dialogRef
     * @param {?} data
     */
    function LinkEditComponent(dialogRef, data) {
        this.dialogRef = dialogRef;
        this.data = data;
    }
    /**
     * @return {?}
     */
    LinkEditComponent.prototype.createProperty = function () {
        this.data.item.properties.push({ key: '', value: '' });
    };
    /**
     * @return {?}
     */
    LinkEditComponent.prototype.ngOnInit = function () {
    };
    return LinkEditComponent;
}());
LinkEditComponent.decorators = [
    { type: Component, args: [{
                selector: 'sv-link-edit',
                template: "<h2 mat-dialog-title>Edit Link</h2>\n<mat-dialog-content>\n\t<div fxLayout fxLayoutAlign=\"start center\" fxLayoutGap=\"1em\">\n\t\t<mat-input-container>\n\t\t\t<mat-select [(ngModel)]=\"data.item.label\" placeholder=\"Label\">\n\t\t\t\t<mat-option *ngFor=\"let item of data.labels\" [value]=\"item\">{{item}}</mat-option>\n\t\t\t</mat-select>\n\t\t</mat-input-container>\n\t\t<div>\n\t\t\t<button mat-raised-button (click)=\"createProperty()\"><mat-icon>add</mat-icon>Add Property</button>\n\t\t</div>\n\t</div>\n\t<div fxLayout fxLayoutGap=\"1em\" *ngFor=\"let item of data.item.properties\">\n\t\t<mat-input-container>\n\t\t\t<input matInput placeholder=\"property name\" [(ngModel)]=\"item.key\">\n\t\t</mat-input-container>\n\t\t<mat-input-container>\n\t\t\t<input matInput placeholder=\"property value\" [(ngModel)]=\"item.value\">\n\t\t</mat-input-container>\n\t</div>\n</mat-dialog-content>\n<mat-dialog-actions>\n\t<button mat-button mat-dialog-close>Cancel</button>\n\t<!-- The mat-dialog-close directive optionally accepts a value as a result for the dialog. -->\n\t<button mat-button [mat-dialog-close]=\"data.item\">Confirm</button>\n</mat-dialog-actions>",
                styles: [""]
            },] },
];
/** @nocollapse */
LinkEditComponent.ctorParameters = function () { return [
    { type: MatDialogRef, },
    { type: undefined, decorators: [{ type: Inject, args: [MAT_DIALOG_DATA,] },] },
]; };
/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes} checked by tsc
 */
var NodeEditComponent = /** @class */ (function () {
    /**
     * @param {?} dialogRef
     * @param {?} data
     */
    function NodeEditComponent(dialogRef, data) {
        this.dialogRef = dialogRef;
        this.data = data;
    }
    /**
     * @return {?}
     */
    NodeEditComponent.prototype.createProperty = function () {
        this.data.item.properties.push({ key: '', value: '' });
    };
    /**
     * @return {?}
     */
    NodeEditComponent.prototype.ngOnInit = function () {
    };
    return NodeEditComponent;
}());
NodeEditComponent.decorators = [
    { type: Component, args: [{
                selector: 'sv-node-edit',
                template: "<h2 mat-dialog-title>Edit Node</h2>\n<mat-dialog-content>\n\t<div fxLayout fxLayoutAlign=\"start center\" fxLayoutGap=\"1em\">\n\t\t<mat-input-container>\n\t\t\t<mat-select [(ngModel)]=\"data.item.label\" placeholder=\"Label\">\n\t\t\t\t<mat-option *ngFor=\"let item of data.labels\" [value]=\"item\">{{item}}</mat-option>\n\t\t\t</mat-select>\n\t\t</mat-input-container>\n\t\t<div>\n\t\t\t<button mat-raised-button (click)=\"createProperty()\"><mat-icon>add</mat-icon>Add Property</button>\n\t\t</div>\n\t</div>\n\t<div fxLayout fxLayoutGap=\"1em\" *ngFor=\"let item of data.item.properties\">\n\t\t<mat-input-container>\n\t\t\t<input matInput placeholder=\"property name\" [(ngModel)]=\"item.key\">\n\t\t</mat-input-container>\n\t\t<mat-input-container>\n\t\t\t<input matInput placeholder=\"property value\" [(ngModel)]=\"item.value\">\n\t\t</mat-input-container>\n\t</div>\n</mat-dialog-content>\n<mat-dialog-actions>\n\t<button mat-button mat-dialog-close>Cancel</button>\n\t<!-- The mat-dialog-close directive optionally accepts a value as a result for the dialog. -->\n\t<button mat-button [mat-dialog-close]=\"data.item\">Confirm</button>\n</mat-dialog-actions>",
                styles: [""]
            },] },
];
/** @nocollapse */
NodeEditComponent.ctorParameters = function () { return [
    { type: MatDialogRef, },
    { type: undefined, decorators: [{ type: Inject, args: [MAT_DIALOG_DATA,] },] },
]; };
/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes} checked by tsc
 */
var GremlinNode = /** @class */ (function () {
    function GremlinNode() {
        this.label = '';
        this.properties = [];
    }
    return GremlinNode;
}());
/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes} checked by tsc
 */
var GremlinLink = /** @class */ (function (_super) {
    tslib_1.__extends(GremlinLink, _super);
    function GremlinLink() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    return GremlinLink;
}(GremlinNode));
/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes} checked by tsc
 */
var GraphexpComponent = /** @class */ (function () {
    /**
     * @param {?} dialog
     */
    function GraphexpComponent(dialog) {
        this.dialog = dialog;
        this.searchValue = '';
        this.searchField = 'id';
        this.numberOfLayers = 3;
        this.showGraphInfo = true;
        this.newNode = {};
    }
    Object.defineProperty(GraphexpComponent.prototype, "selectedNode", {
        /**
         * @return {?}
         */
        get: function () {
            if (this.graphViz && this.graphViz.selectedNode && this.graphViz.selectedNode.value) {
                return this.graphViz.selectedNode.value;
            }
            else {
                return null;
            }
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(GraphexpComponent.prototype, "nodeNames", {
        /**
         * @return {?}
         */
        get: function () {
            return this.graphexpService.nodeNames;
        },
        enumerable: true,
        configurable: true
    });
    ;
    Object.defineProperty(GraphexpComponent.prototype, "nodeProperties", {
        /**
         * @return {?}
         */
        get: function () {
            return this.graphexpService.nodeProperties;
        },
        enumerable: true,
        configurable: true
    });
    ;
    Object.defineProperty(GraphexpComponent.prototype, "edgeProperties", {
        /**
         * @return {?}
         */
        get: function () {
            return this.graphexpService.edgeProperties;
        },
        enumerable: true,
        configurable: true
    });
    ;
    Object.defineProperty(GraphexpComponent.prototype, "enableEdit", {
        /**
         * @return {?}
         */
        get: function () {
            return (this.graphConfig && this.graphConfig.enableEdit);
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(GraphexpComponent.prototype, "nodeLabels", {
        /**
         * @return {?}
         */
        get: function () {
            return this.graphConfig.nodeLabels;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(GraphexpComponent.prototype, "linkLabels", {
        /**
         * @return {?}
         */
        get: function () {
            return this.graphConfig.linkLabels;
        },
        enumerable: true,
        configurable: true
    });
    /**
     * @return {?}
     */
    GraphexpComponent.prototype.ngOnInit = function () {
        var _this = this;
        if (!this.graphConfig) {
            this.graphConfig = new GraphConfig();
        }
        this.graphViz = new GraphViz(this.graphexpService, this.graphConfig);
        setTimeout(function () {
            _this.graphViz.init('#sv_graphexp');
            _this.graphexpService.queryGraphInfo();
            _this.graphViz.connectionCreated.subscribe(function (val) {
                console.log("GraphexpComponent#ngAfterViewInit: connection created " + val);
                var /** @type {?} */ gremlinLink = new GremlinLink();
                gremlinLink.source = val.source.id;
                gremlinLink.target = val.target.id;
                _this.openLinkEditDialog(gremlinLink);
            });
            _this.graphViz.createNodeEvent.subscribe(function (d3Node) {
                if (d3Node === null) {
                    return;
                }
                var /** @type {?} */ gremlinNode = new GremlinNode();
                _this.openNodeEditDialog(gremlinNode);
            });
        });
    };
    /**
     * @param {?} item
     * @return {?}
     */
    GraphexpComponent.prototype.openLinkEditDialog = function (item) {
        var _this = this;
        var /** @type {?} */ dialogRef = this.dialog.open(LinkEditComponent, {
            width: '30em',
            data: { labels: this.linkLabels, item: item }
        });
        dialogRef.afterClosed().subscribe(function (result) {
            console.log('The dialog was closed');
            if (result) {
                _this.createLink(result);
            }
        });
    };
    /**
     * @param {?=} item
     * @return {?}
     */
    GraphexpComponent.prototype.openNodeEditDialog = function (item) {
        var _this = this;
        item = item || new GremlinNode();
        var /** @type {?} */ dialogRef = this.dialog.open(NodeEditComponent, {
            width: '30em',
            data: { labels: this.nodeLabels, item: item }
        });
        dialogRef.afterClosed().subscribe(function (result) {
            console.log('The dialog was closed');
            if (result) {
                _this.createNode(result);
            }
        });
    };
    /**
     * @param {?} data
     * @return {?}
     */
    GraphexpComponent.prototype.createLink = function (data) {
        this.graphexpService.createLink(data).then(function (tinkerNode) {
            console.log(data);
        }, function (err) { console.error(err); });
    };
    /**
     * @param {?} data
     * @return {?}
     */
    GraphexpComponent.prototype.createNode = function (data) {
        this.graphexpService.createNode(data.label, data.properties).then(function (tinkerNode) {
            console.log(data);
        }, function (err) { console.error(err); });
    };
    /**
     * @return {?}
     */
    GraphexpComponent.prototype.search = function () {
        var _this = this;
        console.log("searching field: " + this.searchField + ", value: " + this.searchValue);
        this.graphexpService.queryNodes(this.searchField, this.searchValue).then(function (data) {
            _this.graphViz.refreshData(data, 1, null);
        }).catch(function (err) {
            console.error(err);
        });
    };
    /**
     * @param {?} node
     * @return {?}
     */
    GraphexpComponent.prototype.getFlattenedNodeProperties = function (node) {
        var /** @type {?} */ props = [];
        try {
            for (var _a = tslib_1.__values(Object.keys(node.properties)), _b = _a.next(); !_b.done; _b = _a.next()) {
                var prop = _b.value;
                var /** @type {?} */ valArray = node.properties[prop];
                var /** @type {?} */ val = valArray[0]['value'];
                props.push({
                    name: prop,
                    value: val
                });
            }
        }
        catch (e_9_1) { e_9 = { error: e_9_1 }; }
        finally {
            try {
                if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
            }
            finally { if (e_9) throw e_9.error; }
        }
        return props;
        var e_9, _c;
    };
    /**
     * @return {?}
     */
    GraphexpComponent.prototype.showNames = function () {
    };
    /**
     * @return {?}
     */
    GraphexpComponent.prototype.setNumberOfLayers = function () {
        this.graphConfig.numberOfLayers = this.numberOfLayers;
    };
    /**
     * @return {?}
     */
    GraphexpComponent.prototype.clearGraph = function () {
        this.graphViz.clear();
    };
    /**
     * @return {?}
     */
    GraphexpComponent.prototype.toggleGraphInfo = function () {
        this.showGraphInfo = !this.showGraphInfo;
    };
    /**
     * @return {?}
     */
    GraphexpComponent.prototype.getGraphInfo = function () {
        this.graphexpService.queryGraphInfo();
    };
    return GraphexpComponent;
}());
GraphexpComponent.decorators = [
    { type: Component, args: [{
                selector: 'sv-graphexp',
                template: "<div fxLayout fxFlexFill class=\"content sv-graphexp\">\n\t<mat-sidenav-container fxFLex>\n\t\t<mat-sidenav #graphexpSideMenu position=\"end\" fxLayout=\"column\" fxLayoutGap=\"1.5em\">\n\t\t\t<button mat-mini-fab color=\"accent\" (click)=\"graphexpSideMenu.toggle()\">\n\t\t      <mat-icon>arrow_right</mat-icon>\n\t\t    </button>\n\t\t    <div fxLayout fxLayoutGap=\"1em\">\n\t\t    \t<button mat-raised-button (click)=\"getGraphInfo()\">\n\t\t    \t\tRefresh<mat-icon>refresh</mat-icon>\n\t\t    \t</button>\n\t\t    \t<button mat-raised-button (click)=\"openNodeEditDialog()\">\n\t\t\t\t\tCreate<mat-icon>add</mat-icon>\n\t\t\t\t</button>\n\t\t    \t<span fxFlex></span>\n\t\t\t\t<button mat-raised-button (click)=\"clearGraph()\">\n\t\t\t\t\tClear<mat-icon>clear</mat-icon>\n\t\t\t\t</button>\n\t\t    </div>\n\t\t    <mat-checkbox [(ngModel)]=\"showGraphInfo\">Show Graph Info</mat-checkbox>\n\t\t    <mat-checkbox>Show Selection Properties</mat-checkbox>\n\t\t    <mat-checkbox (click)=\"showNames()\">Show Labels</mat-checkbox>\n\t\t    <mat-checkbox>Freeze Graph</mat-checkbox>\n\t\t\t<section>\n\t\t\t\t<div fxLayout>\n\t\t\t\t\t<label>Visible Layers</label>\n\t\t    \t\t<mat-slider min=\"1\" max=\"5\" [(ngModel)]=\"numberOfLayers\" thumbLabel tickInterval=\"1\"></mat-slider>\n\t\t\t\t</div>\n\t\t    </section>\n\t\t</mat-sidenav>\n\t\t<div fxLayout=\"column\" fxFlexFill>\n\t\t\t<mat-toolbar fxLayoutGap=\"1em\">\n\t\t\t    <label>Search</label>\n\t\t\t\t<mat-form-field>\n\t\t\t\t\t<mat-select [(ngModel)]=\"searchField\">\n\t\t\t\t\t\t<mat-optgroup label=\"Node\">\n\t\t\t\t\t\t\t<mat-option value=\"id\">id</mat-option>\n\t\t\t\t\t\t\t<mat-option *ngFor=\"let item of nodeProperties | async\" [value]=\"item\">{{item}}</mat-option>\n\t\t\t\t\t\t</mat-optgroup>\n\t\t\t\t\t\t<mat-optgroup label=\"Edge\">\n\t\t\t\t\t\t\t<mat-option value=\"id\">id</mat-option>\n\t\t\t\t\t\t\t<mat-option *ngFor=\"let item of edgeProperties | async\" [value]=\"item\">{{item}}</mat-option>\n\t\t\t\t\t\t</mat-optgroup>\n\t\t\t\t\t</mat-select>\n\t\t\t\t</mat-form-field>\n\t\t\t\t<mat-input-container>\n\t\t\t\t\t<input matInput name=\"searchValue\" [(ngModel)]=\"searchValue\" placeholder=\"Id/Keyword\">\n\t\t\t\t</mat-input-container>\n\t\t\t\t<button (click)=\"search()\" mat-mini-fab>\n\t\t\t\t\t<mat-icon>search</mat-icon>\n\t\t\t\t</button>\n\t\t\t\t<button mat-mini-fab (click)=\"openNodeEditDialog()\">\n\t\t\t\t\t<mat-icon>add</mat-icon>\n\t\t\t\t</button>\n\t\t\t    <span fxFlex></span>\n\t\t\t\t<button mat-mini-fab (click)=\"graphexpSideMenu.toggle()\">\n\t\t\t      <mat-icon>menu</mat-icon>\n\t\t\t    </button>\n\t\t\t</mat-toolbar>\n\t\t\t<div class=\"sv-graphexp-content\">\n\t\t\t\t<div class=\"sv-graphexp-left-bar\">\n\t\t\t\t\t<div *ngIf=\"showGraphInfo\"><br/>\n\t\t\t\t\t\t<strong>Node Names</strong>\n\t\t\t\t\t\t<div *ngFor=\"let item of nodeNames | async\">\n\t\t\t\t\t\t\t{{item.key}}: {{item.value}}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"sv-graphexp-right-bar\">\n\t\t\t\t\t<strong>Selected Node</strong>\n\t\t\t\t\t\t<div *ngIf=\"selectedNode\">\n\t\t\t\t\t\t\t<div>Label: {{selectedNode.label}}</div>\n\t\t\t\t\t\t\t<div>Type: {{selectedNode.type}}</div>\n\t\t\t\t\t\t\t<div *ngFor=\"let prop of getFlattenedNodeProperties(selectedNode)\">\n\t\t\t\t\t\t\t\t<div>{{prop.name}}: {{prop.value}}</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"sv-graphexp\" id=\"sv_graphexp\">\n\t\t\t\t\t<svg></svg>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</mat-sidenav-container>\n</div>\n",
                styles: [".hidden{\n\tdisplay:none;\n}\n.sv-graphexp mat-sidenav-container{\n\twidth:100%;\n}\n.sv-graphexp mat-sidenav{\n\tpadding:1em;\n\twidth:25em;\n}\n.sv-graphexp mat-divider{\n\tpadding:5px 0;\n}\ndiv.sv-graphexp{\n\theight:100%;\n}\n.sv-graphexp-content{\n\tpadding:1em;\n\tposition:relative;\n\ttop:0;\n\theight:100%;\n}\n.sv-graphexp-left-bar{\n\tposition:absolute;\n\ttop:0;\n\twidth:10em;\n}\n.sv-graphexp-right-bar{\n\tposition:absolute;\n\ttop:0;\n\tright:0;\n\twidth:10em;\n}\npath.drag-line{\n    fill:none;\n    stroke:#333;\n    stroke-width:4px;\n    stroke-dasharray:5 5;\n    cursor:default;\n}\n.edge{\n\tstroke:#999;\n\tstroke-opacity:0.8;\n}\n.old_edge0{\n\tstroke:#999;\n\tstroke-opacity:0.6;\n}\n.node circle{\n\tstroke:#000;\n\tstroke-width:1.5px;\n}\n.node text{\n\tfont:10px sans-serif;\n}\n.node:hover circle{\n\tstroke-opacity:0.6;\n}\n.pinned circle{\n\tstroke:#000;\n\tstroke-width:1.5px;\n}\n.pinned text{\n\tfont:10px sans-serif;\n}\n.pinned:hover circle{\n\tstroke-opacity:0.6;\n}\n.old_node0 circle{\n\tstroke-opacity:0.9;\n}\n.old_node0 text{\n\tfont:10px sans-serif;\n\topacity:0.9;\n\tcolor:#000;\n\tcolor:rgba(0, 0, 0, 0.5);\n}\n.cell{\n\tfill:none;\n\tpointer-events:all;\n}"],
                encapsulation: ViewEncapsulation.None
            },] },
];
/** @nocollapse */
GraphexpComponent.ctorParameters = function () { return [
    { type: MatDialog, },
]; };
GraphexpComponent.propDecorators = {
    "graphexpService": [{ type: Input },],
    "graphConfig": [{ type: Input },],
};
/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes} checked by tsc
 */
var GraphexpModule = /** @class */ (function () {
    function GraphexpModule() {
    }
    return GraphexpModule;
}());
GraphexpModule.decorators = [
    { type: NgModule, args: [{
                imports: [
                    CommonModule,
                    FormsModule,
                    MatSidenavModule,
                    MatButtonModule,
                    MatIconModule,
                    MatFormFieldModule,
                    MatInputModule,
                    MatListModule,
                    MatSelectModule,
                    MatCheckboxModule,
                    MatToolbarModule,
                    MatSliderModule,
                    MatDialogModule,
                    FlexLayoutModule
                ],
                declarations: [GraphexpComponent, NodeEditComponent, LinkEditComponent],
                entryComponents: [NodeEditComponent, LinkEditComponent],
                providers: [],
                exports: [
                    GraphexpComponent,
                    GraphexpService,
                    GraphConfig,
                    CommonModule,
                    FormsModule,
                    MatSidenavModule,
                    MatButtonModule,
                    MatIconModule,
                    MatFormFieldModule,
                    MatInputModule,
                    MatListModule,
                    MatSelectModule,
                    MatCheckboxModule,
                    MatToolbarModule,
                    MatSliderModule,
                    MatDialogModule,
                    FlexLayoutModule
                ]
            },] },
];
/** @nocollapse */
GraphexpModule.ctorParameters = function () { return []; };
/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes} checked by tsc
 */
/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes} checked by tsc
 */
/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes} checked by tsc
 */
/**
 * Generated bundle index. Do not edit.
 */
export { GraphexpModule, GraphConfig, GraphexpComponent, GraphexpService, LinkEditComponent as ɵb, NodeEditComponent as ɵa };
//# sourceMappingURL=savantly-ngx-gremlin.js.map