Updated dashboard to show full final statuses instead of just "Successful" vs "Unsuccessful".

pull/662/head
Jordan Wright 2017-06-18 17:32:18 -05:00
parent 269568148e
commit 80c68194a6
3 changed files with 183 additions and 86 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,12 +1,89 @@
var campaigns = []
// labels is a map of campaign statuses to
// CSS classes
var labels = {
"In progress": "label-primary",
"Queued": "label-info",
"Completed": "label-success",
"Emails Sent": "label-success",
"Error": "label-danger"
// statuses is a helper map to point result statuses to ui classes
var statuses = {
"Email Sent": {
slice: "ct-slice-donut-sent",
legend: "ct-legend-sent",
label: "label-success",
icon: "fa-envelope",
point: "ct-point-sent"
},
"Email Sent": {
slice: "ct-slice-donut-sent",
legend: "ct-legend-sent",
label: "label-success",
icon: "fa-envelope",
point: "ct-point-sent"
},
"Email Opened": {
slice: "ct-slice-donut-opened",
legend: "ct-legend-opened",
label: "label-warning",
icon: "fa-envelope",
point: "ct-point-opened"
},
"Clicked Link": {
slice: "ct-slice-donut-clicked",
legend: "ct-legend-clicked",
label: "label-clicked",
icon: "fa-mouse-pointer",
point: "ct-point-clicked"
},
"Success": {
slice: "ct-slice-donut-success",
legend: "ct-legend-success",
label: "label-danger",
icon: "fa-exclamation",
point: "ct-point-clicked"
},
"Error": {
slice: "ct-slice-donut-error",
legend: "ct-legend-error",
label: "label-default",
icon: "fa-times",
point: "ct-point-error"
},
"Error Sending Email": {
slice: "ct-slice-donut-error",
legend: "ct-legend-error",
label: "label-default",
icon: "fa-times",
point: "ct-point-error"
},
"Submitted Data": {
slice: "ct-slice-donut-success",
legend: "ct-legend-success",
label: "label-danger",
icon: "fa-exclamation",
point: "ct-point-clicked"
},
"Unknown": {
slice: "ct-slice-donut-error",
legend: "ct-legend-error",
label: "label-default",
icon: "fa-question",
point: "ct-point-error"
},
"Sending": {
slice: "ct-slice-donut-sending",
legend: "ct-legend-sending",
label: "label-primary",
icon: "fa-spinner",
point: "ct-point-sending"
},
"Campaign Created": {
label: "label-success",
icon: "fa-rocket"
}
}
var statsMapping = {
"sent": "Email Sent",
"opened": "Email Opened",
"clicked": "Clicked Link",
"submitted_data": "Submitted Data",
"error": "Error"
}
function deleteCampaign(idx) {
@ -19,6 +96,75 @@ function deleteCampaign(idx) {
}
}
function generateStatsPieChart(campaigns) {
var stats_opts = {
donut: true,
donutWidth: 40,
chartPadding: 0,
showLabel: false
}
var stats_series_data = {}
var stats_data = {
series: []
}
var total = 0
$.each(campaigns, function(i, campaign) {
$.each(campaign.stats, function(status, count) {
if (status == "total") {
total += count
return true
}
if (!stats_series_data[status]) {
stats_series_data[status] = count;
} else {
stats_series_data[status] += count;
}
})
})
$.each(stats_series_data, function(status, count) {
// I don't like this, but I guess it'll have to work.
// Turns submitted_data into Submitted Data
status_label = statsMapping[status]
stats_data.series.push({
meta: status_label,
value: Math.floor((count / total) * 100)
})
$("#stats_chart_legend").append('<li><span class="' + statuses[status_label].legend + '"></span>' + status_label + '</li>')
})
var stats_chart = new Chartist.Pie("#stats_chart", stats_data, stats_opts)
$piechart = $("#stats_chart")
var $pietoolTip = $piechart
.append('<div class="chartist-tooltip"></div>')
.find('.chartist-tooltip')
.hide();
$piechart.get(0).__chartist__.on('draw', function(data) {
data.element.addClass(statuses[data.meta].slice)
})
// Update with the latest data
$piechart.get(0).__chartist__.update(stats_data)
$piechart.on('mouseenter', '.ct-slice-donut', function() {
var $point = $(this)
value = $point.attr('ct:value')
label = $point.attr('ct:meta')
$pietoolTip.html(label + ': ' + value.toString() + "%").show();
});
$piechart.on('mouseleave', '.ct-slice-donut', function() {
$pietoolTip.hide();
});
$piechart.on('mousemove', function(event) {
$pietoolTip.css({
left: (event.offsetX || event.originalEvent.layerX) - $pietoolTip.width() / 2 - 10,
top: (event.offsetY + 40 || event.originalEvent.layerY) - $pietoolTip.height() - 80
});
});
}
$(document).ready(function() {
api.campaigns.summary()
.success(function(data) {
@ -33,9 +179,6 @@ $(document).ready(function() {
[]
]
}
var average_data = {
series: []
}
var overview_opts = {
axisX: {
showGrid: false
@ -45,13 +188,6 @@ $(document).ready(function() {
low: 0,
high: 100
}
var average_opts = {
donut: true,
donutWidth: 40,
chartPadding: 0,
showLabel: false
}
var average = 0
campaignTable = $("#campaignTable").DataTable({
columnDefs: [{
orderable: false,
@ -62,19 +198,19 @@ $(document).ready(function() {
]
});
$.each(campaigns, function(i, campaign) {
var campaign_date = moment(campaign.created_date).format('MMMM Do YYYY, h:mm:ss a')
var label = labels[campaign.status] || "label-default";
//section for tooltips on the status of a campaign to show some quick stats
var launchDate;
if (moment(campaign.launch_date).isAfter(moment())) {
launchDate = "Scheduled to start: " + moment(campaign.launch_date).format('MMMM Do YYYY, h:mm:ss a')
var quickStats = launchDate + "<br><br>" + "Number of recipients: " + campaign.stats.total
} else {
launchDate = "Launch Date: " + moment(campaign.launch_date).format('MMMM Do YYYY, h:mm:ss a')
var quickStats = launchDate + "<br><br>" + "Number of recipients: " + campaign.stats.total + "<br><br>" + "Emails opened: " + campaign.stats.opened + "<br><br>" + "Emails clicked: " + campaign.stats.clicked + "<br><br>" + "Submitted Credentials: " + campaign.stats.submitted_data + "<br><br>" + "Errors : " + campaign.stats.error
}
// Add it to the table
campaignTable.row.add([
var campaign_date = moment(campaign.created_date).format('MMMM Do YYYY, h:mm:ss a')
var label = statuses[campaign.status] || "label-default";
//section for tooltips on the status of a campaign to show some quick stats
var launchDate;
if (moment(campaign.launch_date).isAfter(moment())) {
launchDate = "Scheduled to start: " + moment(campaign.launch_date).format('MMMM Do YYYY, h:mm:ss a')
var quickStats = launchDate + "<br><br>" + "Number of recipients: " + campaign.stats.total
} else {
launchDate = "Launch Date: " + moment(campaign.launch_date).format('MMMM Do YYYY, h:mm:ss a')
var quickStats = launchDate + "<br><br>" + "Number of recipients: " + campaign.stats.total + "<br><br>" + "Emails opened: " + campaign.stats.opened + "<br><br>" + "Emails clicked: " + campaign.stats.clicked + "<br><br>" + "Submitted Credentials: " + campaign.stats.submitted_data + "<br><br>" + "Errors : " + campaign.stats.error
}
// Add it to the table
campaignTable.row.add([
escapeHtml(campaign.name),
campaign_date,
"<span class=\"label " + label + "\" data-toggle=\"tooltip\" data-placement=\"right\" data-html=\"true\" title=\"" + quickStats + "\">" + campaign.status + "</span>",
@ -85,54 +221,21 @@ $(document).ready(function() {
<i class='fa fa-trash-o'></i>\
</button></div>"
]).draw()
$('[data-toggle="tooltip"]').tooltip()
// Add it to the chart data
campaign.y = 0
campaign.y += campaign.stats.clicked + campaign.stats.submitted_data
campaign.y = Math.floor((campaign.y / campaign.stats.total) * 100)
average += campaign.y
// Add the data to the overview chart
overview_data.labels.push(campaign_date)
overview_data.series[0].push({
meta: i,
value: campaign.y
})
})
average = Math.floor(average / data.total);
average_data.series.push({
meta: "Unsuccessful Phishes",
value: 100 - average
})
average_data.series.push({
meta: "Successful Phishes",
value: average
$('[data-toggle="tooltip"]').tooltip()
// Add it to the chart data
campaign.y = 0
campaign.y += campaign.stats.clicked + campaign.stats.submitted_data
campaign.y = Math.floor((campaign.y / campaign.stats.total) * 100)
// Add the data to the overview chart
overview_data.labels.push(campaign_date)
overview_data.series[0].push({
meta: i,
value: campaign.y
})
})
// Build the charts
var average_chart = new Chartist.Pie("#average_chart", average_data, average_opts)
generateStatsPieChart(campaigns)
var overview_chart = new Chartist.Line('#overview_chart', overview_data, overview_opts)
// Setup the average chart listeners
$piechart = $("#average_chart")
var $pietoolTip = $piechart
.append('<div class="chartist-tooltip"></div>')
.find('.chartist-tooltip')
.hide();
$piechart.on('mouseenter', '.ct-slice-donut', function() {
var $point = $(this)
value = $point.attr('ct:value')
label = $point.attr('ct:meta')
$pietoolTip.html(label + ': ' + value.toString() + "%").show();
});
$piechart.on('mouseleave', '.ct-slice-donut', function() {
$pietoolTip.hide();
});
$piechart.on('mousemove', function(event) {
$pietoolTip.css({
left: (event.offsetX || event.originalEvent.layerX) - $pietoolTip.width() / 2 - 10,
top: (event.offsetY + 40 || event.originalEvent.layerY) - $pietoolTip.height() - 80
});
});
// Setup the overview chart listeners
$chart = $("#overview_chart")

View File

@ -45,15 +45,9 @@
</div>
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
<p style="text-align:center;">Average Phishing Results</p>
<div id="average_chart" class="col-lg-7 col-md-7"></div>
<div id="average_chart_legend" class="col-lg-5 col-md-5">
<ul class="chartist-legend">
<li>
<span style="background-color:#f05b4f;"></span> Successful Phishes
</li>
<li>
<span style="background-color:#1abc9c;"></span> Unsuccessful Phishes
</li>
<div id="stats_chart" class="col-lg-7 col-md-7"></div>
<div class="col-lg-5 col-md-5">
<ul id="stats_chart_legend" class="chartist-legend">
</ul>
</div>
</div>