prototyped svg reports
This commit is contained in:
@@ -3,36 +3,43 @@ package accounts
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
|
||||
"ruben/inventory2/consts"
|
||||
"ruben/inventory2/domains/accounts"
|
||||
"ruben/inventory2/domains/reports"
|
||||
"ruben/inventory2/logging"
|
||||
"ruben/inventory2/server/auth"
|
||||
"ruben/inventory2/server/param"
|
||||
"ruben/inventory2/server/response"
|
||||
"ruben/inventory2/server/sse"
|
||||
"ruben/inventory2/server/ui/charts"
|
||||
)
|
||||
|
||||
type accountSubrouter struct {
|
||||
log *logging.Logger
|
||||
accts *accounts.Store
|
||||
pub *sse.UpdateNotificationPublisher
|
||||
log *logging.Logger
|
||||
accts *accounts.Store
|
||||
reports *reports.Store
|
||||
pub *sse.UpdateNotificationPublisher
|
||||
}
|
||||
|
||||
func Routes(
|
||||
r *gin.RouterGroup,
|
||||
logger *logging.Logger,
|
||||
accts *accounts.Store,
|
||||
reports *reports.Store,
|
||||
pub *sse.UpdateNotificationPublisher,
|
||||
) {
|
||||
as := &accountSubrouter{
|
||||
log: logger,
|
||||
accts: accts,
|
||||
pub: pub,
|
||||
log: logger,
|
||||
accts: accts,
|
||||
reports: reports,
|
||||
pub: pub,
|
||||
}
|
||||
|
||||
r.POST("", response.Handler(as.createAccount))
|
||||
@@ -46,6 +53,9 @@ func Routes(
|
||||
mockShops.PUT("/listings/:listing-id", response.Handler(as.updateMockListing))
|
||||
mockShops.DELETE("/listings/:listing-id", response.Handler(as.deleteMockListing))
|
||||
|
||||
mockListingCharts := r.Group("/:acctID/platforms/:platform/shops/mocks/:shop-id/listings/:listing-id/charts")
|
||||
mockListingCharts.GET("/counts", response.Handler(as.getCountsChartForMockListing))
|
||||
|
||||
syncGroups := r.Group("/:acctID/inventory/sync-groups", pub.Publish("/:acctID/inventory/sync-groups"))
|
||||
syncGroups.POST("", response.Handler(as.saveNewSyncGroup))
|
||||
|
||||
@@ -421,6 +431,135 @@ func (s *accountSubrouter) deleteMockListing(c *gin.Context) (response.Response,
|
||||
return response.StatusNoContent(), nil
|
||||
}
|
||||
|
||||
// TODO: accept dimensions
|
||||
// GET /:acctID/platforms/:platform/shops/mocks/:shop-id/charts/counts
|
||||
func (s *accountSubrouter) getCountsChartForMockListing(c *gin.Context) (response.Response, error) {
|
||||
s.log.Debug("ENDPOINT HIT")
|
||||
acctID := auth.GetIdentity(c).Account.AccountID
|
||||
|
||||
var (
|
||||
platform accounts.Platform
|
||||
shopID string
|
||||
listingID string
|
||||
width float64
|
||||
height float64
|
||||
timezone string
|
||||
)
|
||||
|
||||
err := param.Path("platform", param.Platform(&platform)).
|
||||
Path("shop-id", param.Text(&shopID)).
|
||||
Path("listing-id", param.Text(&listingID)).
|
||||
Form("width", param.Float64(&width)).
|
||||
Form("height", param.Float64(&height)).
|
||||
Form("timezone", param.Text(&timezone)).
|
||||
Unmarshal(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if width <= 0 {
|
||||
return nil, response.BadRequest().Msg("width must be positive")
|
||||
}
|
||||
if height <= 0 {
|
||||
return nil, response.BadRequest().Msg("height must be positive")
|
||||
}
|
||||
|
||||
report, err := s.reports.GetListingCountsReport(c, acctID, platform, shopID, listingID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get report: %w", err)
|
||||
}
|
||||
|
||||
/*
|
||||
bvs := make([]charts.BarValue, len(report.Counts))
|
||||
for i, v := range report.Counts {
|
||||
label := "start"
|
||||
if v.EventTimestamp != nil {
|
||||
label = v.EventTimestamp.Format(time.RFC822)
|
||||
}
|
||||
bvs[i] = charts.BarValue{
|
||||
Label: label,
|
||||
Value: float64(v.Count),
|
||||
}
|
||||
}
|
||||
|
||||
return response.StatusOK().
|
||||
HTMLReader(charts.NewBar(bvs...).SVG().GetMarkupReader()), nil
|
||||
*/
|
||||
|
||||
/*
|
||||
lvs := make([]charts.LineValue, len(report.Counts))
|
||||
for i, v := range report.Counts {
|
||||
label := "initial"
|
||||
if v.EventTimestamp != nil {
|
||||
label = v.EventTimestamp.Format(time.RFC822)
|
||||
}
|
||||
lvs[i] = charts.LineValue{
|
||||
Label: label,
|
||||
Value: float64(v.Count),
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
l, err := time.LoadLocation(timezone)
|
||||
if err != nil {
|
||||
s.log.Errorf("failed to parse time zone %s: %v; defaulting to UTC", timezone, err)
|
||||
l = time.UTC
|
||||
}
|
||||
|
||||
var times []time.Time
|
||||
for _, v := range report.Counts {
|
||||
if v.EventTimestamp == nil {
|
||||
continue
|
||||
}
|
||||
times = append(times, *v.EventTimestamp)
|
||||
}
|
||||
var (
|
||||
minTime time.Time
|
||||
maxTime time.Time
|
||||
initTime time.Time
|
||||
)
|
||||
if len(times) > 0 {
|
||||
minTime = slices.MinFunc(times, func(a, b time.Time) int {
|
||||
return int(a.UnixNano() - b.UnixNano())
|
||||
}).In(l)
|
||||
maxTime = slices.MaxFunc(times, func(a, b time.Time) int {
|
||||
return int(a.UnixNano() - b.UnixNano())
|
||||
}).In(l)
|
||||
|
||||
if len(times) > 1 {
|
||||
avgIntervalPerUpdate := time.Duration((maxTime.UnixNano() - minTime.UnixNano())) / time.Duration(len(times)-1)
|
||||
initTime = minTime.Add(-avgIntervalPerUpdate)
|
||||
} else {
|
||||
initTime = minTime.Add(-time.Minute)
|
||||
}
|
||||
}
|
||||
|
||||
lvs := make([]charts.TimeLineValue, len(report.Counts))
|
||||
for i, v := range report.Counts {
|
||||
ts := initTime
|
||||
label := fmt.Sprint(v.Count)
|
||||
if v.EventTimestamp != nil {
|
||||
ts = v.EventTimestamp.In(l)
|
||||
}
|
||||
|
||||
lvs[i] = charts.TimeLineValue{
|
||||
Label: label,
|
||||
Time: ts,
|
||||
Value: float64(v.Count),
|
||||
}
|
||||
}
|
||||
|
||||
return response.StatusOK().
|
||||
HTMLReader(
|
||||
//charts.NewLineChart(width, height, lvs...).
|
||||
charts.NewTimeLineChart(width, height, lvs...).
|
||||
Foreground("var(--foreground)").
|
||||
Background("var(--muted)").
|
||||
SVG().
|
||||
GetMarkupReader(),
|
||||
), nil
|
||||
}
|
||||
|
||||
// POST /:acctID/inventory/sync-groups/mock/draft/listings
|
||||
func (s *accountSubrouter) createMockSyncGroupListingDraft(c *gin.Context) (response.Response, error) {
|
||||
r := c.Request
|
||||
|
||||
Reference in New Issue
Block a user