B: Add getting metrics for cards
This commit is contained in:
parent
9c70466f30
commit
16a236aba1
|
@ -3,6 +3,8 @@ package controllers
|
||||||
import (
|
import (
|
||||||
"git.preston-baxter.com/Preston_PLB/capstone/frontend-service/templates"
|
"git.preston-baxter.com/Preston_PLB/capstone/frontend-service/templates"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
"golang.org/x/text/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetAddActionForm(c *gin.Context) {
|
func GetAddActionForm(c *gin.Context) {
|
||||||
|
@ -22,3 +24,81 @@ func GetAddActionForm(c *gin.Context) {
|
||||||
|
|
||||||
renderTempl(c, templates.DashboardActionModal(accounts))
|
renderTempl(c, templates.DashboardActionModal(accounts))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DashboardMetric struct {
|
||||||
|
Title string
|
||||||
|
PrimaryValue string
|
||||||
|
SecondaryValue string
|
||||||
|
Subtitle string
|
||||||
|
}
|
||||||
|
|
||||||
|
type dashboardMetricFunc func(c *gin.Context) *DashboardMetric
|
||||||
|
|
||||||
|
var metricFuncMap = map[string]dashboardMetricFunc{"default": defaultMetricFunction, "events_received": eventsRecievedMetricFunction, "streams_scheduled": streamsScheduledMetricFunction}
|
||||||
|
|
||||||
|
func GetMetricCard(c *gin.Context) {
|
||||||
|
user := getUserFromContext(c)
|
||||||
|
if user == nil {
|
||||||
|
log.Warnf("Could not find user in context. Trying to redner Action form")
|
||||||
|
badRequest(c, "No user available in context")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if metric, ok := c.GetQuery("metric"); ok {
|
||||||
|
if metricFunc, mok := metricFuncMap[metric]; mok {
|
||||||
|
renderDashboardMetric(c, &metricFunc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//send default metric function
|
||||||
|
log.Warn("Failed to find metricfunc")
|
||||||
|
defaultFunc := metricFuncMap["default"]
|
||||||
|
renderDashboardMetric(c, &defaultFunc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultMetricFunction(c *gin.Context) *DashboardMetric {
|
||||||
|
return &DashboardMetric{
|
||||||
|
Title: "Err",
|
||||||
|
PrimaryValue: "0.00",
|
||||||
|
SecondaryValue: "0.00",
|
||||||
|
Subtitle: "something went wrong",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderDashboardMetric(c *gin.Context, metricFunc *dashboardMetricFunc) {
|
||||||
|
metric := (*metricFunc)(c)
|
||||||
|
renderTempl(c, templates.DashboardCard(metric.Title, metric.PrimaryValue, metric.SecondaryValue, metric.Subtitle))
|
||||||
|
}
|
||||||
|
|
||||||
|
func eventsRecievedMetricFunction(c *gin.Context) *DashboardMetric {
|
||||||
|
user := getUserFromContext(c)
|
||||||
|
|
||||||
|
events, err := mongo.AggregateVendorEventReport(user.Id)
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Errorf("Failed to find events for user: %s", user.Id.Hex())
|
||||||
|
return defaultMetricFunction(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
totalEvents := 0
|
||||||
|
biggestVendor := 0
|
||||||
|
for index, event := range events {
|
||||||
|
totalEvents += event.Count
|
||||||
|
if events[biggestVendor].Count < event.Count {
|
||||||
|
biggestVendor = index
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
p := message.NewPrinter(language.English)
|
||||||
|
return &DashboardMetric{
|
||||||
|
Title: "Events Recieved",
|
||||||
|
PrimaryValue: p.Sprintf("%d", totalEvents),
|
||||||
|
SecondaryValue: p.Sprintf("Most events came from: %s", events[biggestVendor].Name),
|
||||||
|
Subtitle: "thats a lot of events",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func streamsScheduledMetricFunction(c *gin.Context) *DashboardMetric {
|
||||||
|
return defaultMetricFunction(c)
|
||||||
|
}
|
||||||
|
|
|
@ -48,6 +48,9 @@ func BuildRouter(r *gin.Engine) {
|
||||||
//Dashboard Forms
|
//Dashboard Forms
|
||||||
dashboardForms := dashboard.Group("/forms")
|
dashboardForms := dashboard.Group("/forms")
|
||||||
dashboardForms.GET("/addAction", GetAddActionForm)
|
dashboardForms.GET("/addAction", GetAddActionForm)
|
||||||
|
//Dashboard Components
|
||||||
|
dashboardComponents := dashboard.Group("/components")
|
||||||
|
dashboardComponents.GET("/metric_card", GetMetricCard)
|
||||||
|
|
||||||
//Vendor stuff
|
//Vendor stuff
|
||||||
vendor := r.Group("/vendor")
|
vendor := r.Group("/vendor")
|
||||||
|
|
|
@ -76,6 +76,61 @@ func (db *DB) FindAuditTrailForUser(userId primitive.ObjectID) ([]models.EventRe
|
||||||
return events, actions, nil
|
return events, actions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) FindEventRecievedByVendorId(id string) []models.EventRecieved {
|
func (db *DB) FindEventsRecievedByUserId(userId primitive.ObjectID) ([]models.EventRecieved, error) {
|
||||||
return []models.EventRecieved{}
|
conf := config.Config()
|
||||||
|
opts := options.Find()
|
||||||
|
res, err := db.client.Database(conf.Mongo.EntDb).Collection(conf.Mongo.EntCol).Find(context.Background(), bson.M{"user_id": userId, "obj_info.ent": models.EVENT_RECIEVED_TYPE}, opts)
|
||||||
|
if err != nil {
|
||||||
|
if err == mongo.ErrNoDocuments {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
events := []models.EventRecieved{}
|
||||||
|
err = res.All(context.Background(), &events)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return events, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type VendorEventReport struct {
|
||||||
|
Count int `bson:"count"`
|
||||||
|
Name string `bson:"_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) AggregateVendorEventReport(userId primitive.ObjectID) ([]VendorEventReport, error) {
|
||||||
|
conf := config.Config()
|
||||||
|
opts := options.Aggregate().SetAllowDiskUse(false)
|
||||||
|
|
||||||
|
aggregation := bson.A{
|
||||||
|
bson.D{{Key: "$match", Value: bson.D{{Key: "obj_info.ent", Value: "audit_event_recieved"}}}},
|
||||||
|
bson.D{
|
||||||
|
{Key: "$group",
|
||||||
|
Value: bson.D{
|
||||||
|
{Key: "_id", Value: "$vendor_name"},
|
||||||
|
{Key: "count", Value: bson.D{{Key: "$sum", Value: 1}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := db.client.Database(conf.Mongo.EntDb).Collection(conf.Mongo.EntCol).Aggregate(context.Background(), aggregation, opts)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if err == mongo.ErrNoDocuments {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
events := []VendorEventReport{}
|
||||||
|
err = res.All(context.Background(), &events)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return events, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ templ DashboardNav(user *models.User) {
|
||||||
<button
|
<button
|
||||||
class="cursor-pointer text-black opacity-50 md:hidden px-3 py-1 text-xl leading-none bg-transparent rounded border border-solid border-transparent"
|
class="cursor-pointer text-black opacity-50 md:hidden px-3 py-1 text-xl leading-none bg-transparent rounded border border-solid border-transparent"
|
||||||
type="button"
|
type="button"
|
||||||
onclick="toggleNavbar('example-collapse-sidebar')"
|
onclick="toggleNavbar('example-collapse-sidebar')"
|
||||||
>
|
>
|
||||||
<i class="fas fa-bars"></i>
|
<i class="fas fa-bars"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@ -87,7 +87,7 @@ templ DashboardNav(user *models.User) {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="cursor-pointer text-black opacity-50 md:hidden px-3 py-1 text-xl leading-none bg-transparent rounded border border-solid border-transparent"
|
class="cursor-pointer text-black opacity-50 md:hidden px-3 py-1 text-xl leading-none bg-transparent rounded border border-solid border-transparent"
|
||||||
onclick="toggleNavbar('example-collapse-sidebar')"
|
onclick="toggleNavbar('example-collapse-sidebar')"
|
||||||
>
|
>
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-times"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@ -167,7 +167,7 @@ templ DashboardContentNav(user *models.User) {
|
||||||
<ul
|
<ul
|
||||||
class="flex-col md:flex-row list-none items-center hidden md:flex"
|
class="flex-col md:flex-row list-none items-center hidden md:flex"
|
||||||
>
|
>
|
||||||
<a class="text-blueGray-500 block" href="#pablo" onclick="openDropdown(event,'user-dropdown')">
|
<a class="text-blueGray-500 block" href="#pablo" onclick="openDropdown(event,'user-dropdown')">
|
||||||
<div class="items-center flex">
|
<div class="items-center flex">
|
||||||
<span
|
<span
|
||||||
class="w-12 h-12 text-sm text-white bg-blueGray-200 inline-flex items-center justify-center rounded-full"
|
class="w-12 h-12 text-sm text-white bg-blueGray-200 inline-flex items-center justify-center rounded-full"
|
||||||
|
@ -206,8 +206,12 @@ templ DashboardContentNav(user *models.User) {
|
||||||
</nav>
|
</nav>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
templ DashboardCardLoader(kind string) {
|
||||||
|
<div class="w-full lg:w-6/12 xl:w-6/12 px-4" hx-get={ fmt.Sprintf("/dashboard/components/metric_card?metric=%s", kind) } hx-trigger="load" hx-swap="outerHTML"></div>
|
||||||
|
}
|
||||||
|
|
||||||
templ DashboardCard(title, primaryVal, secondaryVal, subtitle string) {
|
templ DashboardCard(title, primaryVal, secondaryVal, subtitle string) {
|
||||||
<div class="w-full lg:w-6/12 xl:w-4/12 px-4">
|
<div class="w-full lg:w-6/12 xl:w-6/12 px-4">
|
||||||
<div class="relative flex flex-col min-w-0 break-words bg-white rounded mb-6 xl:mb-0 shadow-lg">
|
<div class="relative flex flex-col min-w-0 break-words bg-white rounded mb-6 xl:mb-0 shadow-lg">
|
||||||
<div class="flex-auto p-4">
|
<div class="flex-auto p-4">
|
||||||
<div class="flex flex-wrap">
|
<div class="flex flex-wrap">
|
||||||
|
@ -242,7 +246,7 @@ templ DashboardVendorDropDown() {
|
||||||
<div class="flex flex-wrap float-right">
|
<div class="flex flex-wrap float-right">
|
||||||
<div class="w-full sm:w-6/12 md:w-4/12 px-4">
|
<div class="w-full sm:w-6/12 md:w-4/12 px-4">
|
||||||
<div class="relative inline-flex align-middle w-full">
|
<div class="relative inline-flex align-middle w-full">
|
||||||
<button class="text-white font-bold uppercase text-sm px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 bg-blueGray-500 ease-linear transition-all duration-150" type="button" onclick="openDropdown(event,'dropdown-id')">
|
<button class="text-white font-bold uppercase text-sm px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 bg-blueGray-500 ease-linear transition-all duration-150" type="button" onclick="openDropdown(event,'dropdown-id')">
|
||||||
+
|
+
|
||||||
</button>
|
</button>
|
||||||
<div class="hidden bg-white text-base z-50 float-left py-2 list-none text-left rounded shadow-lg mt-1" style="min-width:12rem" id="dropdown-id">
|
<div class="hidden bg-white text-base z-50 float-left py-2 list-none text-left rounded shadow-lg mt-1" style="min-width:12rem" id="dropdown-id">
|
||||||
|
@ -323,7 +327,7 @@ templ DashboardVendorWidget(vendors []models.VendorAccount) {
|
||||||
templ DashboardActionModalForm(vendors []models.VendorAccount) {
|
templ DashboardActionModalForm(vendors []models.VendorAccount) {
|
||||||
<div class="relative p-6 flex-auto">
|
<div class="relative p-6 flex-auto">
|
||||||
<form class="space-y-4 text-gray-700" action="/dashboard/action/add" method="POST">
|
<form class="space-y-4 text-gray-700" action="/dashboard/action/add" method="POST">
|
||||||
<div class="flex flex-wrap">
|
<div class="flex flex-wrap -mx-2 space-y-4 md:space-y-0">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div class="relative inline-block w-full text-gray-700">
|
<div class="relative inline-block w-full text-gray-700">
|
||||||
<select class="w-full h-10 pl-3 pr-6 text-base placeholder-gray-600 border rounded-lg appearance-none focus:shadow-outline" placeholder="Choose action source" name="source">
|
<select class="w-full h-10 pl-3 pr-6 text-base placeholder-gray-600 border rounded-lg appearance-none focus:shadow-outline" placeholder="Choose action source" name="source">
|
||||||
|
@ -334,9 +338,6 @@ templ DashboardActionModalForm(vendors []models.VendorAccount) {
|
||||||
<option value="nil">None Available</option>
|
<option value="nil">None Available</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
<div class="absolute inset-y-0 right-0 flex items-center px-2 pointer-events-none">
|
|
||||||
<svg class="w-4 h-4 fill-current" viewBox="0 0 20 20"><path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" fill-rule="evenodd"></path></svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -351,17 +352,14 @@ templ DashboardActionModalForm(vendors []models.VendorAccount) {
|
||||||
<option value="nil">None Available</option>
|
<option value="nil">None Available</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
<div class="absolute inset-y-0 right-0 flex items-center px-2 pointer-events-none">
|
|
||||||
<svg class="w-4 h-4 fill-current" viewBox="0 0 20 20"><path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" fill-rule="evenodd"></path></svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-end p-6 border-t border-solid border-blueGray-200 rounded-b">
|
<div class="flex items-center justify-end p-6 border-t border-solid border-blueGray-200 rounded-b">
|
||||||
<button class="text-gray-400 background-transparent font-bold uppercase px-6 py-2 text-sm outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150" type="button" onclick="toggleModal('add-action-modal')">
|
<button class="text-gray-400 background-transparent font-bold uppercase px-6 py-2 text-sm outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150" type="button" onclick="toggleModal('add-action-modal')">
|
||||||
Close
|
Close
|
||||||
</button>
|
</button>
|
||||||
<button class="bg-blue-700 text-white active:bg-blue-900 font-bold uppercase text-sm px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150" type="submit">
|
<button class="bg-blue-700 text-white active:bg-blue-300 font-bold uppercase text-sm px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150" type="submit">
|
||||||
Save Changes
|
Save Changes
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -379,8 +377,8 @@ templ DashboardActionModal(vendors []models.VendorAccount) {
|
||||||
<h3 class="text-3xl font-semibold">
|
<h3 class="text-3xl font-semibold">
|
||||||
Modal Title
|
Modal Title
|
||||||
</h3>
|
</h3>
|
||||||
<button class="p-1 ml-auto bg-transparent border-0 text-black opacity-5 float-right text-3xl leading-none font-semibold outline-none focus:outline-none" onclick="toggleModal('add-action-modal')">
|
<button class="p-1 ml-auto bg-transparent border-0 float-right text-3xl leading-none font-semibold outline-none focus:outline-none" onclick="toggleModal('add-action-modal')">
|
||||||
<span class="bg-transparent text-black opacity-5 h-6 w-6 text-2xl block outline-none focus:outline-none">
|
<span class="bg-transparent text-gray-500 h-6 w-6 text-2xl block outline-none focus:outline-none">
|
||||||
×
|
×
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -485,9 +483,8 @@ templ DashboardContent(user *models.User, vendorAccounts []models.VendorAccount,
|
||||||
<div>
|
<div>
|
||||||
<!-- Card stats -->
|
<!-- Card stats -->
|
||||||
<div class="flex flex-wrap">
|
<div class="flex flex-wrap">
|
||||||
@DashboardCard("Events Recieved", "420,696", "3.3%", "Since Last Month")
|
@DashboardCardLoader("events_received")
|
||||||
@DashboardCard("Live Streams Scheduled", "420,696", "3.3%", "Since Last Month")
|
@DashboardCardLoader("streams_scheduled")
|
||||||
@DashboardCard("Failed Schedules", "420,696", "3.3%", "Since Last Month")
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"webhook_version": "0.0.60",
|
"webhook_version": "0.0.60",
|
||||||
"frontend_version": "0.0.40"
|
"frontend_version": "0.0.41"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue