github.com/topsteplocal/gophish@v0.6.0/static/js/src/app/dashboard.js (about)

     1  var campaigns = []
     2  // statuses is a helper map to point result statuses to ui classes
     3  var statuses = {
     4      "Email Sent": {
     5          color: "#1abc9c",
     6          label: "label-success",
     7          icon: "fa-envelope",
     8          point: "ct-point-sent"
     9      },
    10      "Emails Sent": {
    11          color: "#1abc9c",
    12          label: "label-success",
    13          icon: "fa-envelope",
    14          point: "ct-point-sent"
    15      },
    16      "In progress": {
    17          label: "label-primary"
    18      },
    19      "Queued": {
    20          label: "label-info"
    21      },
    22      "Completed": {
    23          label: "label-success"
    24      },
    25      "Email Opened": {
    26          color: "#f9bf3b",
    27          label: "label-warning",
    28          icon: "fa-envelope",
    29          point: "ct-point-opened"
    30      },
    31      "Email Reported": {
    32          color: "#45d6ef",
    33          label: "label-warning",
    34          icon: "fa-bullhorne",
    35          point: "ct-point-reported"
    36      },
    37      "Clicked Link": {
    38          color: "#F39C12",
    39          label: "label-clicked",
    40          icon: "fa-mouse-pointer",
    41          point: "ct-point-clicked"
    42      },
    43      "Success": {
    44          color: "#f05b4f",
    45          label: "label-danger",
    46          icon: "fa-exclamation",
    47          point: "ct-point-clicked"
    48      },
    49      "Error": {
    50          color: "#6c7a89",
    51          label: "label-default",
    52          icon: "fa-times",
    53          point: "ct-point-error"
    54      },
    55      "Error Sending Email": {
    56          color: "#6c7a89",
    57          label: "label-default",
    58          icon: "fa-times",
    59          point: "ct-point-error"
    60      },
    61      "Submitted Data": {
    62          color: "#f05b4f",
    63          label: "label-danger",
    64          icon: "fa-exclamation",
    65          point: "ct-point-clicked"
    66      },
    67      "Unknown": {
    68          color: "#6c7a89",
    69          label: "label-default",
    70          icon: "fa-question",
    71          point: "ct-point-error"
    72      },
    73      "Sending": {
    74          color: "#428bca",
    75          label: "label-primary",
    76          icon: "fa-spinner",
    77          point: "ct-point-sending"
    78      },
    79      "Campaign Created": {
    80          label: "label-success",
    81          icon: "fa-rocket"
    82      }
    83  }
    84  
    85  var statsMapping = {
    86      "sent": "Email Sent",
    87      "opened": "Email Opened",
    88      "email_reported": "Email Reported",
    89      "clicked": "Clicked Link",
    90      "submitted_data": "Submitted Data",
    91  }
    92  
    93  function deleteCampaign(idx) {
    94      if (confirm("Delete " + campaigns[idx].name + "?")) {
    95          api.campaignId.delete(campaigns[idx].id)
    96              .success(function (data) {
    97                  successFlash(data.message)
    98                  location.reload()
    99              })
   100      }
   101  }
   102  
   103  /* Renders a pie chart using the provided chartops */
   104  function renderPieChart(chartopts) {
   105      return Highcharts.chart(chartopts['elemId'], {
   106          chart: {
   107              type: 'pie',
   108              events: {
   109                  load: function () {
   110                      var chart = this,
   111                          rend = chart.renderer,
   112                          pie = chart.series[0],
   113                          left = chart.plotLeft + pie.center[0],
   114                          top = chart.plotTop + pie.center[1];
   115                      this.innerText = rend.text(chartopts['data'][0].count, left, top).
   116                      attr({
   117                          'text-anchor': 'middle',
   118                          'font-size': '16px',
   119                          'font-weight': 'bold',
   120                          'fill': chartopts['colors'][0],
   121                          'font-family': 'Helvetica,Arial,sans-serif'
   122                      }).add();
   123                  },
   124                  render: function () {
   125                      this.innerText.attr({
   126                          text: chartopts['data'][0].count
   127                      })
   128                  }
   129              }
   130          },
   131          title: {
   132              text: chartopts['title']
   133          },
   134          plotOptions: {
   135              pie: {
   136                  innerSize: '80%',
   137                  dataLabels: {
   138                      enabled: false
   139                  }
   140              }
   141          },
   142          credits: {
   143              enabled: false
   144          },
   145          tooltip: {
   146              formatter: function () {
   147                  if (this.key == undefined) {
   148                      return false
   149                  }
   150                  return '<span style="color:' + this.color + '">\u25CF</span>' + this.point.name + ': <b>' + this.y + '%</b><br/>'
   151              }
   152          },
   153          series: [{
   154              data: chartopts['data'],
   155              colors: chartopts['colors'],
   156          }]
   157      })
   158  }
   159  
   160  function generateStatsPieCharts(campaigns) {
   161      var stats_data = []
   162      var stats_series_data = {}
   163      var total = 0
   164  
   165      $.each(campaigns, function (i, campaign) {
   166          $.each(campaign.stats, function (status, count) {
   167              if (status == "total") {
   168                  total += count
   169                  return true
   170              }
   171              if (!stats_series_data[status]) {
   172                  stats_series_data[status] = count;
   173              } else {
   174                  stats_series_data[status] += count;
   175              }
   176          })
   177      })
   178      $.each(stats_series_data, function (status, count) {
   179          // I don't like this, but I guess it'll have to work.
   180          // Turns submitted_data into Submitted Data
   181          if (!(status in statsMapping)) {
   182              return true
   183          }
   184          status_label = statsMapping[status]
   185          stats_data.push({
   186              name: status_label,
   187              y: Math.floor((count / total) * 100),
   188              count: count
   189          })
   190          stats_data.push({
   191              name: '',
   192              y: 100 - Math.floor((count / total) * 100)
   193          })
   194          var stats_chart = renderPieChart({
   195              elemId: status + '_chart',
   196              title: status_label,
   197              name: status,
   198              data: stats_data,
   199              colors: [statuses[status_label].color, "#dddddd"]
   200          })
   201  
   202          stats_data = []
   203      });
   204  }
   205  
   206  function generateTimelineChart(campaigns) {
   207      var overview_data = []
   208      $.each(campaigns, function (i, campaign) {
   209          var campaign_date = moment.utc(campaign.created_date).local()
   210          // Add it to the chart data
   211          campaign.y = 0
   212          // Clicked events also contain our data submitted events
   213          campaign.y += campaign.stats.clicked
   214          campaign.y = Math.floor((campaign.y / campaign.stats.total) * 100)
   215          // Add the data to the overview chart
   216          overview_data.push({
   217              campaign_id: campaign.id,
   218              name: campaign.name,
   219              x: campaign_date.valueOf(),
   220              y: campaign.y
   221          })
   222      })
   223      Highcharts.chart('overview_chart', {
   224          chart: {
   225              zoomType: 'x',
   226              type: 'areaspline'
   227          },
   228          title: {
   229              text: 'Phishing Success Overview'
   230          },
   231          xAxis: {
   232              type: 'datetime',
   233              dateTimeLabelFormats: {
   234                  second: '%l:%M:%S',
   235                  minute: '%l:%M',
   236                  hour: '%l:%M',
   237                  day: '%b %d, %Y',
   238                  week: '%b %d, %Y',
   239                  month: '%b %Y'
   240              }
   241          },
   242          yAxis: {
   243              min: 0,
   244              max: 100,
   245              title: {
   246                  text: "% of Success"
   247              }
   248          },
   249          tooltip: {
   250              formatter: function () {
   251                  return Highcharts.dateFormat('%A, %b %d %l:%M:%S %P', new Date(this.x)) +
   252                      '<br>' + this.point.name + '<br>% Success: <b>' + this.y + '%</b>'
   253              }
   254          },
   255          legend: {
   256              enabled: false
   257          },
   258          plotOptions: {
   259              series: {
   260                  marker: {
   261                      enabled: true,
   262                      symbol: 'circle',
   263                      radius: 3
   264                  },
   265                  cursor: 'pointer',
   266                  point: {
   267                      events: {
   268                          click: function (e) {
   269                              window.location.href = "/campaigns/" + this.campaign_id
   270                          }
   271                      }
   272                  }
   273              }
   274          },
   275          credits: {
   276              enabled: false
   277          },
   278          series: [{
   279              data: overview_data,
   280              color: "#f05b4f",
   281              fillOpacity: 0.5
   282          }]
   283      })
   284  }
   285  
   286  $(document).ready(function () {
   287      Highcharts.setOptions({
   288          global: {
   289              useUTC: false
   290          }
   291      })
   292      api.campaigns.summary()
   293          .success(function (data) {
   294              $("#loading").hide()
   295              campaigns = data.campaigns
   296              if (campaigns.length > 0) {
   297                  $("#dashboard").show()
   298                  // Create the overview chart data
   299                  campaignTable = $("#campaignTable").DataTable({
   300                      columnDefs: [{
   301                              orderable: false,
   302                              targets: "no-sort"
   303                          },
   304                          {
   305                              className: "color-sent",
   306                              targets: [2]
   307                          },
   308                          {
   309                              className: "color-opened",
   310                              targets: [3]
   311                          },
   312                          {
   313                              className: "color-clicked",
   314                              targets: [4]
   315                          },
   316                          {
   317                              className: "color-success",
   318                              targets: [5]
   319                          },
   320                          {
   321                              className: "color-reported",
   322                              targets: [6]
   323                          }
   324                      ],
   325                      order: [
   326                          [1, "desc"]
   327                      ]
   328                  });
   329                  $.each(campaigns, function (i, campaign) {
   330                      var campaign_date = moment(campaign.created_date).format('MMMM Do YYYY, h:mm:ss a')
   331                      var label = statuses[campaign.status].label || "label-default";
   332                      //section for tooltips on the status of a campaign to show some quick stats
   333                      var launchDate;
   334                      if (moment(campaign.launch_date).isAfter(moment())) {
   335                          launchDate = "Scheduled to start: " + moment(campaign.launch_date).format('MMMM Do YYYY, h:mm:ss a')
   336                          var quickStats = launchDate + "<br><br>" + "Number of recipients: " + campaign.stats.total
   337                      } else {
   338                          launchDate = "Launch Date: " + moment(campaign.launch_date).format('MMMM Do YYYY, h:mm:ss a')
   339                          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 + "<br><br>" + "Reported : " + campaign.stats.email_reported
   340                      }
   341                      // Add it to the table
   342                      campaignTable.row.add([
   343                          escapeHtml(campaign.name),
   344                          campaign_date,
   345                          campaign.stats.sent,
   346                          campaign.stats.opened,
   347                          campaign.stats.clicked,
   348                          campaign.stats.submitted_data,
   349                          campaign.stats.email_reported,
   350                          "<span class=\"label " + label + "\" data-toggle=\"tooltip\" data-placement=\"right\" data-html=\"true\" title=\"" + quickStats + "\">" + campaign.status + "</span>",
   351                          "<div class='pull-right'><a class='btn btn-primary' href='/campaigns/" + campaign.id + "' data-toggle='tooltip' data-placement='left' title='View Results'>\
   352                      <i class='fa fa-bar-chart'></i>\
   353                      </a>\
   354                      <button class='btn btn-danger' onclick='deleteCampaign(" + i + ")' data-toggle='tooltip' data-placement='left' title='Delete Campaign'>\
   355                      <i class='fa fa-trash-o'></i>\
   356                      </button></div>"
   357                      ]).draw()
   358                      $('[data-toggle="tooltip"]').tooltip()
   359                  })
   360                  // Build the charts
   361                  generateStatsPieCharts(campaigns)
   362                  generateTimelineChart(campaigns)
   363              } else {
   364                  $("#emptyMessage").show()
   365              }
   366          })
   367          .error(function () {
   368              errorFlash("Error fetching campaigns")
   369          })
   370  })