Add button to campaign result view, to update users.

ToDo: Prevent duplicate user entries.
pull/3047/head
Andrew Walter 2023-12-10 11:36:30 +11:00
parent a28dcc5df8
commit 3e6e87a19e
7 changed files with 197 additions and 0 deletions

View File

@ -100,6 +100,32 @@ func (as *Server) CampaignResults(w http.ResponseWriter, r *http.Request) {
}
}
// CampaignUpdateUsers updates the users assigned to this campaign
func (as *Server) CampaignUpdateUsers(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, _ := strconv.ParseInt(vars["id"], 0, 64)
c, err := models.GetCampaign(id, ctx.Get(r, "user_id").(int64))
if err != nil {
log.Error(err);
JSONResponse(w, models.Response{Success: false, Message: "Campaign not found"}, http.StatusNotFound)
return
}
err = models.UpdateCampaignUsersFromGroups(&c);
if err != nil {
log.Error(err);
JSONResponse(w, models.Response{Success: false, Message: "Unable to update campaign users"}, http.StatusInternalServerError)
return
}
if r.Method == "GET" {
JSONResponse(w, models.Response{Success: true, Message: "Campaign user assignment updated successfully!"}, http.StatusOK)
return
}
}
// CampaignSummary returns the summary for a given campaign.
func (as *Server) CampaignSummary(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)

View File

@ -67,6 +67,7 @@ func (as *Server) registerRoutes() {
router.HandleFunc("/campaigns/{id:[0-9]+}/results", as.CampaignResults)
router.HandleFunc("/campaigns/{id:[0-9]+}/summary", as.CampaignSummary)
router.HandleFunc("/campaigns/{id:[0-9]+}/complete", as.CampaignComplete)
router.HandleFunc("/campaigns/{id:[0-9]+}/update_users", as.CampaignUpdateUsers)
router.HandleFunc("/groups/", as.Groups)
router.HandleFunc("/groups/summary", as.GroupsSummary)
router.HandleFunc("/groups/{id:[0-9]+}", as.Group)

View File

@ -713,4 +713,113 @@ func InsertGroupIntoCampaign(tx *gorm.DB, gid int64, c *Campaign) error {
}
return nil
}
// GetCampaignGroups returns the groups for a campaign
func GetCampaignGroups(cid int64) ([]Group, error) {
gids := []int64{}
err := db.Table("campaign_groups").Where("campaign_id=?", cid).Pluck("group_id", &gids).Error
if err != nil {
log.Error(err)
return nil, err
}
gs := make([]Group, len(gids))
for i, gid := range gids {
gs[i], err = GetGroupById(gid)
if err != nil {
log.Error(err)
}
}
return gs, nil
}
// UpdateCampaignUsersFromGroups creates maillogs and result entries for all group members assigned to the specified campaign
func UpdateCampaignUsersFromGroups(c *Campaign) (error) {
// ToDo: Prevent duplicates
gs, err := GetCampaignGroups(c.Id)
if err != nil {
log.Error(err)
return err
}
c.Groups = gs
totalRecipients := 0
for i, _ := range c.Groups {
totalRecipients += len(c.Groups[i].Targets)
}
resultMap := make(map[string]bool)
recipientIndex := 0
tx := db.Begin()
for _, g := range c.Groups {
// Insert a result for each target in the group
for _, t := range g.Targets {
// Remove duplicate results - we should only
// send emails to unique email addresses.
if _, ok := resultMap[t.Email]; ok {
continue
}
resultMap[t.Email] = true
sendDate := c.generateSendDate(recipientIndex, totalRecipients)
r := &Result{
BaseRecipient: BaseRecipient{
Email: t.Email,
Position: t.Position,
FirstName: t.FirstName,
LastName: t.LastName,
},
Status: StatusScheduled,
CampaignId: c.Id,
UserId: c.UserId,
SendDate: sendDate,
Reported: false,
ModifiedDate: c.CreatedDate,
}
err := r.GenerateId(tx)
if err != nil {
log.Error(err)
tx.Rollback()
return err
}
processing := false
if r.SendDate.Before(c.CreatedDate) || r.SendDate.Equal(c.CreatedDate) {
r.Status = StatusSending
processing = true
}
err = tx.Save(r).Error
if err != nil {
log.WithFields(logrus.Fields{
"email": t.Email,
}).Errorf("error creating result: %v", err)
tx.Rollback()
return err
}
c.Results = append(c.Results, *r)
log.WithFields(logrus.Fields{
"email": r.Email,
"send_date": sendDate,
}).Debug("creating maillog")
m := &MailLog{
UserId: c.UserId,
CampaignId: c.Id,
RId: r.RId,
SendDate: sendDate,
Processing: processing,
}
err = tx.Save(m).Error
if err != nil {
log.WithFields(logrus.Fields{
"email": t.Email,
}).Errorf("error creating maillog entry: %v", err)
tx.Rollback()
return err
}
recipientIndex++
}
}
return tx.Commit().Error
}

View File

@ -122,6 +122,22 @@ func GetGroups(uid int64) ([]Group, error) {
return gs, nil
}
func GetGroupById(gid int64) (Group, error) {
g := Group{}
err := db.Where("id=?", gid).Find(&g).Error
if err != nil {
log.Error(err)
return g, err
}
g.Targets, err = GetTargets(g.Id)
if err != nil {
log.Error(err)
}
return g, nil
}
// GetGroupSummaries returns the summaries for the groups
// created by the given uid.
func GetGroupSummaries(uid int64) (GroupSummaries, error) {

View File

@ -199,6 +199,44 @@ function completeCampaign() {
})
}
// Updates a campaign's user assignments after prompting the user
function updateCampaignUserAssignment() {
Swal.fire({
title: "Are you sure?",
text: "This will update the campaign's user assignments.",
type: "warning",
animation: false,
showCancelButton: true,
confirmButtonText: "Update user assignments",
confirmButtonColor: "#428bca",
reverseButtons: true,
allowOutsideClick: false,
showLoaderOnConfirm: true,
preConfirm: function () {
return new Promise(function (resolve, reject) {
api.campaignId.updateUsers(campaign.id)
.success(function (msg) {
resolve()
})
.error(function (data) {
reject(data.responseJSON.message)
})
})
}
}).then(function (result) {
if(result.value){
Swal.fire(
'Campaign User assignment Updated!',
'This campaign\'s user assignment has been updated!',
'success'
);
}
$('button:contains("OK")').on('click', function () {
location.href = '/campaigns/' + campaign.id;
})
})
}
// Exports campaign results as a CSV file
function exportAsCSV(scope) {
exportHTML = $("#exportButton").html()

View File

@ -104,6 +104,10 @@ var api = {
complete: function (id) {
return query("/campaigns/" + id + "/complete", "GET", {}, true)
},
// updateUsers() - Upates a campaign's user assignments at POST /campaigns/:id/update_users
updateUsers: function(id) {
return query("/campaigns/" + id + "/update_users", "GET", {}, true);
},
// summary() - Queries the API for GET /campaigns/summary
summary: function (id) {
return query("/campaigns/" + id + "/summary", "GET", {}, true)

View File

@ -29,6 +29,9 @@
<button id="complete_button" type="button" class="btn btn-blue" data-toggle="tooltip" onclick="completeCampaign()">
<i class="fa fa-flag-checkered"></i> Complete
</button>
<button id="complete_button" type="button" class="btn btn-blue" data-toggle="tooltip" onclick="updateCampaignUserAssignment()">
<i class="fa fa-users"></i> Update users
</button>
<button type="button" class="btn btn-danger" data-toggle="tooltip" onclick="deleteCampaign()">
<i class="fa fa-trash-o fa-lg"></i> Delete
</button>