From 1fff14f0a5e25adaa851537c71c7bd8381c1bbb1 Mon Sep 17 00:00:00 2001 From: Koren Lev Date: Mon, 2 Oct 2017 11:37:03 +0300 Subject: ui move to docker Change-Id: Iff31ebb3fff782e848704801b7800fdf480264a1 Signed-off-by: Koren Lev (cherry picked from commit a9691f5fe78af32c474754f841a71a68e2d2a484) --- .../ui/components/network-graph/network-graph.js | 803 --------------------- 1 file changed, 803 deletions(-) delete mode 100644 ui/imports/ui/components/network-graph/network-graph.js (limited to 'ui/imports/ui/components/network-graph/network-graph.js') diff --git a/ui/imports/ui/components/network-graph/network-graph.js b/ui/imports/ui/components/network-graph/network-graph.js deleted file mode 100644 index 04b69e3..0000000 --- a/ui/imports/ui/components/network-graph/network-graph.js +++ /dev/null @@ -1,803 +0,0 @@ -/* - * Template Component: NetworkGraph - */ - -//import { Meteor } from 'meteor/meteor'; -import { Template } from 'meteor/templating'; -import { ReactiveDict } from 'meteor/reactive-dict'; -import { SimpleSchema } from 'meteor/aldeed:simple-schema'; -import * as R from 'ramda'; -import * as cola from 'webcola'; -import { imagesForNodeType, defaultNodeTypeImage } from '/imports/lib/images-for-node-type'; -import * as _ from 'lodash'; - -import './network-graph.html'; - -/* - * Lifecycles - */ - -Template.NetworkGraph.onCreated(function() { - let instance = this; - - instance.state = new ReactiveDict(); - instance.state.setDefault({ - graphDataChanged: null, - }); - instance.simpleState = { - graphData: null - }; - instance.prevForce = null; - - instance.autorun(function () { - let data = Template.currentData(); - - new SimpleSchema({ - graphData: { type: Object, blackbox: true }, - onNodeOver: { type: Function, optional: true }, - onNodeOut: { type: Function, optional: true }, - onNodeClick: { type: Function, optional: true }, - onDragStart: { type: Function, optional: true }, - onDragEnd: { type: Function, optional: true }, - onGroupOver: { type: Function, optional: true }, - onLinkOver: { type: Function, optional: true }, - }).validate(data); - - instance.simpleState.graphData = data.graphData; - instance.state.set('graphDataChanged', Date.now()); - instance.onNodeOver = R.defaultTo(() => {}, data.onNodeOver); - instance.onNodeOut = R.defaultTo(() => {}, data.onNodeOut); - instance.onNodeClick = R.defaultTo(() => {}, data.onNodeClick); - instance.onDragStart = R.defaultTo(() => {}, data.onDragStart); - instance.onDragEnd = R.defaultTo(() => {}, data.onDragEnd); - instance.onGroupOver = R.defaultTo(() => {}, data.onGroupOver); - instance.onLinkOver = R.defaultTo(() => {}, data.onLinkOver); - }); -}); - -Template.NetworkGraph.rendered = function() { - let instance = Template.instance(); - - instance.autorun(function () { - //let _graphDataChanged = - instance.state.get('graphDataChanged'); - let graphEl = instance.$('.sm-graph')[0]; - - renderGraph(graphEl, - graphEl.clientWidth, - graphEl.clientHeight, - instance.simpleState.graphData, - genConfig(), - instance.onNodeOver, - instance.onNodeOut, - instance.onNodeClick, - instance.onDragStart, - instance.onDragEnd, - instance.onGroupOver, - instance.onLinkOver, - function onNewForce(newForce) { - if (instance.prevForce) { - instance.prevForce.stop(); - } - instance.prevForce = newForce; - } - ); - }); -}; - -Template.NetworkGraph.onDestroyed(function () { - let instance = Template.instance(); - let graphEl = instance.$('.sm-graph')[0]; - let svg = d3.select(graphEl).select('svg'); - if (instance.prevForce) { - instance.prevForce.stop(); - } - - svg.remove(); -}); -/* - * Events - */ - -Template.NetworkGraph.events({ -}); - -/* - * Helpers - */ - -Template.NetworkGraph.helpers({ -}); // end: helpers - - -function genConfig() { - let outline = false; - let tocolor = 'fill'; - let towhite = 'stroke'; - if (outline) { - tocolor = 'stroke'; - towhite = 'fill'; - } - - return { - initialLinkLabelsFontSize: 18, - tocolor: tocolor, - towhite: towhite, - text_center: false, - outline: outline, - min_score: 0, - max_score: 1, - highlight_color: 'blue', - highlight_trans: 0.1, - default_node_color: '#ccc', - //var default_node_color: 'rgb(3,190,100)', - default_link_color: '#888', - nominal_base_node_size: 8, - nominal_text_size: 10, - max_text_size: 24, - nominal_stroke: 1.5, - max_stroke: 4.5, - max_base_node_size: 36, - min_zoom: 0.3, - max_zoom: 5, - }; -} - -function renderGraph( - mainElement, - w, - h, - graph, - config, - onNodeOver, - onNodeOut, - onNodeClick, - onDragStart, - onDragEnd, - onGroupOver, - onLinkOver, - onNewForce -) { - - let force = genForceCola(cola, d3, w, h); - onNewForce(force); - - let drag = force.drag() - .on('start', function (_d) { - onDragStart(); - }) - .on('end', function (_d) { - onDragEnd(); - }) - ; - - let svg = d3.select(mainElement).select('svg'); - svg.remove(); - svg = genSvg(d3, mainElement); - - let zoom = genZoomBehavior(d3, config); - svg.call(zoom); - - let mainEl = svg.append('g'); - let groupsEl = mainEl.append('g').attr('class', 'groups-container'); - let linksEl = mainEl.append('g').attr('class', 'links-container'); - let nodesEl = mainEl.append('g').attr('class', 'nodes-container'); - - renderView(force, { - graph: graph, - viewGraph: { - nodes: [], - links: [], - groups: [] - }, - }, - mainEl, - groupsEl, - nodesEl, - linksEl, - drag, zoom, config, - onNodeOver, - onNodeOut, - onNodeClick, - onGroupOver, - onLinkOver - ); -} - -// d3.select(window).on('resize', resize); - -function genSvg(d3, mainElement) { - let svg = d3.select(mainElement).append('svg'); - - svg.style('cursor', 'move') - .attr('width', '100%') - .attr('height', '100%') - .attr('pointer-events', 'all'); - - return svg; -} - -function genSvgLinks( - g, - links, - nominal_stroke, - default_link_color, - initialLinkLabelsFontSize, - onLinkOver -) { - let svgLinks = g.selectAll('.link-group') - .data(links, (d) => d._osid); - - let svgLinksEnter = svgLinks - .enter() - .append('g') - .attr('class', 'link-group') - .attr('data-link-id', function (d) { - return d._osid; - }) - ; - - //let svgLinksExit = - svgLinks - .exit().remove(); - - let svgLinkLines = svgLinksEnter - .append('line') - .attr('class', 'link-line') - .style('stroke-width', nominal_stroke) - .style('stroke', - function(d) { - let status = R.defaultTo('', R.path(['_osmeta', 'status'], d)); - status = _.toLower(status); - switch(status) { - case 'ok': - return 'green'; - case 'warning': - return 'orange'; - case 'error': - return 'red'; - default: - return default_link_color; - } - }) - .on('mouseover', function (d) { - onLinkOver(d._osmeta.linkId, d3.event.pageX, d3.event.pageY); - }) - ; - - let svgLinkLabels = svgLinksEnter - .append('text') - .text(function(d) { - return d.label; - }) - .attr('class', 'link-label') - .attr('x', function(d) { return (d.source.x + (d.target.x - d.source.x) * 0.5); }) - .attr('y', function(d) { return (d.source.y + (d.target.y - d.source.y) * 0.5); }) - .attr('dy', '.25em') - .attr('text-anchor', 'right') - .attr('font-size', initialLinkLabelsFontSize) - ; - - return {svgLinks, svgLinkLines, svgLinkLabels}; -} - -function genSvgNodes(g, nodes, drag, onNodeOver, onNodeOut, onNodeClick, onGroupNodeClick) { - let svgNodes = g.selectAll('.node') - .data(nodes, (d) => d._osid); - - let svgNodesEnter = svgNodes - .enter() - .append('g') - .attr('class', 'node') - .attr('data-node-id', (d) => d._osid) - .call(drag); - - //let svgNodesExit = - svgNodes - .exit().remove(); - - let imageLength = 36; - let svgImages = svgNodesEnter.append('image') - .attr('class', 'node-image') - .attr('xlink:href', function(d) { - let status = R.defaultTo('', R.path(['_osmeta', 'status'], d)); - status = _.toLower(status); - return `/${calcImageForNodeType(d._osmeta.type, status)}`; - }) - .attr('x', -(Math.floor(imageLength / 2))) - .attr('y', -(Math.floor(imageLength / 2))) - .attr('width', imageLength) - .attr('height', imageLength) - .on('mouseover', function (d) { - onNodeOver(d._osmeta.nodeId, d3.event.pageX, d3.event.pageY); - }) - .on('mouseout', function (d) { - onNodeOut(d._osmeta.nodeId); - }) - .on('click', function (d) { - let type = R.defaultTo('', R.path(['_osmeta', 'type'], d)); - if (R.contains(type, ['view_group-host', 'view_group-switch'])) { - onGroupNodeClick(d._osmeta.nodeId); - } - onNodeClick(d._osmeta.nodeId); - }) - ; - - return {svgNodes, svgImages}; - //return [svgNodes]; -} - -function calcImageForNodeType(nodeType, status) { - let image = R.defaultTo(defaultNodeTypeImage, R.prop(nodeType, imagesForNodeType)); - if (typeof image === 'object') { - image = R.defaultTo(image.default, image[status]); - } - - return image; -} - -function genZoomBehavior(d3, config) { - let zoom = d3.zoom().scaleExtent([config.min_zoom, config.max_zoom]); - - return zoom; -} - -/* -function genForceD3(d3, w, h) { - let force = d3.layout.force() - .linkDistance(60) - .charge(-300) - .size([w,h]); - - return force; -} -*/ - -function genForceCola(cola, d3, w, h) { - let force = cola.d3adaptor(d3) - .convergenceThreshold(0.1) - //.convergenceThreshold(1e-9) - .linkDistance(120) - .size([w,h]); - - return force; -} - -function activateForce(force, nodes, links, groups) { - force - .nodes(nodes) - .links(links) - .groups(groups) - //.symmetricDiffLinkLengths(25) - .handleDisconnected(true) - .avoidOverlaps(true) - .start(50, 100, 200); - //.start(); -} - -/* -function resize() { - let width = mainElement.clientWidth; - let height = mainElement.clientHeight; - - svg.attr('width', '100%') //width) - .attr('height', '100%'); //height); - - force.size([ - force.size()[0] + (width - w) / zoom.scale(), - force.size()[1] + (height - h) / zoom.scale() - ]).resume(); - - w = width; - h = height; -} -*/ - -function renderView(force, - state, - mainEl, - groupsEl, - nodesEl, - linksEl, - drag, - zoom, - config, - onNodeOver, - onNodeOut, - onNodeClick, - onGroupOver, - onLinkOver -) { - - state.viewGraph = calcViewGraph(state.graph, state.viewGraph); - - activateForce(force, state.viewGraph.nodes, state.viewGraph.links, state.viewGraph.groups); - - zoom.on('zoom', zoomFn); - - genSvgGroups(groupsEl, state.viewGraph.groups, drag, onRenderViewReq, onGroupOver); - - genSvgLinks( - linksEl, state.viewGraph.links, - config.nominal_stroke, - config.default_link_color, - config.initialLinkLabelsFontSize, - onLinkOver - ); - - genSvgNodes( - nodesEl, state.viewGraph.nodes, drag, onNodeOver, onNodeOut, onNodeClick, - function onGroupNodeClick(groupId) { - let group = R.find(R.propEq('_osid', groupId), state.graph.groups); - group.isExpanded = true; - - state.viewGraph = renderView(force, state, - mainEl, groupsEl, nodesEl, linksEl, - drag, zoom, config, - onNodeOver, onNodeOut, onNodeClick, onGroupOver, onLinkOver); - }); - - force.on('tick', tickFn); - - function onRenderViewReq() { - state.viewGraph = renderView(force, state, - mainEl, groupsEl, nodesEl, linksEl, - drag, zoom, config, - onNodeOver, onNodeOut, onNodeClick, onGroupOver, onLinkOver); - } - - function tickFn() { - let svgGroups = mainEl.selectAll('.group'); - svgGroups - .attr('transform', function (d) { - let x = R.path(['bounds', 'x'], d); - let y = R.path(['bounds', 'y'], d); - return `translate(${x},${y})`; - }) - ; - /* - .attr('x', function (d) { - return R.path(['bounds', 'x'], d); - }) - .attr('y', function (d) { - return R.path(['bounds', 'y'], d); - }) - */ - - svgGroups.selectAll('.group-shape') - .attr('width', function (d) { - if (d.bounds) { return d.bounds.width(); } - }) - .attr('height', function (d) { - if (d.bounds) { return d.bounds.height(); } - }); - - svgGroups.selectAll('.group-name') - .attr('x', function(d) { - return (d.bounds.width() / 2); - }) - .attr('y', function(_d) { - return 30; - }) - ; - - let svgNodes = mainEl.selectAll('.node'); - svgNodes.attr('transform', function(d) { - return 'translate(' + d.x + ',' + d.y + ')'; - }); - - let svgLinkLines = mainEl.selectAll('.link-group').selectAll('.link-line'); - svgLinkLines - .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; }); - - let svgLinkLabels = mainEl.selectAll('.link-group').selectAll('.link-label'); - svgLinkLabels - .attr('x', function(d) { - return (d.source.x + (d.target.x - d.source.x) * 0.5); - }) - .attr('y', function(d) { - return (d.source.y + (d.target.y - d.source.y) * 0.5); - }); - - } - - function zoomFn() { - mainEl.attr('transform', d3.event.transform); - - let trn = d3.event.transform; - - let maxZoomAllowedForNodes = 1.8; - let imageInitialLength = 36; - let imageLength; - - if (trn.k > maxZoomAllowedForNodes) { - imageLength = (imageInitialLength / trn.k) * maxZoomAllowedForNodes; - } else { - imageLength = imageInitialLength; - } - - let svgImages = mainEl.selectAll('.node-image'); - svgImages - .attr('x', -(Math.floor(imageLength / 2))) - .attr('y', -(Math.floor(imageLength / 2))) - .attr('width', imageLength) - .attr('height', imageLength) - ; - - let labelsFontSize; - - if (trn.k > maxZoomAllowedForNodes) { - labelsFontSize = (config.initialLinkLabelsFontSize / trn.k) * maxZoomAllowedForNodes; - } else { - labelsFontSize = config.initialLinkLabelsFontSize; - } - - let svgLinkLabels = mainEl.selectAll('.link-group').selectAll('.link-label'); - svgLinkLabels - .attr('font-size', labelsFontSize); - } - - return state.viewGraph; -} - -function genSvgGroups(g, groups, drag, onRenderViewReq, onGroupOver) { - let svgGroups = g.selectAll('.group') - .data(groups, (d) => d._osid); - - let enterGroups = svgGroups.enter(); - - let groupsContainers = - enterGroups - .append('g') - .attr('class', 'group') - .attr('data-group-id', (d) => d._osid) - .call(drag) - .on('mouseover', function (_d) { - onGroupOver(); - }) - .on('click', function (d) { - console.log('click', d); - d.isExpanded = !d.isExpanded; - onRenderViewReq(); - }); - - groupsContainers - .append('rect') - .attr('class', 'group-shape') - .attr('rx', 8) - .attr('ry', 8) - .style('fill', function (_d, _i) { return 'lightblue'; }) - ; - - groupsContainers - .append('text') - .text(function(d) { - return d.name; - }) - .attr('class', 'group-name') - .attr('x', function(d) { - return (d.bounds.width() / 2); - }) - .attr('y', function(_d) { - return 30; - }) - .attr('dy', '.25em') - .attr('text-anchor', 'middle') - .attr('font-size', 20) - ; - - svgGroups.exit() - .remove(); - - return svgGroups; -} -function calcViewGraph(graph, prevViewGraph) { - let {groups, rejectedGroups} = calcGroupsAndRejectedGroups(graph.groups); - let newClosedGroupNodes = calcClosedGroupsNodes(rejectedGroups, prevViewGraph.nodes); - let {nodes, rejectedNodes} = calcNodesAndRejectedNodes(graph.nodes, graph.groups); - nodes = R.concat(newClosedGroupNodes, nodes); - - let {links, rejectedSourceLinks, rejectedTargetLinks, rejectedBothLinks} = - calcLinksAndRejectedLinks(graph.links, rejectedNodes); - - let newLinksForRejectedSource = - calcNewLinksForRejectedSource(rejectedSourceLinks, nodes, prevViewGraph.links); - - let newLinksForRejectedTarget = - calcNewLinksForRejectedTarget(rejectedTargetLinks, nodes, prevViewGraph.links); - - let newLinksForRejectedBoth = - calcNewLinksForRejectedBoth(rejectedBothLinks, nodes, prevViewGraph.links); - - links = R.pipe( - R.concat(newLinksForRejectedSource), - R.concat(newLinksForRejectedTarget), - R.concat(newLinksForRejectedBoth) - )(links); - - return { - nodes, - links, - groups - }; -} - -function calcGroupsAndRejectedGroups(originalGroups) { - let rejectedGroups = R.filter(R.propEq('isExpanded', false), originalGroups); - let groups = R.reject(R.propEq('isExpanded', false), originalGroups); - - return { groups, rejectedGroups }; -} - -function calcClosedGroupsNodes(rejectedGroups, prevViewNodes) { - return R.reduce((acc, group) => { - let nodeId = `${group._osid}-group-node`; - let prevNode = R.find(R.propEq('_osid', nodeId), prevViewNodes); - if (prevNode) { - return R.append(prevNode, acc); - } - - return R.append({ - _osid: nodeId, - _osmeta: { - type: `view_group-${group.type}`, - nodeId: group._osid, - }, - width: 60, - height: 40, - name: group._osid - }, acc); - }, [], rejectedGroups); -} - -function calcNodesAndRejectedNodes(originalNodes, originalGroups) { - let rejectedNodes = []; - let nodes = R.reject((node) => { - let groupId = R.path(['_osmeta', 'groupId'], node); - if (R.isNil(groupId)) { return false; } - - let group = R.find(R.propEq('_osid', groupId), originalGroups); - if (R.isNil(group)) { return false; } - - if (group.isExpanded) { return false; } - - rejectedNodes = R.append(node, rejectedNodes); - return true; - }, originalNodes); - - return { nodes, rejectedNodes }; -} - -function calcLinksAndRejectedLinks(originalLinks, rejectedNodes) { - return R.reduce((acc, link) => { - let sourceRejected = R.contains(link.source, rejectedNodes); - let targetRejected = R.contains(link.target, rejectedNodes); - - if (sourceRejected && targetRejected) { - acc = R.assoc('rejectedBothLinks', R.append(link, acc.rejectedBothLinks), acc); - return acc; - } - - if (sourceRejected) { - acc = R.assoc('rejectedSourceLinks', R.append(link, acc.rejectedSourceLinks), acc); - return acc; - } - - if (targetRejected) { - acc = R.assoc('rejectedTargetLinks', R.append(link, acc.rejectedTargetLinks), acc); - return acc; - } - - acc = R.assoc('links', R.append(link, acc.links), acc); - return acc; - }, - {links: [], rejectedSourceLinks: [], rejectedTargetLinks: [], rejectedBothLinks: [] }, - originalLinks); -} - -function calcNewLinksForRejectedSource(rejectedSourceLinks, nodes, prevLinks) { - let newLinksForRejectedSource = R.reduce((acc, link) => { - let groupId = R.path(['_osmeta', 'groupId'], link.source); - let groupNodeId = `${groupId}-group-node`; - let newSource = R.find(R.propEq('_osid', groupNodeId), nodes); - if (R.isNil(newSource)) { - throw 'error in new links for rejected source function'; - } - - let newLinkId = `${newSource._osid}:${link.target._osid}:rejected-source`; - - let existingLink = R.find(R.propEq('_osid', newLinkId), acc); - if (existingLink) { - return acc; - } - - let prevExistingLink = R.find(R.propEq('_osid', newLinkId), prevLinks); - if (prevExistingLink) { - return R.append(prevExistingLink, acc); - } - - return R.append({ - source: newSource , - target: link.target, - label: link.label, - _osid: newLinkId - }, acc); - }, [], rejectedSourceLinks); - - return newLinksForRejectedSource; -} - -function calcNewLinksForRejectedTarget(rejectedLinks, nodes, prevLinks) { - let newLinks = R.reduce((acc, link) => { - let groupId = R.path(['_osmeta', 'groupId'], link.target); - let groupNodeId = `${groupId}-group-node`; - let newTarget = R.find(R.propEq('_osid', groupNodeId), nodes); - if (R.isNil(newTarget)) { - throw 'error in new links for rejected target function'; - } - - let newLinkId = `${link.source._osid}:${newTarget._osid}:rejected-target`; - - let existingLink = R.find(R.propEq('_osid', newLinkId), acc); - if (existingLink) { - return acc; - } - - let prevExistingLink = R.find(R.propEq('_osid', newLinkId), prevLinks); - if (prevExistingLink) { - return R.append(prevExistingLink, acc); - } - - return R.append({ - source: link.source , - target: newTarget, - label: link.label, - _osid: newLinkId - }, acc); - }, [], rejectedLinks); - - return newLinks; -} - -function calcNewLinksForRejectedBoth(rejectedLinks, nodes, prevLinks) { - let newLinks = R.reduce((acc, link) => { - let targetHost = R.path(['_osmeta', 'groupId'], link.target); - let sourceHost = R.path(['_osmeta', 'groupId'], link.source); - let groupSourceNodeId = `${sourceHost}-group-node`; - let groupTargetNodeId = `${targetHost}-group-node`; - - if (targetHost === sourceHost) { - return acc; - } - - let newLinkId = `${sourceHost}:${targetHost}:groups-link`; - let existingNewLink = R.find(R.propEq('_osid', newLinkId), acc); - if (existingNewLink) { - return acc; - } - - let prevExistingLink = R.find(R.propEq('_osid', newLinkId), prevLinks); - if (prevExistingLink) { - return R.append(prevExistingLink, acc); - } - - let newSource = R.find(R.propEq('_osid', groupSourceNodeId), nodes); - let newTarget = R.find(R.propEq('_osid', groupTargetNodeId), nodes); - - let newLink = { - source: newSource, - target: newTarget, - label: 'hosts link', - _osid: newLinkId - }; - - return R.append(newLink, acc); - }, [], rejectedLinks); - - return newLinks; -} -- cgit 1.2.3-korg