Added /campaigns/:id/results endpoint to return campaign summary and make results page much quicker.

Fixes 282.
pull/291/head
Jordan Wright 2016-06-07 22:31:55 -05:00
parent 3d5b330c61
commit c5d6792bba
5 changed files with 60 additions and 9 deletions

View File

@ -111,6 +111,23 @@ func API_Campaigns_Id(w http.ResponseWriter, r *http.Request) {
} }
} }
// API_Campaigns_Id_Results returns just the results for a given campaign to
// significantly reduce the information returned.
func API_Campaigns_Id_Results(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, _ := strconv.ParseInt(vars["id"], 0, 64)
cr, err := models.GetCampaignResults(id, ctx.Get(r, "user_id").(int64))
if err != nil {
Logger.Println(err)
JSONResponse(w, models.Response{Success: false, Message: "Campaign not found"}, http.StatusNotFound)
return
}
if r.Method == "GET" {
JSONResponse(w, cr, http.StatusOK)
return
}
}
// API_Groups returns details about the requested group. If the campaign is not // API_Groups returns details about the requested group. If the campaign is not
// valid, API_Groups returns null. // valid, API_Groups returns null.
func API_Groups(w http.ResponseWriter, r *http.Request) { func API_Groups(w http.ResponseWriter, r *http.Request) {

View File

@ -46,6 +46,7 @@ func CreateAdminRouter() http.Handler {
api.HandleFunc("/reset", Use(API_Reset, mid.RequireLogin)) api.HandleFunc("/reset", Use(API_Reset, mid.RequireLogin))
api.HandleFunc("/campaigns/", Use(API_Campaigns, mid.RequireAPIKey)) api.HandleFunc("/campaigns/", Use(API_Campaigns, mid.RequireAPIKey))
api.HandleFunc("/campaigns/{id:[0-9]+}", Use(API_Campaigns_Id, mid.RequireAPIKey)) api.HandleFunc("/campaigns/{id:[0-9]+}", Use(API_Campaigns_Id, mid.RequireAPIKey))
api.HandleFunc("/campaigns/{id:[0-9]+}/results", Use(API_Campaigns_Id_Results, mid.RequireAPIKey))
api.HandleFunc("/groups/", Use(API_Groups, mid.RequireAPIKey)) api.HandleFunc("/groups/", Use(API_Groups, mid.RequireAPIKey))
api.HandleFunc("/groups/{id:[0-9]+}", Use(API_Groups_Id, mid.RequireAPIKey)) api.HandleFunc("/groups/{id:[0-9]+}", Use(API_Groups_Id, mid.RequireAPIKey))
api.HandleFunc("/templates/", Use(API_Templates, mid.RequireAPIKey)) api.HandleFunc("/templates/", Use(API_Templates, mid.RequireAPIKey))

View File

@ -7,7 +7,7 @@ import (
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
) )
//Campaign is a struct representing a created campaign // Campaign is a struct representing a created campaign
type Campaign struct { type Campaign struct {
Id int64 `json:"id"` Id int64 `json:"id"`
UserId int64 `json:"-"` UserId int64 `json:"-"`
@ -28,6 +28,15 @@ type Campaign struct {
URL string `json:"url"` URL string `json:"url"`
} }
// CampaignResults is a struct representing the results from a campaign
type CampaignResults struct {
Id int64 `json:"id"`
Name string `json:"name"`
Status string `json:"status"`
Results []Result `json:"results, omitempty"`
Events []Event `json:"timeline,omitempty"`
}
// ErrCampaignNameNotSpecified indicates there was no template given by the user // ErrCampaignNameNotSpecified indicates there was no template given by the user
var ErrCampaignNameNotSpecified = errors.New("Campaign name not specified") var ErrCampaignNameNotSpecified = errors.New("Campaign name not specified")
@ -190,6 +199,26 @@ func GetCampaign(id int64, uid int64) (Campaign, error) {
return c, err return c, err
} }
func GetCampaignResults(id int64, uid int64) (CampaignResults, error) {
cr := CampaignResults{}
err := db.Table("campaigns").Where("id=? and user_id=?", id, uid).Find(&cr).Error
if err != nil {
Logger.Printf("%s: campaign not found\n", err)
return cr, err
}
err = db.Table("results").Where("campaign_id=? and user_id=?", cr.Id, uid).Find(&cr.Results).Error
if err != nil {
Logger.Printf("%s: results not found for campaign\n", err)
return cr, err
}
err = db.Table("events").Where("campaign_id=?", cr.Id).Find(&cr.Events).Error
if err != nil {
Logger.Printf("%s: events not found for campaign\n", err)
return cr, err
}
return cr, err
}
// GetQueuedCampaigns returns the campaigns that are queued up for this given minute // GetQueuedCampaigns returns the campaigns that are queued up for this given minute
func GetQueuedCampaigns(t time.Time) ([]Campaign, error) { func GetQueuedCampaigns(t time.Time) ([]Campaign, error) {
cs := []Campaign{} cs := []Campaign{}

View File

@ -191,7 +191,7 @@ function renderTimeline(data) {
* * Datatables * * Datatables
*/ */
function poll() { function poll() {
api.campaignId.get(campaign.id) api.campaignId.results(campaign.id)
.success(function(c) { .success(function(c) {
campaign = c campaign = c
/* Update the timeline */ /* Update the timeline */
@ -289,7 +289,7 @@ function poll() {
function load() { function load() {
campaign.id = window.location.pathname.split('/').slice(-1)[0] campaign.id = window.location.pathname.split('/').slice(-1)[0]
api.campaignId.get(campaign.id) api.campaignId.results(campaign.id)
.success(function(c) { .success(function(c) {
campaign = c campaign = c
if (campaign) { if (campaign) {

View File

@ -26,11 +26,11 @@ function query(endpoint, method, data, async) {
}) })
} }
function escapeHtml(text){ function escapeHtml(text) {
return $("<div/>").text(text).html() return $("<div/>").text(text).html()
} }
function unescapeHtml(html){ function unescapeHtml(html) {
return $("<div/>").html(html).text() return $("<div/>").html(html).text()
} }
@ -58,6 +58,10 @@ var api = {
// delete() - Deletes a campaign at DELETE /campaigns/:id // delete() - Deletes a campaign at DELETE /campaigns/:id
delete: function(id) { delete: function(id) {
return query("/campaigns/" + id, "DELETE", {}, false) return query("/campaigns/" + id, "DELETE", {}, false)
},
// results() - Queries the API for GET /campaigns/:id/results
results: function(id) {
return query("/campaigns/" + id + "/results", "GET", {}, true)
} }
}, },
// groups contains the endpoints for /groups // groups contains the endpoints for /groups
@ -173,7 +177,7 @@ var api = {
return query("/import/site", "POST", req, false) return query("/import/site", "POST", req, false)
}, },
// send_test_email sends an email to the specified email address // send_test_email sends an email to the specified email address
send_test_email: function(req){ send_test_email: function(req) {
return query("/util/send_test_email", "POST", req, true) return query("/util/send_test_email", "POST", req, true)
} }
} }