first pass at choosing flows from the full list
diff --git a/web/ons-demo/js/app.js b/web/ons-demo/js/app.js
index e1f89e9..17189c2 100644
--- a/web/ons-demo/js/app.js
+++ b/web/ons-demo/js/app.js
@@ -15,7 +15,7 @@
});
var model;
-var svg, selectedFlowsView;
+var svg;
var updateTopology;
var pendingLinks = {};
@@ -68,26 +68,31 @@
attr('id', 'viewbox').append('svg:g').attr('transform', 'translate(500 500)');
}
-var selectedFlowsData = [
- {selected: false, flow: null},
- {selected: false, flow: null},
- {selected: false, flow: null}
-];
+var selectedFlows = [null, null, null];
function drawFlows() {
// DRAW THE FLOWS
- var flows = d3.select('svg').selectAll('.flow').data(selectedFlowsData, function (d) {
- return d.flow ? d.flow.flowId.value : null;
+ var flows = d3.select('svg').selectAll('.flow').data(selectedFlows, function (d) {
+ return d ? d.flowId.value : null;
});
- flows.enter().append("svg:path")
- .attr('class', 'flow')
- .attr('d', function (d) {
- if (!d.flow) {
+ flows.enter().append("svg:path").attr('class', 'flow')
+ .attr('stroke-dasharray', '4, 10')
+ .append('svg:animate')
+ .attr('attributeName', 'stroke-dashoffset')
+ .attr('attributeType', 'xml')
+ .attr('from', '500')
+ .attr('to', '-500')
+ .attr('dur', '20s')
+ .attr('repeatCount', 'indefinite');
+
+
+ flows.attr('d', function (d) {
+ if (!d) {
return;
}
var pts = [];
- d.flow.dataPath.flowEntries.forEach(function (flowEntry) {
+ d.dataPath.flowEntries.forEach(function (flowEntry) {
var s = d3.select(document.getElementById(flowEntry.dpid.value));
var pt = document.querySelector('svg').createSVGPoint();
pt.x = s.attr('x');
@@ -97,102 +102,111 @@
});
return line(pts);
})
- .attr('stroke-dasharray', '4, 10')
- .append('svg:animate')
- .attr('attributeName', 'stroke-dashoffset')
- .attr('attributeType', 'xml')
- .attr('from', '500')
- .attr('to', '-500')
- .attr('dur', '20s')
- .attr('repeatCount', 'indefinite');
-
- flows.style('visibility', function (d) {
- if (d) {
- return d.selected ? '' : 'hidden';
- }
- })
// "marching ants"
- // TODO: this will only be true if there's an iperf session running
- flows.select('animate').attr('from', function (d) {
- if (d.flow) {
- if (d.selected) {
- return '500';
- } else {
- return '-500';
- }
- }
- });
+ flows.select('animate').attr('from', 500);
+
+ flows.exit().remove();
}
-function updateFlowView() {
- selectedFlowsView.data(selectedFlowsData);
-
- selectedFlowsView.classed('selected', function (d) {
- if (d.flow) {
- return d.selected;
- }
- });
-
- selectedFlowsView.select('.flowId')
- .text(function (d) {
- if (d.flow) {
- return d.flow.flowId.value;
- }
- });
-
- selectedFlowsView.select('.srcDPID')
- .text(function (d) {
- if (d.flow) {
- return d.flow.dataPath.srcPort.dpid.value;
- }
- });
-
- selectedFlowsView.select('.dstDPID')
- .text(function (d) {
- if (d.flow) {
- return d.flow.dataPath.dstPort.dpid.value;
- }
- });
-}
-
-function createFlowView() {
- function rowEnter(d, i) {
+function showFlowChooser() {
+ function rowEnter(d) {
var row = d3.select(this);
- row.on('click', function () {
- selectedFlowsData[i].selected = !selectedFlowsData[i].selected;
- updateFlowView();
- drawFlows();
- });
-
row.append('div')
- .classed('flowIndex', true)
- .text(function () {
- return i+1;
+ .classed('eye', true).
+ on('click', function () {
+ selectedFlows.unshift(d);
+ selectedFlows = selectedFlows.slice(0, 3);
+
+ updateSelectedFlows();
+ updateTopology(svg, model);
});
row.append('div')
- .classed('flowId', true);
+ .classed('flowId', true)
+ .text(function (d) {
+ return d.flowId.value;
+ });
row.append('div')
- .classed('srcDPID', true);
+ .classed('srcDPID', true)
+ .text(function (d) {
+ return d.dataPath.srcPort.dpid.value;
+ });
+
row.append('div')
- .classed('dstDPID', true);
+ .classed('dstDPID', true)
+ .text(function (d) {
+ return d.dataPath.dstPort.dpid.value;
+ });
- row.append('div')
- .classed('iperf', true);
}
- var flows = d3.select('#selectedFlows')
+ var flows = d3.select('#flowChooser')
+ .append('div')
+ .style('pointer-events', 'auto')
.selectAll('.selectedFlow')
- .data(selectedFlowsData)
+ .data(model.flows)
.enter()
.append('div')
.classed('selectedFlow', true)
.each(rowEnter);
+ setTimeout(function () {
+ d3.select(document.body).on('click', function () {
+ d3.select('#flowChooser').html('');
+ d3.select(document.body).on('click', null);
+ });
+ }, 0);
+}
+
+function updateSelectedFlows() {
+ function rowEnter(d) {
+ var row = d3.select(this);
+ row.append('div').classed('flowId', true);
+ row.append('div').classed('srcDPID', true);
+ row.append('div').classed('dstDPID', true);
+ row.append('div').classed('iperf', true);
+ }
+
+ function rowUpdate(d) {
+ var row = d3.select(this);
+ row.select('.flowId')
+ .text(function (d) {
+ if (d) {
+ return d.flowId.value;
+ }
+ });
+
+ row.select('.srcDPID')
+ .text(function (d) {
+ if (d) {
+ return d.dataPath.srcPort.dpid.value;
+ }
+ });
+
+ row.select('.dstDPID')
+ .text(function (d) {
+ if (d) {
+ return d.dataPath.dstPort.dpid.value;
+ }
+ });
+ }
+
+ var flows = d3.select('#selectedFlows')
+ .selectAll('.selectedFlow')
+ .data(selectedFlows);
+
+ flows.enter()
+ .append('div')
+ .classed('selectedFlow', true)
+ .each(rowEnter);
+
+ flows.each(rowUpdate);
+
+ flows.exit().remove();
return flows;
}
@@ -833,7 +847,7 @@
return d;
})
.append('div')
- .attr('class', 'controllerEye');
+ .attr('class', 'eye');
controllers.attr('class', function (d) {
var color = 'colorInactive';
@@ -863,7 +877,7 @@
}
});
- controllers.select('.controllerEye').on('click', function (c) {
+ controllers.select('.eye').on('click', function (c) {
var allSelected = true;
for (var key in controllerColorMap) {
if (!d3.select(document.body).classed(controllerColorMap[key] + '-selected')) {
@@ -888,23 +902,14 @@
}
-function sync(svg, selectedFlowsView) {
+function sync(svg) {
var d = Date.now();
updateModel(function (newModel) {
// console.log('Update time: ' + (Date.now() - d)/1000 + 's');
if (!model || JSON.stringify(model) != JSON.stringify(newModel)) {
updateControllers(newModel);
-
- // fake flows right now
- var i;
- for (i = 0; i < newModel.flows.length && i < selectedFlowsData.length; i+=1) {
- var selected = selectedFlowsData[i] ? selectedFlowsData[i].selected : false;
- selectedFlowsData[i].flow = newModel.flows[i];
- selectedFlowsData[i].selected = selected;
- }
-
- updateFlowView(newModel);
+ updateSelectedFlows();
updateTopology(svg, newModel);
} else {
// console.log('no change');
@@ -921,7 +926,12 @@
}
svg = createTopologyView();
-selectedFlowsView = createFlowView();
+updateSelectedFlows();
+
+d3.select('#showFlowChooser').on('click', function () {
+ showFlowChooser();
+});
+
// workaround for Chrome v25 bug
// if executed immediately, the view box transform logic doesn't work properly
@@ -931,5 +941,5 @@
// viewbox transform stuff doesn't work in combination with browser zoom
// also works in Chrome v27
d3.select('#svg-container').style('zoom', window.document.body.clientWidth/window.document.width);
- sync(svg, selectedFlowsView);
+ sync(svg);
}, 100);