From 987386ea8743359d9989aa7fb630343b7177a827 Mon Sep 17 00:00:00 2001 From: Angel Beltran Date: Tue, 3 Mar 2026 00:29:27 -0700 Subject: [PATCH] protoype: list raw events on mock mode reports page --- domains/reports/events.go | 81 +++++++++ domains/reports/reports.go | 32 ++++ domains/reports/store_with_context.go | 25 +++ main.go | 6 +- server/server.go | 3 + server/ui/router.go | 6 + styles/index.css | 158 ++++-------------- .../{acctID.int64}/reports/mock.html.tmpl | 69 ++++++++ 8 files changed, 252 insertions(+), 128 deletions(-) create mode 100644 domains/reports/events.go create mode 100644 domains/reports/reports.go create mode 100644 domains/reports/store_with_context.go create mode 100644 templates/pages/accounts/{acctID.int64}/reports/mock.html.tmpl diff --git a/domains/reports/events.go b/domains/reports/events.go new file mode 100644 index 0000000..4b895db --- /dev/null +++ b/domains/reports/events.go @@ -0,0 +1,81 @@ +package reports + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "time" + + "github.com/jackc/pgx/v5" + + "ruben/inventory2/consts" + "ruben/inventory2/domains/accounts" +) + +type ( + RawShopEvent struct { + Platform accounts.Platform + ShopID string + EventTimestamp time.Time + EventID string + RawPayload json.RawMessage + } +) + +func (db *Store) GetRawShopEvents(ctx context.Context, acctID int64, platform accounts.Platform, shopID string) ([]RawShopEvent, error) { + if _, err := db.accts.GetMockShop(ctx, acctID, platform, shopID); err != nil { + if errors.Is(err, consts.ErrNotFound) { + return nil, fmt.Errorf("shop not found: %w", err) + } + return nil, fmt.Errorf("failed to look up shop: %w", err) + } + + rows, err := db.db.Query( + ctx, + ` + SELECT + event_timestamp, + event_id, + raw_payload + FROM + mock.raw_shop_events + WHERE + platform = @platform + AND shop_id = @shop_id + `, + pgx.NamedArgs{ + "platform": platform, + "shop_id": shopID, + }, + ) + if err != nil { + return nil, fmt.Errorf("failed to perform query: %w", err) + } + + vs, err := pgx.CollectRows(rows, pgx.RowToStructByNameLax[struct { + Event_timestamp time.Time + Event_id string + Raw_payload json.RawMessage + }]) + if err != nil { + return nil, fmt.Errorf("failed to scan rows: %w", err) + } + + fmt.Println("vs:", vs) + + evts := make([]RawShopEvent, len(vs)) + for i, v := range vs { + evts[i] = RawShopEvent{ + Platform: platform, + ShopID: shopID, + EventTimestamp: v.Event_timestamp, + EventID: v.Event_id, + RawPayload: v.Raw_payload, + } + } + + fmt.Println("evts:", evts) + + return evts, nil +} diff --git a/domains/reports/reports.go b/domains/reports/reports.go new file mode 100644 index 0000000..0feca73 --- /dev/null +++ b/domains/reports/reports.go @@ -0,0 +1,32 @@ +package reports + +import ( + "context" + + "github.com/jackc/pgx/v5/pgxpool" + + "ruben/inventory2/domains/accounts" + "ruben/inventory2/logging" +) + +//go:generate concurry -s Store + +type ( + Store struct { + log *logging.Logger + db *pgxpool.Pool + accts *accounts.Store + } +) + +func NewStore(logger *logging.Logger, db *pgxpool.Pool, accts *accounts.Store) *Store { + return &Store{ + log: logger, + db: db, + accts: accts, + } +} + +func (db *Store) WithContext(ctx context.Context) *StoreWithContext { + return NewStoreWithContext(ctx, db) +} diff --git a/domains/reports/store_with_context.go b/domains/reports/store_with_context.go new file mode 100644 index 0000000..6a8b555 --- /dev/null +++ b/domains/reports/store_with_context.go @@ -0,0 +1,25 @@ +// Code generated by concurry DO NOT EDIT. +// https://github.com/angelbeltran/concurry +// concurry +package reports + +import ( + "context" + "ruben/inventory2/domains/accounts" +) + +type StoreWithContext struct { + ctx context.Context + *Store +} + +func NewStoreWithContext(ctx context.Context, v *Store) *StoreWithContext { + return &StoreWithContext{ + ctx: ctx, + Store: v, + } +} + +func (v_ctx *StoreWithContext) GetRawShopEvents(acctID int64, platform accounts.Platform, shopID string) ([]RawShopEvent, error) { + return v_ctx.Store.GetRawShopEvents(v_ctx.ctx, acctID, platform, shopID) +} diff --git a/main.go b/main.go index 4176ac4..c24a8c1 100644 --- a/main.go +++ b/main.go @@ -25,6 +25,7 @@ import ( "ruben/inventory2/domains/authentication" etsy_platform "ruben/inventory2/domains/platforms/etsy" "ruben/inventory2/domains/raw_events" + "ruben/inventory2/domains/reports" "ruben/inventory2/logging" "ruben/inventory2/server" ) @@ -151,11 +152,14 @@ func runAuthProcesses(ctx context.Context, auth *authentication.Authenticator) < } func runServer(ctx context.Context, logger *logging.Logger, connPool *pgxpool.Pool, auth *authentication.Authenticator) <-chan error { + accts := accounts.NewStore(logger, connPool) + r := server.NewRouter( logger.WithGroup("server"), "./", raw_events.NewStore(logger.WithGroup("raw-event-store"), connPool), - accounts.NewStore(logger, connPool), + accts, + reports.NewStore(logger, connPool, accts), etsy_platform.NewPlatform( logger, func(acctID int64) string { diff --git a/server/server.go b/server/server.go index 47f009b..7b91d54 100644 --- a/server/server.go +++ b/server/server.go @@ -12,6 +12,7 @@ import ( "ruben/inventory2/domains/authentication" etsy_platform "ruben/inventory2/domains/platforms/etsy" "ruben/inventory2/domains/raw_events" + "ruben/inventory2/domains/reports" "ruben/inventory2/logging" "ruben/inventory2/server/api" "ruben/inventory2/server/auth" @@ -30,6 +31,7 @@ func NewRouter( contentDir string, rawEvents *raw_events.Store, accts *accounts.Store, + reps *reports.Store, etsy *etsy_platform.Platform, authr *authentication.Authenticator, ) *Router { @@ -59,6 +61,7 @@ func NewRouter( "/ui", rawEvents, accts, + reps, etsy, authM.Authenticate(), ) diff --git a/server/ui/router.go b/server/ui/router.go index 167d905..25e312b 100644 --- a/server/ui/router.go +++ b/server/ui/router.go @@ -16,6 +16,7 @@ import ( "ruben/inventory2/domains/accounts" etsy_platform "ruben/inventory2/domains/platforms/etsy" "ruben/inventory2/domains/raw_events" + "ruben/inventory2/domains/reports" "ruben/inventory2/logging" "ruben/inventory2/server/auth" "ruben/inventory2/server/response" @@ -28,6 +29,7 @@ type ( templater *templater.Templater rawEvents *raw_events.Store accts *accounts.Store + reports *reports.Store etsy *etsy_platform.Platform } @@ -44,6 +46,7 @@ func Routes( uiPath string, rawEvents *raw_events.Store, accts *accounts.Store, + reps *reports.Store, etsy *etsy_platform.Platform, authenticate gin.HandlerFunc, ) { @@ -143,6 +146,7 @@ func Routes( }), rawEvents: rawEvents, accts: accts, + reports: reps, etsy: etsy, } @@ -189,6 +193,8 @@ func (s *webpageRouter) serveTemplate(c *gin.Context) (response.Response, error) newURLCalculator(r.URL), "Accounts", s.accts.WithContext(ctx), + "Reports", + s.reports.WithContext(ctx), "Etsy", s.etsy.WithContext(ctx), "MockMode", diff --git a/styles/index.css b/styles/index.css index ca1e853..0599e09 100644 --- a/styles/index.css +++ b/styles/index.css @@ -197,29 +197,6 @@ .bottom-0 { bottom: calc(var(--spacing) * 0); } - .grid-table-\[1fr_1fr_1fr_1fr_1fr_1fr\] { - &:is(table) { - display: grid; - grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; - & > :is(thead, tbody, tfoot) { - grid-column-start: 1; - grid-column-end: -1; - display: grid; - grid-template-columns: subgrid; - & > tr { - grid-column-start: 1; - grid-column-end: -1; - display: grid; - grid-template-columns: subgrid; - & > th, & > td { - grid-column: span 1; - align-content: center; - text-align: center; - } - } - } - } - } .grid-table-\[1fr_1fr_1fr_1fr_1fr_1fr_1fr\] { &:is(table) { display: grid; @@ -297,6 +274,9 @@ .my-\[0\.5em\] { margin-block: 0.5em; } + .my-\[1em\] { + margin-block: 1em; + } .my-\[1rem\] { margin-block: 1rem; } @@ -312,9 +292,6 @@ .mt-\[3em\] { margin-top: 3em; } - .mb-0 { - margin-bottom: calc(var(--spacing) * 0); - } .mb-\[0\.5em\] { margin-bottom: 0.5em; } @@ -327,9 +304,6 @@ .mb-\[3em\] { margin-bottom: 3em; } - .ml-\[0\.5em\] { - margin-left: 0.5em; - } .ml-\[1em\] { margin-left: 1em; } @@ -399,9 +373,6 @@ .flex-shrink { flex-shrink: 1; } - .flex-grow { - flex-grow: 1; - } .flex-grow-\[1\] { flex-grow: 1; } @@ -417,12 +388,6 @@ .basis-full { flex-basis: 100%; } - .border-collapse { - border-collapse: collapse; - } - .transform { - transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,); - } .animate-pulse { animation: var(--animate-pulse); } @@ -533,15 +498,6 @@ .border-\[gray\] { border-color: gray; } - .border-\[red\] { - border-color: red; - } - .border-\[white\] { - border-color: white; - } - .border-accent { - border-color: var(--accent); - } .border-border { border-color: var(--border); } @@ -554,9 +510,6 @@ .border-sidebar-border { border-color: var(--sidebar-border); } - .bg-\[red\] { - background-color: red; - } .bg-accent { background-color: var(--accent); } @@ -569,9 +522,6 @@ .bg-card { background-color: var(--card); } - .bg-none { - background-image: none; - } .p-\[0\.5em\] { padding: 0.5em; } @@ -590,6 +540,9 @@ .py-\[1em\] { padding-block: 1em; } + .py-\[2em\] { + padding-block: 2em; + } .pt-\[1em\] { padding-top: 1em; } @@ -611,9 +564,6 @@ .font-display { font-family: var(--display-family); } - .font-text { - font-family: var(--text-family); - } .text-lg { font-size: var(--text-lg); line-height: var(--tw-leading, var(--text-lg--line-height)); @@ -629,10 +579,6 @@ .text-\[1\.5em\] { font-size: 1.5em; } - .font-\[1\.5em\] { - --tw-font-weight: 1.5em; - font-weight: 1.5em; - } .font-bold { --tw-font-weight: var(--font-weight-bold); font-weight: var(--font-weight-bold); @@ -644,12 +590,6 @@ .text-nowrap { text-wrap: nowrap; } - .text-wrap { - text-wrap: wrap; - } - .text-inherit { - color: inherit; - } .capitalize { text-transform: capitalize; } @@ -659,24 +599,13 @@ .underline { text-decoration-line: underline; } - .outline { - outline-style: var(--tw-outline-style); - outline-width: 1px; - } .outline-1 { outline-style: var(--tw-outline-style); outline-width: 1px; } - .outline-\[1px\] { - outline-style: var(--tw-outline-style); - outline-width: 1px; - } .outline-\(--table-tfoot\) { outline-color: var(--table-tfoot); } - .outline-\[red\] { - outline-color: red; - } .filter { filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); } @@ -690,16 +619,6 @@ transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); transition-duration: var(--tw-duration, var(--default-transition-duration)); } - .\*\:bg-background { - :is(& > *) { - background-color: var(--background); - } - } - .\*\*\:bg-background { - :is(& *) { - background-color: var(--background); - } - } .not-open\:mb-\[1em\] { &:not(*:is([open], :popover-open, :open)) { margin-bottom: 1em; @@ -906,26 +825,11 @@ } } } - .active\:bg-accent { - &:active { - background-color: var(--accent); - } - } .active\:bg-accent-secondary { &:active { background-color: var(--accent-secondary); } } - .active\:bg-muted { - &:active { - background-color: var(--muted); - } - } - .active\:bg-secondary { - &:active { - background-color: var(--secondary); - } - } .disabled\:cursor-not-allowed { &:disabled { cursor: not-allowed; @@ -1274,26 +1178,6 @@ } } } -@property --tw-rotate-x { - syntax: "*"; - inherits: false; -} -@property --tw-rotate-y { - syntax: "*"; - inherits: false; -} -@property --tw-rotate-z { - syntax: "*"; - inherits: false; -} -@property --tw-skew-x { - syntax: "*"; - inherits: false; -} -@property --tw-skew-y { - syntax: "*"; - inherits: false; -} @property --tw-border-style { syntax: "*"; inherits: false; @@ -1376,6 +1260,26 @@ inherits: false; initial-value: 1; } +@property --tw-rotate-x { + syntax: "*"; + inherits: false; +} +@property --tw-rotate-y { + syntax: "*"; + inherits: false; +} +@property --tw-rotate-z { + syntax: "*"; + inherits: false; +} +@property --tw-skew-x { + syntax: "*"; + inherits: false; +} +@property --tw-skew-y { + syntax: "*"; + inherits: false; +} @property --tw-content { syntax: "*"; initial-value: ""; @@ -1393,11 +1297,6 @@ @layer properties { @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) { *, ::before, ::after, ::backdrop { - --tw-rotate-x: initial; - --tw-rotate-y: initial; - --tw-rotate-z: initial; - --tw-skew-x: initial; - --tw-skew-y: initial; --tw-border-style: solid; --tw-font-weight: initial; --tw-outline-style: solid; @@ -1417,6 +1316,11 @@ --tw-scale-x: 1; --tw-scale-y: 1; --tw-scale-z: 1; + --tw-rotate-x: initial; + --tw-rotate-y: initial; + --tw-rotate-z: initial; + --tw-skew-x: initial; + --tw-skew-y: initial; --tw-content: ""; --tw-leading: initial; } diff --git a/templates/pages/accounts/{acctID.int64}/reports/mock.html.tmpl b/templates/pages/accounts/{acctID.int64}/reports/mock.html.tmpl new file mode 100644 index 0000000..1395f04 --- /dev/null +++ b/templates/pages/accounts/{acctID.int64}/reports/mock.html.tmpl @@ -0,0 +1,69 @@ +{{- $acctID := .Identity.Account.AccountID }} + +{{- $platform := .Platform }} +{{- if not $platform }} + {{- $platform = .Request.URL.Query.Get "platform" }} +{{- end }} + +{{- $shopID := .ShopID }} +{{- if not $shopID }} + {{- $shopID = .Request.URL.Query.Get "shop-id" }} +{{- end }} + + + + + +

+ Platform: {{ $platform }} +

+ +{{- $evts := "" }} +{{- if and $platform $shopID }} + {{- $parsedPlatform := parsePlatform $platform }} + {{- $evts = .Reports.GetRawShopEvents $acctID $parsedPlatform $shopID }} +{{- end }} + + + + + + {{/**/}} + + + + +{{- if $evts }} + {{- range $evt := $evts }} + + + {{/**/}} + + + {{- end }} +{{- end }} + + +
TimeEventIDEvent
{{$evt.EventTimestamp}}{{$evt.EventID}}{{prettyPrintJSON $evt.RawPayload}}