protoype: list raw events on mock mode reports page
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(),
|
||||
)
|
||||
|
||||
@@ -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",
|
||||
|
||||
+31
-127
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
|
||||
<label for="shop-selector">
|
||||
Select a Shop
|
||||
</label>
|
||||
<select
|
||||
id="shop-selector"
|
||||
hx-swap=""
|
||||
hx-get="/ui/accounts/{{$acctID}}/reports/mock"
|
||||
hx-vals="js:{
|
||||
platform: console.log(event.target.value.replace(/-.*/, '')) || event.target.value.replace(/-.*/, ''),
|
||||
'shop-id': console.log(event.target.value.replace(/[^-]*-/, '')) || event.target.value.replace(/[^-]*-/, ''),
|
||||
}"
|
||||
hx-push-url="true"
|
||||
hx-target="body"
|
||||
>
|
||||
{{- range $shop := .Accounts.GetMockShops $acctID }}
|
||||
{{- $isSelected := and (eq $platform $shop.Platform) (eq $shopID $shop.ShopID) }}
|
||||
<option
|
||||
value="{{ $shop.Platform }}-{{ $shop.ShopID }}"
|
||||
{{ if $isSelected }}selected{{end}}
|
||||
>
|
||||
{{ $shop.Name }}
|
||||
</option>
|
||||
{{- end }}
|
||||
</select>
|
||||
|
||||
<h3 class="m-[1em]">
|
||||
Platform: {{ $platform }}
|
||||
</h3>
|
||||
|
||||
{{- $evts := "" }}
|
||||
{{- if and $platform $shopID }}
|
||||
{{- $parsedPlatform := parsePlatform $platform }}
|
||||
{{- $evts = .Reports.GetRawShopEvents $acctID $parsedPlatform $shopID }}
|
||||
{{- end }}
|
||||
|
||||
<table id="raw-event-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Time</td>
|
||||
{{/*<td>EventID</td>*/}}
|
||||
<td>Event</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{- if $evts }}
|
||||
{{- range $evt := $evts }}
|
||||
<tr>
|
||||
<td>{{$evt.EventTimestamp}}</td>
|
||||
{{/*<td>{{$evt.EventID}}</td>*/}}
|
||||
<td>{{prettyPrintJSON $evt.RawPayload}}</td>
|
||||
</tr>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
Reference in New Issue
Block a user