Added summary routes for groups.

Routes:
/api/groups/summary
/api/groups/:id/summary

The UI is now using these routes for the "Users & Groups" page.
pull/539/merge
Jordan Wright 2017-01-14 17:26:04 -06:00
parent 9dfe54ac3d
commit 7453fd3b48
8 changed files with 133 additions and 41 deletions

View File

@ -214,6 +214,20 @@ func API_Groups(w http.ResponseWriter, r *http.Request) {
} }
} }
// API_Groups_Summary returns a summary of the groups owned by the current user.
func API_Groups_Summary(w http.ResponseWriter, r *http.Request) {
switch {
case r.Method == "GET":
gs, err := models.GetGroupSummaries(ctx.Get(r, "user_id").(int64))
if err != nil {
Logger.Println(err)
JSONResponse(w, models.Response{Success: false, Message: err.Error()}, http.StatusInternalServerError)
return
}
JSONResponse(w, gs, http.StatusOK)
}
}
// API_Groups_Id returns details about the requested group. // API_Groups_Id returns details about the requested group.
// If the group is not valid, API_Groups_Id returns null. // If the group is not valid, API_Groups_Id returns null.
func API_Groups_Id(w http.ResponseWriter, r *http.Request) { func API_Groups_Id(w http.ResponseWriter, r *http.Request) {
@ -253,6 +267,21 @@ func API_Groups_Id(w http.ResponseWriter, r *http.Request) {
} }
} }
// API_Groups_Id_Summary returns a summary of the groups owned by the current user.
func API_Groups_Id_Summary(w http.ResponseWriter, r *http.Request) {
switch {
case r.Method == "GET":
vars := mux.Vars(r)
id, _ := strconv.ParseInt(vars["id"], 0, 64)
g, err := models.GetGroupSummary(id, ctx.Get(r, "user_id").(int64))
if err != nil {
JSONResponse(w, models.Response{Success: false, Message: "Group not found"}, http.StatusNotFound)
return
}
JSONResponse(w, g, http.StatusOK)
}
}
// API_Templates handles the functionality for the /api/templates endpoint // API_Templates handles the functionality for the /api/templates endpoint
func API_Templates(w http.ResponseWriter, r *http.Request) { func API_Templates(w http.ResponseWriter, r *http.Request) {
switch { switch {

View File

@ -54,7 +54,9 @@ func CreateAdminRouter() http.Handler {
api.HandleFunc("/campaigns/{id:[0-9]+}/summary", Use(API_Campaign_Id_Summary, mid.RequireAPIKey)) api.HandleFunc("/campaigns/{id:[0-9]+}/summary", Use(API_Campaign_Id_Summary, mid.RequireAPIKey))
api.HandleFunc("/campaigns/{id:[0-9]+}/complete", Use(API_Campaigns_Id_Complete, mid.RequireAPIKey)) api.HandleFunc("/campaigns/{id:[0-9]+}/complete", Use(API_Campaigns_Id_Complete, mid.RequireAPIKey))
api.HandleFunc("/groups/", Use(API_Groups, mid.RequireAPIKey)) api.HandleFunc("/groups/", Use(API_Groups, mid.RequireAPIKey))
api.HandleFunc("/groups/summary", Use(API_Groups_Summary, 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("/groups/{id:[0-9]+}/summary", Use(API_Groups_Id_Summary, mid.RequireAPIKey))
api.HandleFunc("/templates/", Use(API_Templates, mid.RequireAPIKey)) api.HandleFunc("/templates/", Use(API_Templates, mid.RequireAPIKey))
api.HandleFunc("/templates/{id:[0-9]+}", Use(API_Templates_Id, mid.RequireAPIKey)) api.HandleFunc("/templates/{id:[0-9]+}", Use(API_Templates_Id, mid.RequireAPIKey))
api.HandleFunc("/pages/", Use(API_Pages, mid.RequireAPIKey)) api.HandleFunc("/pages/", Use(API_Pages, mid.RequireAPIKey))

View File

@ -18,6 +18,22 @@ type Group struct {
Targets []Target `json:"targets" sql:"-"` Targets []Target `json:"targets" sql:"-"`
} }
// GroupSummaries is a struct representing the overview of Groups.
type GroupSummaries struct {
Total int64 `json:"total"`
Groups []GroupSummary `json:"groups"`
}
// GroupSummary represents a summary of the Group model. The only
// difference is that, instead of listing the Targets (which could be expensive
// for large groups), it lists the target count.
type GroupSummary struct {
Id int64 `json:"id"`
Name string `json:"name"`
ModifiedDate time.Time `json:"modified_date"`
NumTargets int64 `json:"num_targets"`
}
// GroupTarget is used for a many-to-many relationship between 1..* Groups and 1..* Targets // GroupTarget is used for a many-to-many relationship between 1..* Groups and 1..* Targets
type GroupTarget struct { type GroupTarget struct {
GroupId int64 `json:"-"` GroupId int64 `json:"-"`
@ -71,6 +87,27 @@ func GetGroups(uid int64) ([]Group, error) {
return gs, nil return gs, nil
} }
// GetGroupSummaries returns the summaries for the groups
// created by the given uid.
func GetGroupSummaries(uid int64) (GroupSummaries, error) {
gs := GroupSummaries{}
query := db.Table("groups").Where("user_id=?", uid)
err := query.Select("id, name, modified_date").Scan(&gs.Groups).Error
if err != nil {
Logger.Println(err)
return gs, err
}
for i := range gs.Groups {
query = db.Table("group_targets").Where("group_id=?", gs.Groups[i].Id)
err = query.Count(&gs.Groups[i].NumTargets).Error
if err != nil {
return gs, err
}
}
gs.Total = int64(len(gs.Groups))
return gs, nil
}
// GetGroup returns the group, if it exists, specified by the given id and user_id. // GetGroup returns the group, if it exists, specified by the given id and user_id.
func GetGroup(id int64, uid int64) (Group, error) { func GetGroup(id int64, uid int64) (Group, error) {
g := Group{} g := Group{}
@ -86,6 +123,23 @@ func GetGroup(id int64, uid int64) (Group, error) {
return g, nil return g, nil
} }
// GetGroupSummary returns the summary for the requested group
func GetGroupSummary(id int64, uid int64) (GroupSummary, error) {
g := GroupSummary{}
query := db.Table("groups").Where("user_id=? and id=?", uid, id)
err := query.Select("id, name, modified_date").Scan(&g).Error
if err != nil {
Logger.Println(err)
return g, err
}
query = db.Table("group_targets").Where("group_id=?", id)
err = query.Count(&g.NumTargets).Error
if err != nil {
return g, err
}
return g, nil
}
// GetGroupByName returns the group, if it exists, specified by the given name and user_id. // GetGroupByName returns the group, if it exists, specified by the given name and user_id.
func GetGroupByName(n string, uid int64) (Group, error) { func GetGroupByName(n string, uid int64) (Group, error) {
g := Group{} g := Group{}

View File

@ -1 +1 @@
function errorFlash(e){$("#flashes").empty(),$("#flashes").append('<div style="text-align:center" class="alert alert-danger"> <i class="fa fa-exclamation-circle"></i> '+e+"</div>")}function successFlash(e){$("#flashes").empty(),$("#flashes").append('<div style="text-align:center" class="alert alert-success"> <i class="fa fa-check-circle"></i> '+e+"</div>")}function modalError(e){$("#modal\\.flashes").empty().append('<div style="text-align:center" class="alert alert-danger"> <i class="fa fa-exclamation-circle"></i> '+e+"</div>")}function query(e,t,n,r){return $.ajax({url:"/api"+e+"?api_key="+user.api_key,async:r,method:t,data:JSON.stringify(n),dataType:"json",contentType:"application/json"})}function escapeHtml(e){return $("<div/>").text(e).html()}function unescapeHtml(e){return $("<div/>").html(e).text()}var api={campaigns:{get:function(){return query("/campaigns/","GET",{},!1)},post:function(e){return query("/campaigns/","POST",e,!1)},summary:function(){return query("/campaigns/summary","GET",{},!1)}},campaignId:{get:function(e){return query("/campaigns/"+e,"GET",{},!0)},delete:function(e){return query("/campaigns/"+e,"DELETE",{},!1)},results:function(e){return query("/campaigns/"+e+"/results","GET",{},!0)},complete:function(e){return query("/campaigns/"+e+"/complete","GET",{},!0)},summary:function(e){return query("/campaigns/"+e+"/summary","GET",{},!0)}},groups:{get:function(){return query("/groups/","GET",{},!1)},post:function(e){return query("/groups/","POST",e,!1)}},groupId:{get:function(e){return query("/groups/"+e,"GET",{},!1)},put:function(e){return query("/groups/"+e.id,"PUT",e,!1)},delete:function(e){return query("/groups/"+e,"DELETE",{},!1)}},templates:{get:function(){return query("/templates/","GET",{},!1)},post:function(e){return query("/templates/","POST",e,!1)}},templateId:{get:function(e){return query("/templates/"+e,"GET",{},!1)},put:function(e){return query("/templates/"+e.id,"PUT",e,!1)},delete:function(e){return query("/templates/"+e,"DELETE",{},!1)}},pages:{get:function(){return query("/pages/","GET",{},!1)},post:function(e){return query("/pages/","POST",e,!1)}},pageId:{get:function(e){return query("/pages/"+e,"GET",{},!1)},put:function(e){return query("/pages/"+e.id,"PUT",e,!1)},delete:function(e){return query("/pages/"+e,"DELETE",{},!1)}},SMTP:{get:function(){return query("/smtp/","GET",{},!1)},post:function(e){return query("/smtp/","POST",e,!1)}},SMTPId:{get:function(e){return query("/smtp/"+e,"GET",{},!1)},put:function(e){return query("/smtp/"+e.id,"PUT",e,!1)},delete:function(e){return query("/smtp/"+e,"DELETE",{},!1)}},import_email:function(e){return query("/import/email","POST",{},!1)},clone_site:function(e){return query("/import/site","POST",e,!1)},send_test_email:function(e){return query("/util/send_test_email","POST",e,!0)}};$(document).ready(function(){$.fn.dataTable.moment("MMMM Do YYYY, h:mm:ss a"),$('[data-toggle="tooltip"]').tooltip()}); function errorFlash(e){$("#flashes").empty(),$("#flashes").append('<div style="text-align:center" class="alert alert-danger"> <i class="fa fa-exclamation-circle"></i> '+e+"</div>")}function successFlash(e){$("#flashes").empty(),$("#flashes").append('<div style="text-align:center" class="alert alert-success"> <i class="fa fa-check-circle"></i> '+e+"</div>")}function modalError(e){$("#modal\\.flashes").empty().append('<div style="text-align:center" class="alert alert-danger"> <i class="fa fa-exclamation-circle"></i> '+e+"</div>")}function query(e,t,n,r){return $.ajax({url:"/api"+e+"?api_key="+user.api_key,async:r,method:t,data:JSON.stringify(n),dataType:"json",contentType:"application/json"})}function escapeHtml(e){return $("<div/>").text(e).html()}function unescapeHtml(e){return $("<div/>").html(e).text()}var api={campaigns:{get:function(){return query("/campaigns/","GET",{},!1)},post:function(e){return query("/campaigns/","POST",e,!1)},summary:function(){return query("/campaigns/summary","GET",{},!1)}},campaignId:{get:function(e){return query("/campaigns/"+e,"GET",{},!0)},delete:function(e){return query("/campaigns/"+e,"DELETE",{},!1)},results:function(e){return query("/campaigns/"+e+"/results","GET",{},!0)},complete:function(e){return query("/campaigns/"+e+"/complete","GET",{},!0)},summary:function(e){return query("/campaigns/"+e+"/summary","GET",{},!0)}},groups:{get:function(){return query("/groups/","GET",{},!1)},post:function(e){return query("/groups/","POST",e,!1)},summary:function(){return query("/groups/summary","GET",{},!0)}},groupId:{get:function(e){return query("/groups/"+e,"GET",{},!1)},put:function(e){return query("/groups/"+e.id,"PUT",e,!1)},delete:function(e){return query("/groups/"+e,"DELETE",{},!1)}},templates:{get:function(){return query("/templates/","GET",{},!1)},post:function(e){return query("/templates/","POST",e,!1)}},templateId:{get:function(e){return query("/templates/"+e,"GET",{},!1)},put:function(e){return query("/templates/"+e.id,"PUT",e,!1)},delete:function(e){return query("/templates/"+e,"DELETE",{},!1)}},pages:{get:function(){return query("/pages/","GET",{},!1)},post:function(e){return query("/pages/","POST",e,!1)}},pageId:{get:function(e){return query("/pages/"+e,"GET",{},!1)},put:function(e){return query("/pages/"+e.id,"PUT",e,!1)},delete:function(e){return query("/pages/"+e,"DELETE",{},!1)}},SMTP:{get:function(){return query("/smtp/","GET",{},!1)},post:function(e){return query("/smtp/","POST",e,!1)}},SMTPId:{get:function(e){return query("/smtp/"+e,"GET",{},!1)},put:function(e){return query("/smtp/"+e.id,"PUT",e,!1)},delete:function(e){return query("/smtp/"+e,"DELETE",{},!1)}},import_email:function(e){return query("/import/email","POST",{},!1)},clone_site:function(e){return query("/import/site","POST",e,!1)},send_test_email:function(e){return query("/util/send_test_email","POST",e,!0)}};$(document).ready(function(){$.fn.dataTable.moment("MMMM Do YYYY, h:mm:ss a"),$('[data-toggle="tooltip"]').tooltip()});

View File

@ -1 +1 @@
function save(a){var e=[];$.each($("#targetsTable").DataTable().rows().data(),function(a,s){e.push({first_name:unescapeHtml(s[0]),last_name:unescapeHtml(s[1]),email:unescapeHtml(s[2]),position:unescapeHtml(s[3])})});var s={name:$("#name").val(),targets:e};a!=-1?(s.id=groups[a].id,api.groupId.put(s).success(function(a){successFlash("Group updated successfully!"),load(),dismiss(),$("#modal").modal("hide")}).error(function(a){modalError(a.responseJSON.message)})):api.groups.post(s).success(function(a){successFlash("Group added successfully!"),load(),dismiss(),$("#modal").modal("hide")}).error(function(a){modalError(a.responseJSON.message)})}function dismiss(){$("#targetsTable").dataTable().DataTable().clear().draw(),$("#name").val(""),$("#modal\\.flashes").empty()}function edit(a){targets=$("#targetsTable").dataTable({destroy:!0,columnDefs:[{orderable:!1,targets:"no-sort"}]}),$("#modalSubmit").unbind("click").click(function(){save(a)}),a==-1?group={}:(group=groups[a],$("#name").val(group.name),$.each(group.targets,function(a,e){targets.DataTable().row.add([escapeHtml(e.first_name),escapeHtml(e.last_name),escapeHtml(e.email),escapeHtml(e.position),'<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>']).draw()})),$("#csvupload").fileupload({dataType:"json",add:function(a,e){$("#modal\\.flashes").empty();var s=/(csv|txt)$/i,t=e.originalFiles[0].name;return t&&!s.test(t.split(".").pop())?(modalError("Unsupported file extension (use .csv or .txt)"),!1):void e.submit()},done:function(a,e){$.each(e.result,function(a,e){addTarget(e.first_name,e.last_name,e.email,e.position)}),targets.DataTable().draw()}})}function deleteGroup(a){confirm("Delete "+groups[a].name+"?")&&api.groupId.delete(groups[a].id).success(function(a){successFlash(a.message),load()})}function addTarget(a,e,s,t){var o=escapeHtml(s).toLowerCase(),r=[escapeHtml(a),escapeHtml(e),o,escapeHtml(t),'<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>'],n=targets.DataTable(),l=n.column(2,{order:"index"}).data().indexOf(o);l>=0?n.row(l,{order:"index"}).data(r):n.row.add(r)}function load(){$("#groupTable").hide(),$("#emptyMessage").hide(),$("#loading").show(),api.groups.get().success(function(a){$("#loading").hide(),a.length>0?(groups=a,$("#emptyMessage").hide(),$("#groupTable").show(),groupTable=$("#groupTable").DataTable({destroy:!0,columnDefs:[{orderable:!1,targets:"no-sort"}]}),groupTable.clear(),$.each(groups,function(a,e){var s="";$.each(e.targets,function(a,e){if(s+=e.email+", ",s.length>50)return s=s.slice(0,-3)+"...",!1}),groupTable.row.add([escapeHtml(e.name),escapeHtml(s),moment(e.modified_date).format("MMMM Do YYYY, h:mm:ss a"),"<div class='pull-right'><button class='btn btn-primary' data-toggle='modal' data-target='#modal' onclick='edit("+a+")'> <i class='fa fa-pencil'></i> </button> <button class='btn btn-danger' onclick='deleteGroup("+a+")'> <i class='fa fa-trash-o'></i> </button></div>"]).draw()})):$("#emptyMessage").show()}).error(function(){errorFlash("Error fetching groups")})}var groups=[];$(document).ready(function(){load(),$("#targetForm").submit(function(){return addTarget($("#firstName").val(),$("#lastName").val(),$("#email").val(),$("#position").val()),targets.DataTable().draw(),$("#targetForm>div>input").val(""),$("#firstName").focus(),!1}),$("#targetsTable").on("click","span>i.fa-trash-o",function(){targets.DataTable().row($(this).parents("tr")).remove().draw()}),$("#modal").on("hide.bs.modal",function(){dismiss()})}); function save(a){var e=[];$.each($("#targetsTable").DataTable().rows().data(),function(a,s){e.push({first_name:unescapeHtml(s[0]),last_name:unescapeHtml(s[1]),email:unescapeHtml(s[2]),position:unescapeHtml(s[3])})});var s={name:$("#name").val(),targets:e};a!=-1?(s.id=a,api.groupId.put(s).success(function(a){successFlash("Group updated successfully!"),load(),dismiss(),$("#modal").modal("hide")}).error(function(a){modalError(a.responseJSON.message)})):api.groups.post(s).success(function(a){successFlash("Group added successfully!"),load(),dismiss(),$("#modal").modal("hide")}).error(function(a){modalError(a.responseJSON.message)})}function dismiss(){$("#targetsTable").dataTable().DataTable().clear().draw(),$("#name").val(""),$("#modal\\.flashes").empty()}function edit(a){if(targets=$("#targetsTable").dataTable({destroy:!0,columnDefs:[{orderable:!1,targets:"no-sort"}]}),$("#modalSubmit").unbind("click").click(function(){save(a)}),a==-1);else api.groupId.get(a).success(function(a){$("#name").val(a.name),$.each(a.targets,function(a,e){targets.DataTable().row.add([escapeHtml(e.first_name),escapeHtml(e.last_name),escapeHtml(e.email),escapeHtml(e.position),'<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>']).draw()})}).error(function(){errorFlash("Error fetching group")});$("#csvupload").fileupload({dataType:"json",add:function(a,e){$("#modal\\.flashes").empty();var s=/(csv|txt)$/i,t=e.originalFiles[0].name;return t&&!s.test(t.split(".").pop())?(modalError("Unsupported file extension (use .csv or .txt)"),!1):void e.submit()},done:function(a,e){$.each(e.result,function(a,e){addTarget(e.first_name,e.last_name,e.email,e.position)}),targets.DataTable().draw()}})}function deleteGroup(a){var e=groups.find(function(e){return e.id===a});return e?void(confirm("Delete "+e.name+"?")&&api.groupId.delete(a).success(function(a){successFlash(a.message),load()})):void console.log("wat")}function addTarget(a,e,s,t){var o=escapeHtml(s).toLowerCase(),r=[escapeHtml(a),escapeHtml(e),o,escapeHtml(t),'<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>'],n=targets.DataTable(),i=n.column(2,{order:"index"}).data().indexOf(o);i>=0?n.row(i,{order:"index"}).data(r):n.row.add(r)}function load(){$("#groupTable").hide(),$("#emptyMessage").hide(),$("#loading").show(),api.groups.summary().success(function(a){if($("#loading").hide(),a.total>0){groups=a.groups,$("#emptyMessage").hide(),$("#groupTable").show();var e=$("#groupTable").DataTable({destroy:!0,columnDefs:[{orderable:!1,targets:"no-sort"}]});e.clear(),$.each(groups,function(a,s){e.row.add([escapeHtml(s.name),escapeHtml(s.num_targets),moment(s.modified_date).format("MMMM Do YYYY, h:mm:ss a"),"<div class='pull-right'><button class='btn btn-primary' data-toggle='modal' data-target='#modal' onclick='edit("+s.id+")'> <i class='fa fa-pencil'></i> </button> <button class='btn btn-danger' onclick='deleteGroup("+s.id+")'> <i class='fa fa-trash-o'></i> </button></div>"]).draw()})}else $("#emptyMessage").show()}).error(function(){errorFlash("Error fetching groups")})}var groups=[];$(document).ready(function(){load(),$("#targetForm").submit(function(){return addTarget($("#firstName").val(),$("#lastName").val(),$("#email").val(),$("#position").val()),targets.DataTable().draw(),$("#targetForm>div>input").val(""),$("#firstName").focus(),!1}),$("#targetsTable").on("click","span>i.fa-trash-o",function(){targets.DataTable().row($(this).parents("tr")).remove().draw()}),$("#modal").on("hide.bs.modal",function(){dismiss()})});

View File

@ -85,6 +85,10 @@ var api = {
// post() - Posts a group to POST /groups // post() - Posts a group to POST /groups
post: function(group) { post: function(group) {
return query("/groups/", "POST", group, false) return query("/groups/", "POST", group, false)
},
// summary() - Queries the API for GET /groups/summary
summary: function() {
return query("/groups/summary", "GET", {}, true)
} }
}, },
// groupId contains the endpoints for /groups/:id // groupId contains the endpoints for /groups/:id

View File

@ -1,7 +1,7 @@
var groups = [] var groups = []
// Save attempts to POST or PUT to /groups/ // Save attempts to POST or PUT to /groups/
function save(idx) { function save(id) {
var targets = [] var targets = []
$.each($("#targetsTable").DataTable().rows().data(), function(i, target) { $.each($("#targetsTable").DataTable().rows().data(), function(i, target) {
targets.push({ targets.push({
@ -16,10 +16,10 @@ function save(idx) {
targets: targets targets: targets
} }
// Submit the group // Submit the group
if (idx != -1) { if (id != -1) {
// If we're just editing an existing group, // If we're just editing an existing group,
// we need to PUT /groups/:id // we need to PUT /groups/:id
group.id = groups[idx].id group.id = id
api.groupId.put(group) api.groupId.put(group)
.success(function(data) { .success(function(data) {
successFlash("Group updated successfully!") successFlash("Group updated successfully!")
@ -52,7 +52,7 @@ function dismiss() {
$("#modal\\.flashes").empty() $("#modal\\.flashes").empty()
} }
function edit(idx) { function edit(id) {
targets = $("#targetsTable").dataTable({ targets = $("#targetsTable").dataTable({
destroy: true, // Destroy any other instantiated table - http://datatables.net/manual/tech-notes/3#destroy destroy: true, // Destroy any other instantiated table - http://datatables.net/manual/tech-notes/3#destroy
columnDefs: [{ columnDefs: [{
@ -61,12 +61,13 @@ function edit(idx) {
}] }]
}) })
$("#modalSubmit").unbind('click').click(function() { $("#modalSubmit").unbind('click').click(function() {
save(idx) save(id)
}) })
if (idx == -1) { if (id == -1) {
group = {} var group = {}
} else { } else {
group = groups[idx] api.groupId.get(id)
.success(function(group) {
$("#name").val(group.name) $("#name").val(group.name)
$.each(group.targets, function(i, record) { $.each(group.targets, function(i, record) {
targets.DataTable() targets.DataTable()
@ -78,6 +79,11 @@ function edit(idx) {
'<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>' '<span style="cursor:pointer;"><i class="fa fa-trash-o"></i></span>'
]).draw() ]).draw()
}); });
})
.error(function() {
errorFlash("Error fetching group")
})
} }
// Handle file uploads // Handle file uploads
$("#csvupload").fileupload({ $("#csvupload").fileupload({
@ -105,9 +111,14 @@ function edit(idx) {
}) })
} }
function deleteGroup(idx) { function deleteGroup(id) {
if (confirm("Delete " + groups[idx].name + "?")) { var group = groups.find(function(x){return x.id === id})
api.groupId.delete(groups[idx].id) if (!group) {
console.log('wat');
return
}
if (confirm("Delete " + group.name + "?")) {
api.groupId.delete(id)
.success(function(data) { .success(function(data) {
successFlash(data.message) successFlash(data.message)
load() load()
@ -150,14 +161,14 @@ function load() {
$("#groupTable").hide() $("#groupTable").hide()
$("#emptyMessage").hide() $("#emptyMessage").hide()
$("#loading").show() $("#loading").show()
api.groups.get() api.groups.summary()
.success(function(gs) { .success(function(response) {
$("#loading").hide() $("#loading").hide()
if (gs.length > 0) { if (response.total > 0) {
groups = gs groups = response.groups
$("#emptyMessage").hide() $("#emptyMessage").hide()
$("#groupTable").show() $("#groupTable").show()
groupTable = $("#groupTable").DataTable({ var groupTable = $("#groupTable").DataTable({
destroy: true, destroy: true,
columnDefs: [{ columnDefs: [{
orderable: false, orderable: false,
@ -166,22 +177,14 @@ function load() {
}); });
groupTable.clear(); groupTable.clear();
$.each(groups, function(i, group) { $.each(groups, function(i, group) {
var targets = ""
$.each(group.targets, function(i, target) {
targets += target.email + ", "
if (targets.length > 50) {
targets = targets.slice(0, -3) + "..."
return false;
}
})
groupTable.row.add([ groupTable.row.add([
escapeHtml(group.name), escapeHtml(group.name),
escapeHtml(targets), escapeHtml(group.num_targets),
moment(group.modified_date).format('MMMM Do YYYY, h:mm:ss a'), moment(group.modified_date).format('MMMM Do YYYY, h:mm:ss a'),
"<div class='pull-right'><button class='btn btn-primary' data-toggle='modal' data-target='#modal' onclick='edit(" + i + ")'>\ "<div class='pull-right'><button class='btn btn-primary' data-toggle='modal' data-target='#modal' onclick='edit(" + group.id + ")'>\
<i class='fa fa-pencil'></i>\ <i class='fa fa-pencil'></i>\
</button>\ </button>\
<button class='btn btn-danger' onclick='deleteGroup(" + i + ")'>\ <button class='btn btn-danger' onclick='deleteGroup(" + group.id + ")'>\
<i class='fa fa-trash-o'></i>\ <i class='fa fa-trash-o'></i>\
</button></div>" </button></div>"
]).draw() ]).draw()

View File

@ -50,7 +50,7 @@
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
<th>Members</th> <th># of Members</th>
<th>Modified Date</th> <th>Modified Date</th>
<th class="col-md-2 no-sort"></th> <th class="col-md-2 no-sort"></th>
</tr> </tr>