mirror of https://github.com/gophish/gophish
Updated dashboard to show full final statuses instead of just "Successful" vs "Unsuccessful".
parent
269568148e
commit
80c68194a6
File diff suppressed because one or more lines are too long
|
@ -1,12 +1,89 @@
|
||||||
var campaigns = []
|
var campaigns = []
|
||||||
// labels is a map of campaign statuses to
|
|
||||||
// CSS classes
|
// statuses is a helper map to point result statuses to ui classes
|
||||||
var labels = {
|
var statuses = {
|
||||||
"In progress": "label-primary",
|
"Email Sent": {
|
||||||
"Queued": "label-info",
|
slice: "ct-slice-donut-sent",
|
||||||
"Completed": "label-success",
|
legend: "ct-legend-sent",
|
||||||
"Emails Sent": "label-success",
|
label: "label-success",
|
||||||
"Error": "label-danger"
|
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) {
|
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() {
|
$(document).ready(function() {
|
||||||
api.campaigns.summary()
|
api.campaigns.summary()
|
||||||
.success(function(data) {
|
.success(function(data) {
|
||||||
|
@ -33,9 +179,6 @@ $(document).ready(function() {
|
||||||
[]
|
[]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
var average_data = {
|
|
||||||
series: []
|
|
||||||
}
|
|
||||||
var overview_opts = {
|
var overview_opts = {
|
||||||
axisX: {
|
axisX: {
|
||||||
showGrid: false
|
showGrid: false
|
||||||
|
@ -45,13 +188,6 @@ $(document).ready(function() {
|
||||||
low: 0,
|
low: 0,
|
||||||
high: 100
|
high: 100
|
||||||
}
|
}
|
||||||
var average_opts = {
|
|
||||||
donut: true,
|
|
||||||
donutWidth: 40,
|
|
||||||
chartPadding: 0,
|
|
||||||
showLabel: false
|
|
||||||
}
|
|
||||||
var average = 0
|
|
||||||
campaignTable = $("#campaignTable").DataTable({
|
campaignTable = $("#campaignTable").DataTable({
|
||||||
columnDefs: [{
|
columnDefs: [{
|
||||||
orderable: false,
|
orderable: false,
|
||||||
|
@ -62,19 +198,19 @@ $(document).ready(function() {
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
$.each(campaigns, function(i, campaign) {
|
$.each(campaigns, function(i, campaign) {
|
||||||
var campaign_date = moment(campaign.created_date).format('MMMM Do YYYY, h:mm:ss a')
|
var campaign_date = moment(campaign.created_date).format('MMMM Do YYYY, h:mm:ss a')
|
||||||
var label = labels[campaign.status] || "label-default";
|
var label = statuses[campaign.status] || "label-default";
|
||||||
//section for tooltips on the status of a campaign to show some quick stats
|
//section for tooltips on the status of a campaign to show some quick stats
|
||||||
var launchDate;
|
var launchDate;
|
||||||
if (moment(campaign.launch_date).isAfter(moment())) {
|
if (moment(campaign.launch_date).isAfter(moment())) {
|
||||||
launchDate = "Scheduled to start: " + moment(campaign.launch_date).format('MMMM Do YYYY, h:mm:ss a')
|
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
|
var quickStats = launchDate + "<br><br>" + "Number of recipients: " + campaign.stats.total
|
||||||
} else {
|
} else {
|
||||||
launchDate = "Launch Date: " + moment(campaign.launch_date).format('MMMM Do YYYY, h:mm:ss a')
|
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
|
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
|
// Add it to the table
|
||||||
campaignTable.row.add([
|
campaignTable.row.add([
|
||||||
escapeHtml(campaign.name),
|
escapeHtml(campaign.name),
|
||||||
campaign_date,
|
campaign_date,
|
||||||
"<span class=\"label " + label + "\" data-toggle=\"tooltip\" data-placement=\"right\" data-html=\"true\" title=\"" + quickStats + "\">" + campaign.status + "</span>",
|
"<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>\
|
<i class='fa fa-trash-o'></i>\
|
||||||
</button></div>"
|
</button></div>"
|
||||||
]).draw()
|
]).draw()
|
||||||
$('[data-toggle="tooltip"]').tooltip()
|
$('[data-toggle="tooltip"]').tooltip()
|
||||||
// Add it to the chart data
|
// Add it to the chart data
|
||||||
campaign.y = 0
|
campaign.y = 0
|
||||||
campaign.y += campaign.stats.clicked + campaign.stats.submitted_data
|
campaign.y += campaign.stats.clicked + campaign.stats.submitted_data
|
||||||
campaign.y = Math.floor((campaign.y / campaign.stats.total) * 100)
|
campaign.y = Math.floor((campaign.y / campaign.stats.total) * 100)
|
||||||
average += campaign.y
|
// Add the data to the overview chart
|
||||||
// Add the data to the overview chart
|
overview_data.labels.push(campaign_date)
|
||||||
overview_data.labels.push(campaign_date)
|
overview_data.series[0].push({
|
||||||
overview_data.series[0].push({
|
meta: i,
|
||||||
meta: i,
|
value: campaign.y
|
||||||
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
|
|
||||||
})
|
})
|
||||||
// Build the charts
|
// 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)
|
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
|
// Setup the overview chart listeners
|
||||||
$chart = $("#overview_chart")
|
$chart = $("#overview_chart")
|
||||||
|
|
|
@ -45,15 +45,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
|
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
|
||||||
<p style="text-align:center;">Average Phishing Results</p>
|
<p style="text-align:center;">Average Phishing Results</p>
|
||||||
<div id="average_chart" class="col-lg-7 col-md-7"></div>
|
<div id="stats_chart" class="col-lg-7 col-md-7"></div>
|
||||||
<div id="average_chart_legend" class="col-lg-5 col-md-5">
|
<div class="col-lg-5 col-md-5">
|
||||||
<ul class="chartist-legend">
|
<ul id="stats_chart_legend" class="chartist-legend">
|
||||||
<li>
|
|
||||||
<span style="background-color:#f05b4f;"></span> Successful Phishes
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span style="background-color:#1abc9c;"></span> Unsuccessful Phishes
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue