|
@ -223,80 +223,80 @@ var PayrollDashboard = AbstractAction.extend({ |
|
|
model: "hr.expense", |
|
|
model: "hr.expense", |
|
|
method: "get_employee_expense", |
|
|
method: "get_employee_expense", |
|
|
}).then(function (data) { |
|
|
}).then(function (data) { |
|
|
data.forEach(function(d) { |
|
|
if(data){ |
|
|
d.values.forEach(function(d) { |
|
|
data.forEach(function(d) { |
|
|
d.l_month = d.l_month; |
|
|
d.values.forEach(function(d) { |
|
|
d.count = +d.count; |
|
|
d.l_month = d.l_month; |
|
|
}); |
|
|
d.count = +d.count; |
|
|
}); |
|
|
}); |
|
|
var margin = {top: 30, right: 10, bottom: 30, left: 30}, |
|
|
}); |
|
|
width = 400 - margin.left - margin.right, |
|
|
var margin = {top: 30, right: 10, bottom: 30, left: 30}, |
|
|
height = 250 - margin.top - margin.bottom; |
|
|
width = 400 - margin.left - margin.right, |
|
|
|
|
|
height = 250 - margin.top - margin.bottom; |
|
|
// Set the ranges
|
|
|
|
|
|
var x = d3.scale.ordinal() |
|
|
// Set the ranges
|
|
|
.rangeRoundBands([0, width], 1); |
|
|
var x = d3.scale.ordinal() |
|
|
|
|
|
.rangeRoundBands([0, width], 1); |
|
|
var y = d3.scale.linear() |
|
|
|
|
|
.range([height, 0]); |
|
|
var y = d3.scale.linear() |
|
|
|
|
|
.range([height, 0]); |
|
|
// Define the axes
|
|
|
|
|
|
var xAxis = d3.svg.axis().scale(x) |
|
|
// Define the axes
|
|
|
.orient("bottom"); |
|
|
var xAxis = d3.svg.axis().scale(x) |
|
|
|
|
|
.orient("bottom"); |
|
|
var yAxis = d3.svg.axis().scale(y) |
|
|
|
|
|
.orient("left").ticks(5); |
|
|
var yAxis = d3.svg.axis().scale(y) |
|
|
|
|
|
.orient("left").ticks(5); |
|
|
x.domain(data[0].values.map(function(d) { return d.l_month; })); |
|
|
|
|
|
y.domain([0, d3.max(data[0].values, d => d.count)]) |
|
|
x.domain(data[0].values.map(function(d) { return d.l_month; })); |
|
|
|
|
|
y.domain([0, d3.max(data[0].values, d => d.count)]) |
|
|
var svg = d3.select(elem[0]).append("svg") |
|
|
|
|
|
.attr("width", width + margin.left + margin.right) |
|
|
var svg = d3.select(elem[0]).append("svg") |
|
|
.attr("height", height + margin.top + margin.bottom) |
|
|
.attr("width", width + margin.left + margin.right) |
|
|
.append("g") |
|
|
.attr("height", height + margin.top + margin.bottom) |
|
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); |
|
|
.append("g") |
|
|
|
|
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); |
|
|
// Add the X Axis
|
|
|
|
|
|
svg.append("g") |
|
|
// Add the X Axis
|
|
|
.attr("class", "x axis") |
|
|
svg.append("g") |
|
|
.attr("transform", "translate(0," + height + ")") |
|
|
.attr("class", "x axis") |
|
|
.call(xAxis); |
|
|
.attr("transform", "translate(0," + height + ")") |
|
|
|
|
|
.call(xAxis); |
|
|
// Add the Y Axis
|
|
|
|
|
|
svg.append("g") |
|
|
// Add the Y Axis
|
|
|
.attr("class", "y axis") |
|
|
svg.append("g") |
|
|
.call(yAxis); |
|
|
.attr("class", "y axis") |
|
|
|
|
|
.call(yAxis); |
|
|
|
|
|
|
|
|
var line = d3.svg.line() |
|
|
|
|
|
.x(function(d) {return x(d.l_month); }) |
|
|
var line = d3.svg.line() |
|
|
.y(function(d) {return y(d.count); }); |
|
|
.x(function(d) {return x(d.l_month); }) |
|
|
|
|
|
.y(function(d) {return y(d.count); }); |
|
|
let lines = svg.append('g') |
|
|
|
|
|
.attr('class', 'lines'); |
|
|
let lines = svg.append('g') |
|
|
|
|
|
.attr('class', 'lines'); |
|
|
lines.selectAll('.line-group') |
|
|
|
|
|
.data(data).enter() |
|
|
lines.selectAll('.line-group') |
|
|
.append('g') |
|
|
.data(data).enter() |
|
|
.attr('class', 'line-group') |
|
|
.append('g') |
|
|
.append('path') |
|
|
.attr('class', 'line-group') |
|
|
.attr('class', 'line') |
|
|
.append('path') |
|
|
.attr('d', function(d) { return line(d.values); }) |
|
|
.attr('class', 'line') |
|
|
.style('stroke', (d, i) => color(i)); |
|
|
.attr('d', function(d) { return line(d.values); }) |
|
|
|
|
|
.style('stroke', (d, i) => color(i)); |
|
|
lines.selectAll("circle-group") |
|
|
|
|
|
.data(data).enter() |
|
|
lines.selectAll("circle-group") |
|
|
.append("g") |
|
|
.data(data).enter() |
|
|
.selectAll("circle") |
|
|
.append("g") |
|
|
.data(function(d) { return d.values;}).enter() |
|
|
.selectAll("circle") |
|
|
.append("g") |
|
|
.data(function(d) { return d.values;}).enter() |
|
|
.attr("class", "circle") |
|
|
.append("g") |
|
|
.append("circle") |
|
|
.attr("class", "circle") |
|
|
.attr("cx", function(d) { return x(d.l_month)}) |
|
|
.append("circle") |
|
|
.attr("cy", function(d) { return y(d.count)}) |
|
|
.attr("cx", function(d) { return x(d.l_month)}) |
|
|
.attr("r", 3); |
|
|
.attr("cy", function(d) { return y(d.count)}) |
|
|
|
|
|
.attr("r", 3); |
|
|
|
|
|
} |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
@ -309,212 +309,214 @@ var PayrollDashboard = AbstractAction.extend({ |
|
|
model: "hr.employee", |
|
|
model: "hr.employee", |
|
|
method: "get_department_leave", |
|
|
method: "get_department_leave", |
|
|
}).then(function (data) { |
|
|
}).then(function (data) { |
|
|
var fData = data[0]; |
|
|
if (data){ |
|
|
var dept = data[1]; |
|
|
var fData = data[0]; |
|
|
var id = self.$('.leave_graph')[0]; |
|
|
var dept = data[1]; |
|
|
var barColor = '#ff618a'; |
|
|
var id = self.$('.leave_graph')[0]; |
|
|
fData.forEach(function(d){ |
|
|
var barColor = '#ff618a'; |
|
|
var total = 0; |
|
|
fData.forEach(function(d){ |
|
|
for (var dpt in dept){ |
|
|
var total = 0; |
|
|
total += d.leave[dept[dpt]]; |
|
|
for (var dpt in dept){ |
|
|
} |
|
|
total += d.leave[dept[dpt]]; |
|
|
d.total=total; |
|
|
} |
|
|
}); |
|
|
d.total=total; |
|
|
|
|
|
}); |
|
|
// function to handle histogram.
|
|
|
|
|
|
function histoGram(fD){ |
|
|
// function to handle histogram.
|
|
|
var hG={}, hGDim = {t: 60, r: 0, b: 30, l: 0}; |
|
|
function histoGram(fD){ |
|
|
hGDim.w = 350 - hGDim.l - hGDim.r, |
|
|
var hG={}, hGDim = {t: 60, r: 0, b: 30, l: 0}; |
|
|
hGDim.h = 200 - hGDim.t - hGDim.b; |
|
|
hGDim.w = 350 - hGDim.l - hGDim.r, |
|
|
|
|
|
hGDim.h = 200 - hGDim.t - hGDim.b; |
|
|
//create svg for histogram.
|
|
|
|
|
|
var hGsvg = d3.select(id).append("svg") |
|
|
//create svg for histogram.
|
|
|
.attr("width", hGDim.w + hGDim.l + hGDim.r) |
|
|
var hGsvg = d3.select(id).append("svg") |
|
|
.attr("height", hGDim.h + hGDim.t + hGDim.b).append("g") |
|
|
.attr("width", hGDim.w + hGDim.l + hGDim.r) |
|
|
.attr("transform", "translate(" + hGDim.l + "," + hGDim.t + ")"); |
|
|
.attr("height", hGDim.h + hGDim.t + hGDim.b).append("g") |
|
|
|
|
|
.attr("transform", "translate(" + hGDim.l + "," + hGDim.t + ")"); |
|
|
// create function for x-axis mapping.
|
|
|
|
|
|
var x = d3.scale.ordinal().rangeRoundBands([0, hGDim.w], 0.1) |
|
|
// create function for x-axis mapping.
|
|
|
.domain(fD.map(function(d) { return d[0]; })); |
|
|
var x = d3.scale.ordinal().rangeRoundBands([0, hGDim.w], 0.1) |
|
|
|
|
|
.domain(fD.map(function(d) { return d[0]; })); |
|
|
// Add x-axis to the histogram svg.
|
|
|
|
|
|
hGsvg.append("g").attr("class", "x axis") |
|
|
// Add x-axis to the histogram svg.
|
|
|
.attr("transform", "translate(0," + hGDim.h + ")") |
|
|
hGsvg.append("g").attr("class", "x axis") |
|
|
.call(d3.svg.axis().scale(x).orient("bottom")); |
|
|
.attr("transform", "translate(0," + hGDim.h + ")") |
|
|
|
|
|
.call(d3.svg.axis().scale(x).orient("bottom")); |
|
|
// Create function for y-axis map.
|
|
|
|
|
|
var y = d3.scale.linear().range([hGDim.h, 0]) |
|
|
// Create function for y-axis map.
|
|
|
.domain([0, d3.max(fD, function(d) { return d[1]; })]); |
|
|
var y = d3.scale.linear().range([hGDim.h, 0]) |
|
|
|
|
|
.domain([0, d3.max(fD, function(d) { return d[1]; })]); |
|
|
// Create bars for histogram to contain rectangles and freq labels.
|
|
|
|
|
|
var bars = hGsvg.selectAll(".bar").data(fD).enter() |
|
|
// Create bars for histogram to contain rectangles and freq labels.
|
|
|
.append("g").attr("class", "bar"); |
|
|
var bars = hGsvg.selectAll(".bar").data(fD).enter() |
|
|
|
|
|
.append("g").attr("class", "bar"); |
|
|
//create the rectangles.
|
|
|
|
|
|
bars.append("rect") |
|
|
//create the rectangles.
|
|
|
.attr("x", function(d) { return x(d[0]); }) |
|
|
bars.append("rect") |
|
|
.attr("y", function(d) { return y(d[1]); }) |
|
|
.attr("x", function(d) { return x(d[0]); }) |
|
|
.attr("width", x.rangeBand()) |
|
|
.attr("y", function(d) { return y(d[1]); }) |
|
|
.attr("height", function(d) { return hGDim.h - y(d[1]); }) |
|
|
.attr("width", x.rangeBand()) |
|
|
.attr('fill',barColor) |
|
|
|
|
|
.on("mouseover",mouseover)// mouseover is defined below.
|
|
|
|
|
|
.on("mouseout",mouseout);// mouseout is defined below.
|
|
|
|
|
|
|
|
|
|
|
|
//Create the frequency labels above the rectangles.
|
|
|
|
|
|
bars.append("text").text(function(d){ return d3.format(",")(d[1])}) |
|
|
|
|
|
.attr("x", function(d) { return x(d[0])+x.rangeBand()/2; }) |
|
|
|
|
|
.attr("y", function(d) { return y(d[1])-5; }) |
|
|
|
|
|
.attr("text-anchor", "middle"); |
|
|
|
|
|
|
|
|
|
|
|
function mouseover(d){ // utility function to be called on mouseover.
|
|
|
|
|
|
// filter for selected state.
|
|
|
|
|
|
var st = fData.filter(function(s){ return s.l_month == d[0];})[0], |
|
|
|
|
|
nD = d3.keys(st.leave).map(function(s){ return {type:s, leave:st.leave[s]};}); |
|
|
|
|
|
|
|
|
|
|
|
// call update functions of pie-chart and legend.
|
|
|
|
|
|
pC.update(nD); |
|
|
|
|
|
leg.update(nD); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function mouseout(d){ // utility function to be called on mouseout.
|
|
|
|
|
|
// reset the pie-chart and legend.
|
|
|
|
|
|
pC.update(tF); |
|
|
|
|
|
leg.update(tF); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// create function to update the bars. This will be used by pie-chart.
|
|
|
|
|
|
hG.update = function(nD, color){ |
|
|
|
|
|
// update the domain of the y-axis map to reflect change in frequencies.
|
|
|
|
|
|
y.domain([0, d3.max(nD, function(d) { return d[1]; })]); |
|
|
|
|
|
|
|
|
|
|
|
// Attach the new data to the bars.
|
|
|
|
|
|
var bars = hGsvg.selectAll(".bar").data(nD); |
|
|
|
|
|
|
|
|
|
|
|
// transition the height and color of rectangles.
|
|
|
|
|
|
bars.select("rect").transition().duration(500) |
|
|
|
|
|
.attr("y", function(d) {return y(d[1]); }) |
|
|
|
|
|
.attr("height", function(d) { return hGDim.h - y(d[1]); }) |
|
|
.attr("height", function(d) { return hGDim.h - y(d[1]); }) |
|
|
.attr("fill", color); |
|
|
.attr('fill',barColor) |
|
|
|
|
|
.on("mouseover",mouseover)// mouseover is defined below.
|
|
|
// transition the frequency labels location and change value.
|
|
|
.on("mouseout",mouseout);// mouseout is defined below.
|
|
|
bars.select("text").transition().duration(500) |
|
|
|
|
|
.text(function(d){ return d3.format(",")(d[1])}) |
|
|
//Create the frequency labels above the rectangles.
|
|
|
.attr("y", function(d) {return y(d[1])-5; }); |
|
|
bars.append("text").text(function(d){ return d3.format(",")(d[1])}) |
|
|
|
|
|
.attr("x", function(d) { return x(d[0])+x.rangeBand()/2; }) |
|
|
|
|
|
.attr("y", function(d) { return y(d[1])-5; }) |
|
|
|
|
|
.attr("text-anchor", "middle"); |
|
|
|
|
|
|
|
|
|
|
|
function mouseover(d){ // utility function to be called on mouseover.
|
|
|
|
|
|
// filter for selected state.
|
|
|
|
|
|
var st = fData.filter(function(s){ return s.l_month == d[0];})[0], |
|
|
|
|
|
nD = d3.keys(st.leave).map(function(s){ return {type:s, leave:st.leave[s]};}); |
|
|
|
|
|
|
|
|
|
|
|
// call update functions of pie-chart and legend.
|
|
|
|
|
|
pC.update(nD); |
|
|
|
|
|
leg.update(nD); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function mouseout(d){ // utility function to be called on mouseout.
|
|
|
|
|
|
// reset the pie-chart and legend.
|
|
|
|
|
|
pC.update(tF); |
|
|
|
|
|
leg.update(tF); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// create function to update the bars. This will be used by pie-chart.
|
|
|
|
|
|
hG.update = function(nD, color){ |
|
|
|
|
|
// update the domain of the y-axis map to reflect change in frequencies.
|
|
|
|
|
|
y.domain([0, d3.max(nD, function(d) { return d[1]; })]); |
|
|
|
|
|
|
|
|
|
|
|
// Attach the new data to the bars.
|
|
|
|
|
|
var bars = hGsvg.selectAll(".bar").data(nD); |
|
|
|
|
|
|
|
|
|
|
|
// transition the height and color of rectangles.
|
|
|
|
|
|
bars.select("rect").transition().duration(500) |
|
|
|
|
|
.attr("y", function(d) {return y(d[1]); }) |
|
|
|
|
|
.attr("height", function(d) { return hGDim.h - y(d[1]); }) |
|
|
|
|
|
.attr("fill", color); |
|
|
|
|
|
|
|
|
|
|
|
// transition the frequency labels location and change value.
|
|
|
|
|
|
bars.select("text").transition().duration(500) |
|
|
|
|
|
.text(function(d){ return d3.format(",")(d[1])}) |
|
|
|
|
|
.attr("y", function(d) {return y(d[1])-5; }); |
|
|
|
|
|
} |
|
|
|
|
|
return hG; |
|
|
} |
|
|
} |
|
|
return hG; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// function to handle pieChart.
|
|
|
|
|
|
function pieChart(pD){ |
|
|
|
|
|
var pC ={}, pieDim ={w:250, h: 250}; |
|
|
|
|
|
pieDim.r = Math.min(pieDim.w, pieDim.h) / 2; |
|
|
|
|
|
|
|
|
|
|
|
// create svg for pie chart.
|
|
|
|
|
|
var piesvg = d3.select(id).append("svg") |
|
|
|
|
|
.attr("width", pieDim.w).attr("height", pieDim.h).append("g") |
|
|
|
|
|
.attr("transform", "translate("+pieDim.w/2+","+pieDim.h/2+")"); |
|
|
|
|
|
|
|
|
|
|
|
// create function to draw the arcs of the pie slices.
|
|
|
|
|
|
var arc = d3.svg.arc().outerRadius(pieDim.r - 10).innerRadius(0); |
|
|
|
|
|
|
|
|
|
|
|
// create a function to compute the pie slice angles.
|
|
|
// function to handle pieChart.
|
|
|
var pie = d3.layout.pie().sort(null).value(function(d) { return d.leave; }); |
|
|
function pieChart(pD){ |
|
|
|
|
|
var pC ={}, pieDim ={w:250, h: 250}; |
|
|
// Draw the pie slices.
|
|
|
pieDim.r = Math.min(pieDim.w, pieDim.h) / 2; |
|
|
piesvg.selectAll("path").data(pie(pD)).enter().append("path").attr("d", arc) |
|
|
|
|
|
.each(function(d) { this._current = d; }) |
|
|
// create svg for pie chart.
|
|
|
.attr("fill", function(d, i){return color(i);}) |
|
|
var piesvg = d3.select(id).append("svg") |
|
|
.on("mouseover",mouseover).on("mouseout",mouseout); |
|
|
.attr("width", pieDim.w).attr("height", pieDim.h).append("g") |
|
|
|
|
|
.attr("transform", "translate("+pieDim.w/2+","+pieDim.h/2+")"); |
|
|
// create function to update pie-chart. This will be used by histogram.
|
|
|
|
|
|
pC.update = function(nD){ |
|
|
// create function to draw the arcs of the pie slices.
|
|
|
piesvg.selectAll("path").data(pie(nD)).transition().duration(500) |
|
|
var arc = d3.svg.arc().outerRadius(pieDim.r - 10).innerRadius(0); |
|
|
.attrTween("d", arcTween); |
|
|
|
|
|
} |
|
|
// create a function to compute the pie slice angles.
|
|
|
// Utility function to be called on mouseover a pie slice.
|
|
|
var pie = d3.layout.pie().sort(null).value(function(d) { return d.leave; }); |
|
|
function mouseover(d, i){ |
|
|
|
|
|
// call the update function of histogram with new data.
|
|
|
// Draw the pie slices.
|
|
|
hG.update(fData.map(function(v){ |
|
|
piesvg.selectAll("path").data(pie(pD)).enter().append("path").attr("d", arc) |
|
|
return [v.l_month,v.leave[d.data.type]];}),color(i)); |
|
|
.each(function(d) { this._current = d; }) |
|
|
|
|
|
.attr("fill", function(d, i){return color(i);}) |
|
|
|
|
|
.on("mouseover",mouseover).on("mouseout",mouseout); |
|
|
|
|
|
|
|
|
|
|
|
// create function to update pie-chart. This will be used by histogram.
|
|
|
|
|
|
pC.update = function(nD){ |
|
|
|
|
|
piesvg.selectAll("path").data(pie(nD)).transition().duration(500) |
|
|
|
|
|
.attrTween("d", arcTween); |
|
|
|
|
|
} |
|
|
|
|
|
// Utility function to be called on mouseover a pie slice.
|
|
|
|
|
|
function mouseover(d, i){ |
|
|
|
|
|
// call the update function of histogram with new data.
|
|
|
|
|
|
hG.update(fData.map(function(v){ |
|
|
|
|
|
return [v.l_month,v.leave[d.data.type]];}),color(i)); |
|
|
|
|
|
} |
|
|
|
|
|
//Utility function to be called on mouseout a pie slice.
|
|
|
|
|
|
function mouseout(d){ |
|
|
|
|
|
// call the update function of histogram with all data.
|
|
|
|
|
|
hG.update(fData.map(function(v){ |
|
|
|
|
|
return [v.l_month,v.total];}), barColor); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
// Animating the pie-slice requiring a custom function which specifies
|
|
|
|
|
|
// how the intermediate paths should be drawn.
|
|
|
|
|
|
function arcTween(a) { |
|
|
|
|
|
var i = d3.interpolate(this._current, a); |
|
|
|
|
|
this._current = i(0); |
|
|
|
|
|
return function(t) { return arc(i(t)); }; |
|
|
|
|
|
} |
|
|
|
|
|
return pC; |
|
|
} |
|
|
} |
|
|
//Utility function to be called on mouseout a pie slice.
|
|
|
|
|
|
function mouseout(d){ |
|
|
|
|
|
// call the update function of histogram with all data.
|
|
|
|
|
|
hG.update(fData.map(function(v){ |
|
|
|
|
|
return [v.l_month,v.total];}), barColor); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
// function to handle legend.
|
|
|
// Animating the pie-slice requiring a custom function which specifies
|
|
|
function legend(lD){ |
|
|
// how the intermediate paths should be drawn.
|
|
|
var leg = {}; |
|
|
function arcTween(a) { |
|
|
|
|
|
var i = d3.interpolate(this._current, a); |
|
|
|
|
|
this._current = i(0); |
|
|
|
|
|
return function(t) { return arc(i(t)); }; |
|
|
|
|
|
} |
|
|
|
|
|
return pC; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// function to handle legend.
|
|
|
// create table for legend.
|
|
|
function legend(lD){ |
|
|
var legend = d3.select(id).append("table").attr('class','legend'); |
|
|
var leg = {}; |
|
|
|
|
|
|
|
|
|
|
|
// create table for legend.
|
|
|
// create one row per segment.
|
|
|
var legend = d3.select(id).append("table").attr('class','legend'); |
|
|
var tr = legend.append("tbody").selectAll("tr").data(lD).enter().append("tr"); |
|
|
|
|
|
|
|
|
// create one row per segment.
|
|
|
// create the first column for each segment.
|
|
|
var tr = legend.append("tbody").selectAll("tr").data(lD).enter().append("tr"); |
|
|
tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") |
|
|
|
|
|
.attr("width", '16').attr("height", '16') |
|
|
|
|
|
.attr("fill", function(d, i){return color(i);}) |
|
|
|
|
|
|
|
|
// create the first column for each segment.
|
|
|
// create the second column for each segment.
|
|
|
tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") |
|
|
tr.append("td").text(function(d){ return d.type;}); |
|
|
.attr("width", '16').attr("height", '16') |
|
|
|
|
|
.attr("fill", function(d, i){return color(i);}) |
|
|
|
|
|
|
|
|
|
|
|
// create the second column for each segment.
|
|
|
// create the third column for each segment.
|
|
|
tr.append("td").text(function(d){ return d.type;}); |
|
|
tr.append("td").attr("class",'legendFreq') |
|
|
|
|
|
.text(function(d){ return d.l_month;}); |
|
|
|
|
|
|
|
|
// create the third column for each segment.
|
|
|
// create the fourth column for each segment.
|
|
|
tr.append("td").attr("class",'legendFreq') |
|
|
tr.append("td").attr("class",'legendPerc') |
|
|
.text(function(d){ return d.l_month;}); |
|
|
.text(function(d){ return getLegend(d,lD);}); |
|
|
|
|
|
|
|
|
// create the fourth column for each segment.
|
|
|
// Utility function to be used to update the legend.
|
|
|
tr.append("td").attr("class",'legendPerc') |
|
|
leg.update = function(nD){ |
|
|
.text(function(d){ return getLegend(d,lD);}); |
|
|
// update the data attached to the row elements.
|
|
|
|
|
|
var l = legend.select("tbody").selectAll("tr").data(nD); |
|
|
|
|
|
|
|
|
// Utility function to be used to update the legend.
|
|
|
// update the frequencies.
|
|
|
leg.update = function(nD){ |
|
|
l.select(".legendFreq").text(function(d){ return d3.format(",")(d.leave);}); |
|
|
// update the data attached to the row elements.
|
|
|
|
|
|
var l = legend.select("tbody").selectAll("tr").data(nD); |
|
|
|
|
|
|
|
|
|
|
|
// update the frequencies.
|
|
|
// update the percentage column.
|
|
|
l.select(".legendFreq").text(function(d){ return d3.format(",")(d.leave);}); |
|
|
l.select(".legendPerc").text(function(d){ return getLegend(d,nD);}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// update the percentage column.
|
|
|
function getLegend(d,aD){ // Utility function to compute percentage.
|
|
|
l.select(".legendPerc").text(function(d){ return getLegend(d,nD);}); |
|
|
var perc = (d.leave/d3.sum(aD.map(function(v){ return v.leave; }))); |
|
|
} |
|
|
if (isNaN(perc)){ |
|
|
|
|
|
return d3.format("%")(0); |
|
|
|
|
|
} |
|
|
|
|
|
else{ |
|
|
|
|
|
return d3.format("%")(d.leave/d3.sum(aD.map(function(v){ return v.leave; }))); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
function getLegend(d,aD){ // Utility function to compute percentage.
|
|
|
return leg; |
|
|
var perc = (d.leave/d3.sum(aD.map(function(v){ return v.leave; }))); |
|
|
|
|
|
if (isNaN(perc)){ |
|
|
|
|
|
return d3.format("%")(0); |
|
|
|
|
|
} |
|
|
|
|
|
else{ |
|
|
|
|
|
return d3.format("%")(d.leave/d3.sum(aD.map(function(v){ return v.leave; }))); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
// calculate total frequency by segment for all state.
|
|
|
|
|
|
var tF = dept.map(function(d){ |
|
|
|
|
|
return {type:d, leave: d3.sum(fData.map(function(t){ return t.leave[d];}))}; |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
return leg; |
|
|
// calculate total frequency by state for all segment.
|
|
|
} |
|
|
var sF = fData.map(function(d){return [d.l_month,d.total];}); |
|
|
// calculate total frequency by segment for all state.
|
|
|
|
|
|
var tF = dept.map(function(d){ |
|
|
|
|
|
return {type:d, leave: d3.sum(fData.map(function(t){ return t.leave[d];}))}; |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// calculate total frequency by state for all segment.
|
|
|
|
|
|
var sF = fData.map(function(d){return [d.l_month,d.total];}); |
|
|
|
|
|
|
|
|
|
|
|
var hG = histoGram(sF), // create the histogram.
|
|
|
var hG = histoGram(sF), // create the histogram.
|
|
|
pC = pieChart(tF), // create the pie-chart.
|
|
|
pC = pieChart(tF), // create the pie-chart.
|
|
|
leg= legend(tF); // create the legend.
|
|
|
leg= legend(tF); // create the legend.
|
|
|
|
|
|
} |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
render_graphs: function(){ |
|
|
render_graphs: function(){ |
|
@ -543,36 +545,37 @@ var PayrollDashboard = AbstractAction.extend({ |
|
|
method: "get_employee_time_off", |
|
|
method: "get_employee_time_off", |
|
|
|
|
|
|
|
|
}).then(function (data) { |
|
|
}).then(function (data) { |
|
|
var segColor = {}; |
|
|
if (data){ |
|
|
var vis = d3.select(elem[0]).append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")"); |
|
|
var segColor = {}; |
|
|
var pie = d3.layout.pie().value(function(d){return d.value;}); |
|
|
var vis = d3.select(elem[0]).append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")"); |
|
|
var arc = d3.svg.arc().outerRadius(r); |
|
|
var pie = d3.layout.pie().value(function(d){return d.value;}); |
|
|
var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice"); |
|
|
var arc = d3.svg.arc().outerRadius(r); |
|
|
arcs.append("svg:path") |
|
|
var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice"); |
|
|
.attr("fill", function(d, i){ |
|
|
arcs.append("svg:path") |
|
|
return color(i); |
|
|
.attr("fill", function(d, i){ |
|
|
}) |
|
|
return color(i); |
|
|
.attr("d", function (d) { |
|
|
}) |
|
|
return arc(d); |
|
|
.attr("d", function (d) { |
|
|
}); |
|
|
return arc(d); |
|
|
|
|
|
}); |
|
|
var legend = d3.select(elem[0]).append("table").attr('class','legend'); |
|
|
|
|
|
|
|
|
var legend = d3.select(elem[0]).append("table").attr('class','legend'); |
|
|
// create one row per segment.
|
|
|
|
|
|
var tr = legend.append("tbody").selectAll("tr").data(data).enter().append("tr"); |
|
|
// create one row per segment.
|
|
|
|
|
|
var tr = legend.append("tbody").selectAll("tr").data(data).enter().append("tr"); |
|
|
// create the first column for each segment.
|
|
|
|
|
|
tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") |
|
|
// create the first column for each segment.
|
|
|
.attr("width", '16').attr("height", '16') |
|
|
tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") |
|
|
.attr("fill",function(d, i){ return color(i) }); |
|
|
.attr("width", '16').attr("height", '16') |
|
|
|
|
|
.attr("fill",function(d, i){ return color(i) }); |
|
|
// create the second column for each segment.
|
|
|
|
|
|
tr.append("td").attr("style","font-weight: bold;").text(function(d){ return d.label;}); |
|
|
// create the second column for each segment.
|
|
|
|
|
|
tr.append("td").attr("style","font-weight: bold;").text(function(d){ return d.label;}); |
|
|
// create the third column for each segment.
|
|
|
|
|
|
tr.append("td").attr("class",'legendFreq').attr("style","border: 5px solid transparent; font-weight: bold;") |
|
|
// create the third column for each segment.
|
|
|
.text(function(d){ return d.value;}); |
|
|
tr.append("td").attr("class",'legendFreq').attr("style","border: 5px solid transparent; font-weight: bold;") |
|
|
|
|
|
.text(function(d){ return d.value;}); |
|
|
|
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
}, |
|
|
}, |
|
@ -590,35 +593,37 @@ var PayrollDashboard = AbstractAction.extend({ |
|
|
model: "hr.payslip", |
|
|
model: "hr.payslip", |
|
|
method: "get_employee_payslips", |
|
|
method: "get_employee_payslips", |
|
|
}).then(function (data) { |
|
|
}).then(function (data) { |
|
|
var segColor = {}; |
|
|
if(data){ |
|
|
var vis = d3.select(elem[0]).append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")"); |
|
|
var segColor = {}; |
|
|
var pie = d3.layout.pie().value(function(d){return d.value;}); |
|
|
var vis = d3.select(elem[0]).append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")"); |
|
|
var arc = d3.svg.arc().outerRadius(r); |
|
|
var pie = d3.layout.pie().value(function(d){return d.value;}); |
|
|
var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice"); |
|
|
var arc = d3.svg.arc().outerRadius(r); |
|
|
arcs.append("svg:path") |
|
|
var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice"); |
|
|
.attr("fill", function(d, i){ |
|
|
arcs.append("svg:path") |
|
|
return color(i); |
|
|
.attr("fill", function(d, i){ |
|
|
}) |
|
|
return color(i); |
|
|
.attr("d", function (d) { |
|
|
}) |
|
|
return arc(d); |
|
|
.attr("d", function (d) { |
|
|
}); |
|
|
return arc(d); |
|
|
|
|
|
}); |
|
|
var legend = d3.select(elem[0]).append("table").attr('class','legend'); |
|
|
|
|
|
|
|
|
var legend = d3.select(elem[0]).append("table").attr('class','legend'); |
|
|
// create one row per segment.
|
|
|
|
|
|
var tr = legend.append("tbody").selectAll("tr").data(data).enter().append("tr"); |
|
|
// create one row per segment.
|
|
|
|
|
|
var tr = legend.append("tbody").selectAll("tr").data(data).enter().append("tr"); |
|
|
// create the first column for each segment.
|
|
|
|
|
|
tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") |
|
|
// create the first column for each segment.
|
|
|
.attr("width", '16').attr("height", '16') |
|
|
tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") |
|
|
.attr("fill",function(d, i){ return color(i) }); |
|
|
.attr("width", '16').attr("height", '16') |
|
|
|
|
|
.attr("fill",function(d, i){ return color(i) }); |
|
|
// create the second column for each segment.
|
|
|
|
|
|
tr.append("td").attr("style","font-weight: bold;").text(function(d){ return d.label;}); |
|
|
// create the second column for each segment.
|
|
|
|
|
|
tr.append("td").attr("style","font-weight: bold;").text(function(d){ return d.label;}); |
|
|
// create the third column for each segment.
|
|
|
|
|
|
tr.append("td").attr("class",'legendFreq').attr("style","border: 5px solid transparent; font-weight: bold;") |
|
|
// create the third column for each segment.
|
|
|
.text(function(d){ return d.value;}); |
|
|
tr.append("td").attr("class",'legendFreq').attr("style","border: 5px solid transparent; font-weight: bold;") |
|
|
|
|
|
.text(function(d){ return d.value;}); |
|
|
|
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
}, |
|
|
}, |
|
@ -636,35 +641,37 @@ var PayrollDashboard = AbstractAction.extend({ |
|
|
model: "hr.contract", |
|
|
model: "hr.contract", |
|
|
method: "get_employee_contract", |
|
|
method: "get_employee_contract", |
|
|
}).then(function (data) { |
|
|
}).then(function (data) { |
|
|
var segColor = {}; |
|
|
if(data){ |
|
|
var vis = d3.select(elem[0]).append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")"); |
|
|
var segColor = {}; |
|
|
var pie = d3.layout.pie().value(function(d){return d.value;}); |
|
|
var vis = d3.select(elem[0]).append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")"); |
|
|
var arc = d3.svg.arc().outerRadius(r); |
|
|
var pie = d3.layout.pie().value(function(d){return d.value;}); |
|
|
var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice"); |
|
|
var arc = d3.svg.arc().outerRadius(r); |
|
|
arcs.append("svg:path") |
|
|
var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice"); |
|
|
.attr("fill", function(d, i){ |
|
|
arcs.append("svg:path") |
|
|
return color(i); |
|
|
.attr("fill", function(d, i){ |
|
|
}) |
|
|
return color(i); |
|
|
.attr("d", function (d) { |
|
|
}) |
|
|
return arc(d); |
|
|
.attr("d", function (d) { |
|
|
}); |
|
|
return arc(d); |
|
|
|
|
|
}); |
|
|
var legend = d3.select(elem[0]).append("table").attr('class','legend'); |
|
|
|
|
|
|
|
|
var legend = d3.select(elem[0]).append("table").attr('class','legend'); |
|
|
// create one row per segment.
|
|
|
|
|
|
var tr = legend.append("tbody").selectAll("tr").data(data).enter().append("tr"); |
|
|
// create one row per segment.
|
|
|
|
|
|
var tr = legend.append("tbody").selectAll("tr").data(data).enter().append("tr"); |
|
|
// create the first column for each segment.
|
|
|
|
|
|
tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") |
|
|
// create the first column for each segment.
|
|
|
.attr("width", '16').attr("height", '16') |
|
|
tr.append("td").append("svg").attr("width", '16').attr("height", '16').append("rect") |
|
|
.attr("fill",function(d, i){ return color(i) }); |
|
|
.attr("width", '16').attr("height", '16') |
|
|
|
|
|
.attr("fill",function(d, i){ return color(i) }); |
|
|
// create the second column for each segment.
|
|
|
|
|
|
tr.append("td").attr("style","font-weight: bold;").text(function(d){ return d.label;}); |
|
|
// create the second column for each segment.
|
|
|
|
|
|
tr.append("td").attr("style","font-weight: bold;").text(function(d){ return d.label;}); |
|
|
// create the third column for each segment.
|
|
|
|
|
|
tr.append("td").attr("class",'legendFreq').attr("style","border: 5px solid transparent; font-weight: bold;") |
|
|
// create the third column for each segment.
|
|
|
.text(function(d){ return d.value;}); |
|
|
tr.append("td").attr("class",'legendFreq').attr("style","border: 5px solid transparent; font-weight: bold;") |
|
|
|
|
|
.text(function(d){ return d.value;}); |
|
|
|
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
}, |
|
|
}, |
|
@ -674,93 +681,94 @@ var PayrollDashboard = AbstractAction.extend({ |
|
|
model: "hr.employee", |
|
|
model: "hr.employee", |
|
|
method: "employee_leave_trend", |
|
|
method: "employee_leave_trend", |
|
|
}).then(function (data) { |
|
|
}).then(function (data) { |
|
|
var elem = self.$('.leave_trend'); |
|
|
if(data){ |
|
|
var margin = {top: 30, right: 20, bottom: 30, left: 80}, |
|
|
var elem = self.$('.leave_trend'); |
|
|
width = 500 - margin.left - margin.right, |
|
|
var margin = {top: 30, right: 20, bottom: 30, left: 80}, |
|
|
height = 250 - margin.top - margin.bottom; |
|
|
width = 500 - margin.left - margin.right, |
|
|
|
|
|
height = 250 - margin.top - margin.bottom; |
|
|
// Set the ranges
|
|
|
|
|
|
var x = d3.scale.ordinal() |
|
|
// Set the ranges
|
|
|
.rangeRoundBands([0, width], 1); |
|
|
var x = d3.scale.ordinal() |
|
|
|
|
|
.rangeRoundBands([0, width], 1); |
|
|
var y = d3.scale.linear() |
|
|
|
|
|
.range([height, 0]); |
|
|
var y = d3.scale.linear() |
|
|
|
|
|
.range([height, 0]); |
|
|
// Define the axes
|
|
|
|
|
|
var xAxis = d3.svg.axis().scale(x) |
|
|
// Define the axes
|
|
|
.orient("bottom"); |
|
|
var xAxis = d3.svg.axis().scale(x) |
|
|
|
|
|
.orient("bottom"); |
|
|
var yAxis = d3.svg.axis().scale(y) |
|
|
|
|
|
.orient("left").ticks(5); |
|
|
var yAxis = d3.svg.axis().scale(y) |
|
|
|
|
|
.orient("left").ticks(5); |
|
|
var valueline = d3.svg.line() |
|
|
|
|
|
.x(function(d) { return x(d.l_month); }) |
|
|
var valueline = d3.svg.line() |
|
|
.y(function(d) { return y(d.leave); }); |
|
|
.x(function(d) { return x(d.l_month); }) |
|
|
|
|
|
.y(function(d) { return y(d.leave); }); |
|
|
|
|
|
|
|
|
var svg = d3.select(elem[0]).append("svg") |
|
|
|
|
|
.attr("width", width + margin.left + margin.right) |
|
|
var svg = d3.select(elem[0]).append("svg") |
|
|
.attr("height", height + margin.top + margin.bottom) |
|
|
.attr("width", width + margin.left + margin.right) |
|
|
.append("g") |
|
|
.attr("height", height + margin.top + margin.bottom) |
|
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); |
|
|
.append("g") |
|
|
|
|
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); |
|
|
x.domain(data.map(function(d) { return d.l_month; })); |
|
|
|
|
|
y.domain([0, d3.max(data, function(d) { return d.leave; })]); |
|
|
x.domain(data.map(function(d) { return d.l_month; })); |
|
|
|
|
|
y.domain([0, d3.max(data, function(d) { return d.leave; })]); |
|
|
// Add the X Axis
|
|
|
|
|
|
svg.append("g") |
|
|
// Add the X Axis
|
|
|
.attr("class", "x axis") |
|
|
svg.append("g") |
|
|
.attr("transform", "translate(0," + height + ")") |
|
|
.attr("class", "x axis") |
|
|
.call(xAxis); |
|
|
.attr("transform", "translate(0," + height + ")") |
|
|
|
|
|
.call(xAxis); |
|
|
// Add the Y Axis
|
|
|
|
|
|
svg.append("g") |
|
|
// Add the Y Axis
|
|
|
.attr("class", "y axis") |
|
|
svg.append("g") |
|
|
.call(yAxis); |
|
|
.attr("class", "y axis") |
|
|
|
|
|
.call(yAxis); |
|
|
svg.append("path") |
|
|
|
|
|
.attr("class", "line") |
|
|
svg.append("path") |
|
|
.attr("d", valueline(data)); |
|
|
.attr("class", "line") |
|
|
|
|
|
.attr("d", valueline(data)); |
|
|
// Add the scatterplot
|
|
|
|
|
|
svg.selectAll("dot") |
|
|
// Add the scatterplot
|
|
|
.data(data) |
|
|
svg.selectAll("dot") |
|
|
.enter().append("circle") |
|
|
.data(data) |
|
|
.attr("r", 3) |
|
|
.enter().append("circle") |
|
|
.attr("cx", function(d) { return x(d.l_month); }) |
|
|
.attr("r", 3) |
|
|
.attr("cy", function(d) { return y(d.leave); }) |
|
|
.attr("cx", function(d) { return x(d.l_month); }) |
|
|
// .on('mouseover', function() { d3.select(this).transition().duration(500).ease("elastic").attr('r', 3 * 2) })
|
|
|
.attr("cy", function(d) { return y(d.leave); }) |
|
|
// .on('mouseout', function() { d3.select(this).transition().duration(500).ease("in-out").attr('r', 3) });
|
|
|
// .on('mouseover', function() { d3.select(this).transition().duration(500).ease("elastic").attr('r', 3 * 2) })
|
|
|
.on("mouseover", function() { tooltip.style("display", null); |
|
|
// .on('mouseout', function() { d3.select(this).transition().duration(500).ease("in-out").attr('r', 3) });
|
|
|
d3.select(this).transition().duration(500).ease("elastic").attr('r', 3 * 2) |
|
|
.on("mouseover", function() { tooltip.style("display", null); |
|
|
}) |
|
|
d3.select(this).transition().duration(500).ease("elastic").attr('r', 3 * 2) |
|
|
.on("mouseout", function() { tooltip.style("display", "none"); |
|
|
}) |
|
|
d3.select(this).transition().duration(500).ease("in-out").attr('r', 3) |
|
|
.on("mouseout", function() { tooltip.style("display", "none"); |
|
|
}) |
|
|
d3.select(this).transition().duration(500).ease("in-out").attr('r', 3) |
|
|
.on("mousemove", function(d) { |
|
|
}) |
|
|
var xPosition = d3.mouse(this)[0] - 15; |
|
|
.on("mousemove", function(d) { |
|
|
var yPosition = d3.mouse(this)[1] - 25; |
|
|
var xPosition = d3.mouse(this)[0] - 15; |
|
|
tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")"); |
|
|
var yPosition = d3.mouse(this)[1] - 25; |
|
|
tooltip.select("text").text(d.leave); |
|
|
tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")"); |
|
|
}); |
|
|
tooltip.select("text").text(d.leave); |
|
|
|
|
|
}); |
|
|
var tooltip = svg.append("g") |
|
|
|
|
|
.attr("class", "tooltip") |
|
|
var tooltip = svg.append("g") |
|
|
.style("display", "none"); |
|
|
.attr("class", "tooltip") |
|
|
|
|
|
.style("display", "none"); |
|
|
tooltip.append("rect") |
|
|
|
|
|
.attr("width", 30) |
|
|
tooltip.append("rect") |
|
|
.attr("height", 20) |
|
|
.attr("width", 30) |
|
|
.attr("fill", "black") |
|
|
.attr("height", 20) |
|
|
.style("opacity", 0.5); |
|
|
.attr("fill", "black") |
|
|
|
|
|
.style("opacity", 0.5); |
|
|
tooltip.append("text") |
|
|
|
|
|
.attr("x", 15) |
|
|
tooltip.append("text") |
|
|
.attr("dy", "1.2em") |
|
|
.attr("x", 15) |
|
|
.style("text-anchor", "middle") |
|
|
.attr("dy", "1.2em") |
|
|
.attr("font-size", "12px") |
|
|
.style("text-anchor", "middle") |
|
|
.attr("font-weight", "bold"); |
|
|
.attr("font-size", "12px") |
|
|
|
|
|
.attr("font-weight", "bold"); |
|
|
|
|
|
} |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|