diff options
Diffstat (limited to 'client/partials/graph.html')
| -rw-r--r-- | client/partials/graph.html | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/client/partials/graph.html b/client/partials/graph.html new file mode 100644 index 0000000..a3274eb --- /dev/null +++ b/client/partials/graph.html @@ -0,0 +1,203 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <link rel="stylesheet" href="../vendors/jointjs/css/joint.min.css" /> + <script src="../vendors/jointjs/dependencies/jquery.min.js"></script> + <script src="../vendors/jointjs/dependencies//lodash.min.js"></script> + <script src="../vendors/jointjs/dependencies/backbone-min.js"></script> + <script src="../vendors/jointjs/js/joint.min.js"></script> + <script src="../vendors/jointjs/lib/dagre.min.js"></script> + <script src="../vendors/jointjs/lib/graphlib.min.js"></script> + <script src="../vendors/jointjs/plugins/joint.layout.DirectedGraph.min.js"></script> + <link rel="stylesheet" type="text/css" href="../css/graph.css" /> +</head> +<body> + <div id="graphHolder"></div> + + <script type="text/javascript"> + + //adjacencyList, hard-encoded now but will be the result of a request to the server, format may change + var vmList = { + 'vms': [ + 'VM 1', + 'VM 2', + 'VM 3', + 'VM 4', + 'VM 5', + 'VM 6', + 'VM 7', + 'VM 8', + 'VM 9', + 'VM 10' + ], + 'links': [ + ['VM 1', 'VM 2', 'I1', 'I2'], + ['VM 2', 'VM 3', 'I3', 'I4'], + ['VM 1', 'VM 3', 'I5', 'I6'], + ['VM 2', 'VM 4', 'I5', 'I6'], + ['VM 4', 'VM 5', 'I5', 'I6'], + ['VM 4', 'VM 6', 'I5', 'I6'], + ['VM 4', 'VM 1', 'I5', 'I6'], + ['VM 7', 'VM 4', 'I5', 'I6'], + ['VM 7', 'VM 3', 'I5', 'I6'], + ['VM 6', 'VM 8', 'I5', 'I6'], + ['VM 3', 'VM 9', 'I5', 'I6'], + ['VM 3', 'VM 10', 'I5', 'I6'] + ] + }; + + + //Custom element for inserting html + joint.shapes.html = {}; + joint.shapes.html.Element = joint.shapes.basic.Rect.extend({ + defaults: joint.util.deepSupplement({ + type: 'html.Element', + attrs: { + rect: { stroke: 'none', 'fill-opacity': 0 } + } + }, joint.shapes.basic.Rect.prototype.defaults) + }); + + //Custom view for this element + joint.shapes.html.ElementView = joint.dia.ElementView.extend({ + + initialize: function() { + _.bindAll(this, 'updateBox'); + joint.dia.ElementView.prototype.initialize.apply(this, arguments); + + this.$box = $(_.template(this.model.get('html'))()); + // Prevent paper from handling pointerdown. + this.$box.find('input,select').on('mousedown click', function(evt) { evt.stopPropagation(); }); + // This is an example of reacting on the input change and storing the input data in the cell model. + this.$box.find('input').on('change', _.bind(function(evt) { + this.model.set('input', $(evt.target).val()); + }, this)); + this.$box.find('select').on('change', _.bind(function(evt) { + this.model.set('select', $(evt.target).val()); + }, this)); + this.$box.find('select').val(this.model.get('select')); + //this.$box.find('.config').on('click', CALL OVERLAY HERE); + // Update the box position whenever the underlying model changes. + this.model.on('change', this.updateBox, this); + // Remove the box when the model gets removed from the graph. + this.model.on('remove', this.removeBox, this); + + this.updateBox(); + }, + render: function() { + joint.dia.ElementView.prototype.render.apply(this, arguments); + this.paper.$el.prepend(this.$box); + this.updateBox(); + return this; + }, + updateBox: function() { + // Set the position and dimension of the box so that it covers the JointJS element. + var bbox = this.model.getBBox(); + // Example of updating the HTML with a data stored in the cell model. + this.$box.find('label').text(this.model.get('name')); + this.$box.find('span').text(this.model.get('select')); + this.$box.css({ width: bbox.width, height: bbox.height, left: bbox.x, top: bbox.y, transform: 'rotate(' + (this.model.get('angle') || 0) + 'deg)' }); + }, + removeBox: function(evt) { + this.$box.remove(); + } + }); + + + //Read the adjacencyList and build the elements and the links according to it + function buildGraphFromAdjacencyList(adjacencyList) { + + var elements = []; + var links = []; + + _.each(adjacencyList['vms'], function(vm) { + elements.push(makeElement(vm)); + }); + + _.each(adjacencyList['links'], function(link) { + links.push(makeLink(link[0], link[1] , link[2], link[3])); + }); + + // Links must be added after all the elements. This is because when the links + // are added to the graph, link source/target + // elements must be in the graph already. + return elements.concat(links); + } + + //Return a new link linking the parent and child elements with the interfaces names given in parameters + function makeLink(parentElementLabel, childElementLabel, Iparent, Ichild) { + + return new joint.dia.Link({ + source: { id: parentElementLabel }, + target: { id: childElementLabel }, + labels: [ + { position: 20, attrs: { text: { text: Iparent } }}, + { position: -20, attrs: { text: { text: Ichild } }} + ] + }); + } + + //Return a new element + function makeElement(label) { + + var maxLineLength = _.max(label.split('\n'), function(l) { return l.length; }).length; + + // Compute width/height of the rectangle based on the number + // of lines in the label and the letter size. 0.6 * letterSize is + // an approximation of the monospace font letter width. + var width = 130; + var height = 80; + + return new joint.shapes.html.Element({ + id: label, + name: label, + size: { width: width, height: height }, + + html: [ + '<div class="html-element">', + '<img src="../images/ON.png">', + '<label></label>', + '<input type="image" src="../images/gear.png" class="config"></button>', + '</div>' + ].join(''), + + attrs: { + rect: { + fill: '#FE854F', + width: width, + height: height, + rx: 5, + ry: 5, + stroke: 'none' + } + } + }); + } + + var graph = new joint.dia.Graph; + + var paper = new joint.dia.Paper({ + el: $('#graphHolder'), + width: 2000, + height: 2000, + model: graph, + gridSize: 1 + }); + + paper.$el.css('pointer-events', 'none'); + + var cells = buildGraphFromAdjacencyList(vmList); + graph.resetCells(cells); + joint.layout.DirectedGraph.layout(graph, { + setLinkVertices: false, + //Top to bottom generation + rankDir: "TB", + nodeSep: 150, + edgeSep: 150, + rankSep: 150 + }); + + </script> +</body> +</html>
\ No newline at end of file |
