blob: f5fb68d1c83bf095ed0feb2c48ea18329a8e3cc7 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Ember from 'ember';
import ChartUtilsMixin from 'yarn-ui/mixins/charts-utils';
export default Ember.Component.extend(ChartUtilsMixin, {
queues: {
data: undefined,
foldedQueues: {},
selectedQueueCircle: undefined,
maxDepth: -1,
},
queueColors: d3.scale.category20().range(),
renderQueue: function (now, depth, sequence) {
if (depth > this.queues.maxDepth) {
this.queues.maxDepth = depth;
}
var cx = 20 + depth * 30;
var cy = 20 + sequence * 30;
var name = now.get("name");
var g = this.queues.dataGroup.append("g")
.attr("id", "queue-" + name + "-g");
var folded = this.queues.foldedQueues[name];
var isParentQueue = false;
// render its children
var children = [];
var childrenNames = now.get("children");
if (childrenNames) {
childrenNames.forEach(function (name) {
isParentQueue = true;
var child = this.queues.data[name];
if (child) {
children.push(child);
}
}.bind(this));
}
if (folded) {
children = [];
}
var linefunction = d3.svg.line()
.interpolate("basis")
.x(function (d) {
return d.x;
})
.y(function (d) {
return d.y;
});
for (var i = 0; i < children.length; i++) {
sequence = sequence + 1;
// Get center of children queue
var cc = this.renderQueue(children[i],
depth + 1, sequence);
g.append("path")
.attr("class", "queue")
.attr("d", linefunction([{
x: cx,
y: cy
}, {
x: cc.x - 20,
y: cc.y
}, cc]));
}
var circle = g.append("circle")
.attr("cx", cx)
.attr("cy", cy)
.attr("class", "queue");
circle.on('mouseover', function () {
}.bind(this));
circle.on('mouseout', function () {
if (circle !== this.queues.selectedQueueCircle) {
circle.style("fill", this.queueColors[0]);
}
}.bind(this));
circle.on('click', function () {
circle.style("fill", this.queueColors[2]);
var pre = this.queues.selectedQueueCircle;
this.queues.selectedQueueCircle = circle;
if (pre) {
pre.on('mouseout')();
}
this.renderCharts(name);
}.bind(this));
circle.on('dblclick', function () {
if (!isParentQueue) {
return;
}
if (this.queues.foldedQueues[name]) {
delete this.queues.foldedQueues[name];
} else {
this.queues.foldedQueues[name] = now;
}
this.renderQueues();
}.bind(this));
var text = name;
if (folded) {
text = name + " (+)";
}
// print queue's name
g.append("text")
.attr("x", cx + 30)
.attr("y", cy + 5)
.text(text)
.attr("class", "queue");
return {
x: cx,
y: cy
};
},
renderQueues: function () {
if (this.queues.dataGroup) {
this.queues.dataGroup.remove();
}
// render queues
this.queues.dataGroup = this.canvas.svg.append("g")
.attr("id", "queues-g");
if (this.queues.data) {
this.renderQueue(this.queues.data['root'], 0, 0);
}
},
draw: function () {
this.queues.data = {};
this.get("model")
.forEach(function (o) {
this.queues.data[o.id] = o;
}.bind(this));
// get w/h of the svg
var bbox = d3.select("#main-container")
.node()
.getBoundingClientRect();
this.canvas.w = bbox.width;
this.canvas.h = Math.max(Object.keys(this.queues.data)
.length * 35, 1500);
this.canvas.svg = d3.select("#main-container")
.append("svg")
.attr("width", this.canvas.w)
.attr("height", this.canvas.h)
.attr("id", "main-svg");
this.renderBackground();
this.renderQueues();
this.renderCharts("root");
},
didInsertElement: function () {
this.draw();
},
/*
* data = [{label="xx", value=},{...}]
*/
renderTable: function (data) {
d3.select("#main-svg")
.append('table')
.selectAll('tr')
.data(data)
.enter()
.append('tr')
.selectAll('td')
.data(function (d) {
return d;
})
.enter()
.append('td')
.text(function (d) {
return d;
});
},
renderQueueCapacities: function (queue, layout) {
// Render bar chart
this.renderCells(this.charts.g, [{
label: "Cap",
value: queue.get("capacity")
}, {
label: "MaxCap",
value: queue.get("maxCapacity")
}, {
label: "UsedCap",
value: queue.get("usedCapacity")
}], "Queue Capacities", layout, 60);
},
renderChildrenCapacities: function (queue, layout) {
var data = [];
var children = queue.get("children");
if (children) {
for (var i = 0; i < children.length; i++) {
var child = this.queues.data[children[i]];
data.push({
label: child.get("name"),
value: child.get("capacity")
});
}
}
this.renderDonutChart(this.charts.g, data, "Children Capacities", layout, true);
},
renderChildrenUsedCapacities: function (queue, layout) {
var data = [];
var children = queue.get("children");
if (children) {
for (var i = 0; i < children.length; i++) {
var child = this.queues.data[children[i]];
data.push({
label: child.get("name"),
value: child.get("usedCapacity")
});
}
}
this.renderDonutChart(this.charts.g, data, "Children Used Capacities", layout, true);
},
renderLeafQueueUsedCapacities: function (layout) {
var leafQueueUsedCaps = [];
for (var queueName in this.queues.data) {
var q = this.queues.data[queueName];
if ((!q.get("children")) || q.get("children")
.length === 0) {
// it's a leafqueue
leafQueueUsedCaps.push({
label: q.get("name"),
value: q.get("usedCapacity")
});
}
}
this.renderDonutChart(this.charts.g, leafQueueUsedCaps, "LeafQueues Used Capacities",
layout, true);
},
renderCharts: function (queueName) {
this.charts.leftBannerLen = this.queues.maxDepth * 30 + 100;
this.initCharts();
var queue = this.queues.data[queueName];
var idx = 0;
if (queue.get("name") === "root") {
this.renderLeafQueueUsedCapacities(this.getLayout(idx++));
}
if (queue.get("name") !== "root") {
this.renderQueueCapacities(queue, this.getLayout(idx++));
}
if (queue.get("children") && queue.get("children")
.length > 0) {
this.renderChildrenCapacities(queue, this.getLayout(idx++));
this.renderChildrenUsedCapacities(queue, this.getLayout(idx++));
}
},
});