ability to mock stores stubbed
This commit is contained in:
@@ -1,6 +1,10 @@
|
|||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
|
|
||||||
|
-- mock etsy sync group listings
|
||||||
|
|
||||||
|
DROP TABLE mock.shop_etsy_sync_group_listings;
|
||||||
|
DROP TABLE mock.shop_etsy_listings;
|
||||||
|
|
||||||
-- mock ebay sync group listings
|
-- mock ebay sync group listings
|
||||||
|
|
||||||
@@ -71,6 +75,7 @@ DROP TABLE mock.sync_groups;
|
|||||||
|
|
||||||
-- mock shops
|
-- mock shops
|
||||||
|
|
||||||
|
DROP TABLE mock.shop_etsy;
|
||||||
DROP TABLE mock.shop_ebay;
|
DROP TABLE mock.shop_ebay;
|
||||||
DROP TABLE mock.shop_walmart_marketplace;
|
DROP TABLE mock.shop_walmart_marketplace;
|
||||||
DROP TABLE mock.shop_amazon;
|
DROP TABLE mock.shop_amazon;
|
||||||
|
|||||||
@@ -138,6 +138,16 @@ CREATE TABLE mock.shop_ebay (
|
|||||||
FOREIGN KEY (account_id, user_id) REFERENCES mock.accounts (account_id, user_id)
|
FOREIGN KEY (account_id, user_id) REFERENCES mock.accounts (account_id, user_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE mock.shop_etsy (
|
||||||
|
user_id TEXT NOT NULL REFERENCES oauth_users (user_id),
|
||||||
|
account_id INTEGER NOT NULL REFERENCES mock.accounts (account_id),
|
||||||
|
shop_id TEXT NOT NULL,
|
||||||
|
name TEXT NOT NULL CHECK (char_length(name) > 0),
|
||||||
|
|
||||||
|
PRIMARY KEY (account_id, shop_id),
|
||||||
|
FOREIGN KEY (account_id, user_id) REFERENCES mock.accounts (account_id, user_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
-- mock sync group listings
|
-- mock sync group listings
|
||||||
|
|
||||||
@@ -467,6 +477,32 @@ CREATE TABLE mock.shop_ebay_sync_group_listings (
|
|||||||
FOREIGN KEY (shop_id, listing_id) REFERENCES mock.shop_ebay_listings (shop_id, listing_id)
|
FOREIGN KEY (shop_id, listing_id) REFERENCES mock.shop_ebay_listings (shop_id, listing_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- mock etsy sync group listings
|
||||||
|
|
||||||
|
CREATE TABLE mock.shop_etsy_listings (
|
||||||
|
account_id INTEGER NOT NULL REFERENCES mock.accounts (account_id),
|
||||||
|
shop_id TEXT NOT NULL,
|
||||||
|
listing_id TEXT NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (shop_id, listing_id),
|
||||||
|
FOREIGN KEY (account_id, shop_id) REFERENCES mock.shop_etsy (account_id, shop_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE mock.shop_etsy_sync_group_listings (
|
||||||
|
account_id INTEGER NOT NULL REFERENCES mock.accounts (account_id),
|
||||||
|
sync_group_id INTEGER NOT NULL REFERENCES mock.sync_groups (sync_group_id),
|
||||||
|
shop_id TEXT NOT NULL,
|
||||||
|
listing_id TEXT NOT NULL,
|
||||||
|
order_index INTEGER NOT NULL,
|
||||||
|
|
||||||
|
-- allow each shop to have at most ONE listing per sync group
|
||||||
|
UNIQUE (sync_group_id, shop_id),
|
||||||
|
FOREIGN KEY (account_id, shop_id) REFERENCES mock.shop_etsy (account_id, shop_id),
|
||||||
|
FOREIGN KEY (sync_group_id, order_index) REFERENCES mock.sync_group_listing_order_indexes (sync_group_id, order_index),
|
||||||
|
FOREIGN KEY (shop_id, listing_id) REFERENCES mock.shop_etsy_listings (shop_id, listing_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GRANT ALL ON SCHEMA mock TO PUBLIC;
|
GRANT ALL ON SCHEMA mock TO PUBLIC;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 209 KiB After Width: | Height: | Size: 225 KiB |
@@ -109,6 +109,31 @@ entity "**shop_ecwid_sync_group_listings**" {
|
|||||||
*""order_index"": //integer //
|
*""order_index"": //integer //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**shop_etsy**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""shop_id"": //text [PK]//
|
||||||
|
--
|
||||||
|
*""user_id"": //text [FK]//
|
||||||
|
*""name"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
|
entity "**shop_etsy_listings**" {
|
||||||
|
+ ""shop_id"": //text [PK]//
|
||||||
|
+ ""listing_id"": //text [PK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer [FK]//
|
||||||
|
*""name"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
|
entity "**shop_etsy_sync_group_listings**" {
|
||||||
|
--
|
||||||
|
*""account_id"": //integer [FK]//
|
||||||
|
*""sync_group_id"": //integer [FK]//
|
||||||
|
*""shop_id"": //text [FK]//
|
||||||
|
*""listing_id"": //text //
|
||||||
|
*""order_index"": //integer //
|
||||||
|
}
|
||||||
|
|
||||||
entity "**shop_shopify**" {
|
entity "**shop_shopify**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""shop_id"": //text [PK]//
|
+ ""shop_id"": //text [PK]//
|
||||||
@@ -404,6 +429,26 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_ecwid_sync_group_listings**" }-- "**sync_group_listing_order_indexes**"
|
"**shop_ecwid_sync_group_listings**" }-- "**sync_group_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**shop_etsy**" }-- "**accounts**"
|
||||||
|
|
||||||
|
"**shop_etsy**" }-- "**accounts**"
|
||||||
|
|
||||||
|
"**shop_etsy**" }-- "**public.oauth_users**"
|
||||||
|
|
||||||
|
"**shop_etsy_listings**" }-- "**accounts**"
|
||||||
|
|
||||||
|
"**shop_etsy_listings**" }-- "**shop_etsy**"
|
||||||
|
|
||||||
|
"**shop_etsy_sync_group_listings**" }-- "**accounts**"
|
||||||
|
|
||||||
|
"**shop_etsy_sync_group_listings**" }-- "**shop_etsy**"
|
||||||
|
|
||||||
|
"**shop_etsy_sync_group_listings**" }-- "**shop_etsy_listings**"
|
||||||
|
|
||||||
|
"**shop_etsy_sync_group_listings**" }-- "**sync_groups**"
|
||||||
|
|
||||||
|
"**shop_etsy_sync_group_listings**" }-- "**sync_group_listing_order_indexes**"
|
||||||
|
|
||||||
"**shop_shopify**" }-- "**accounts**"
|
"**shop_shopify**" }-- "**accounts**"
|
||||||
|
|
||||||
"**shop_shopify**" }-- "**accounts**"
|
"**shop_shopify**" }-- "**accounts**"
|
||||||
|
|||||||
@@ -5,4 +5,5 @@ import "errors"
|
|||||||
var (
|
var (
|
||||||
ErrNotFound = errors.New("not found")
|
ErrNotFound = errors.New("not found")
|
||||||
ErrConflict = errors.New("conflict")
|
ErrConflict = errors.New("conflict")
|
||||||
|
ErrBadRequest = errors.New("bad request")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"ruben/inventory2/internal/consts"
|
"ruben/inventory2/internal/consts"
|
||||||
"ruben/inventory2/internal/logging"
|
"ruben/inventory2/internal/logging"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
)
|
)
|
||||||
@@ -59,6 +60,11 @@ type (
|
|||||||
AccountShopIDs
|
AccountShopIDs
|
||||||
ListingID string
|
ListingID string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MockShop struct {
|
||||||
|
AccountShopIDs
|
||||||
|
Name string
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewStore(logger *logging.Logger, db *pgxpool.Pool) *Store {
|
func NewStore(logger *logging.Logger, db *pgxpool.Pool) *Store {
|
||||||
@@ -309,6 +315,258 @@ func (db *Store) GetListingsForShop(ctx context.Context, acctID int64, platform
|
|||||||
return vs, nil
|
return vs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *Store) CreateMockShop(ctx context.Context, acctID int64, platform Platform, name string) (shopID uuid.UUID, err error) {
|
||||||
|
shopTableName, err := getMockShopTableName(platform)
|
||||||
|
if err != nil {
|
||||||
|
return uuid.Nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := db.db.Begin(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return uuid.Nil, fmt.Errorf("failed to being transaction: %w", err)
|
||||||
|
}
|
||||||
|
defer tx.Rollback(ctx)
|
||||||
|
|
||||||
|
// TODO: are we really going to just copy the id between accounts and mock.accounts?
|
||||||
|
|
||||||
|
// upsert mock account
|
||||||
|
|
||||||
|
rows, err := tx.Query(
|
||||||
|
ctx,
|
||||||
|
`
|
||||||
|
WITH existing_account(account_id, user_id) AS (
|
||||||
|
SELECT
|
||||||
|
account_id,
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
accounts
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
), existing_mock_account AS (
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
accounts
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
), inserted_mock_account AS (
|
||||||
|
INSERT INTO
|
||||||
|
mock.accounts (
|
||||||
|
account_id,
|
||||||
|
user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
account_id,
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
existing_account
|
||||||
|
ON CONFLICT
|
||||||
|
DO NOTHING
|
||||||
|
RETURNING
|
||||||
|
user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
COALESCE(ia.user_id, ea.user_id)
|
||||||
|
FROM
|
||||||
|
inserted_mock_account ia
|
||||||
|
FULL OUTER JOIN
|
||||||
|
existing_mock_account ea
|
||||||
|
USING
|
||||||
|
(user_id)
|
||||||
|
`,
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return uuid.Nil, fmt.Errorf("test query failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
userID, err := pgx.CollectExactlyOneRow(rows, pgx.RowTo[string])
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
return uuid.Nil, fmt.Errorf("%w: account not found", consts.ErrNotFound)
|
||||||
|
}
|
||||||
|
return uuid.Nil, fmt.Errorf("failed to scan rows: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the mock shop
|
||||||
|
|
||||||
|
shopID = uuid.New()
|
||||||
|
|
||||||
|
_, err = tx.Exec(
|
||||||
|
ctx,
|
||||||
|
fmt.Sprintf(
|
||||||
|
`
|
||||||
|
INSERT INTO
|
||||||
|
%s (
|
||||||
|
user_id,
|
||||||
|
account_id,
|
||||||
|
shop_id,
|
||||||
|
name
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
@user_id,
|
||||||
|
@account_id,
|
||||||
|
@shop_id,
|
||||||
|
@name
|
||||||
|
)
|
||||||
|
`,
|
||||||
|
shopTableName,
|
||||||
|
),
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
"user_id": userID,
|
||||||
|
"shop_id": shopID,
|
||||||
|
"name": name,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return uuid.Nil, fmt.Errorf("failed to perform query to create mock shop: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Commit(ctx); err != nil {
|
||||||
|
return uuid.Nil, fmt.Errorf("failed to commit transaction: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return shopID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Store) ListMockShopsForPlatform(ctx context.Context, acctID int64, platform Platform) ([]MockShop, error) {
|
||||||
|
shopTableName, err := getMockShopTableName(platform)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := db.db.Query(
|
||||||
|
ctx,
|
||||||
|
fmt.Sprintf(
|
||||||
|
`
|
||||||
|
SELECT
|
||||||
|
shop_id,
|
||||||
|
name
|
||||||
|
FROM
|
||||||
|
%s
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
`,
|
||||||
|
shopTableName,
|
||||||
|
),
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to perform query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vs, err := pgx.CollectRows(rows, pgx.RowToStructByNameLax[struct {
|
||||||
|
Shop_id uuid.UUID
|
||||||
|
Name string
|
||||||
|
}])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to scan rows: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
shops := make([]MockShop, len(vs))
|
||||||
|
for i, v := range vs {
|
||||||
|
shops[i] = MockShop{
|
||||||
|
AccountShopIDs: AccountShopIDs{
|
||||||
|
AccountIDs: AccountIDs{
|
||||||
|
AccountID: acctID,
|
||||||
|
},
|
||||||
|
Platform: platform,
|
||||||
|
ShopID: v.Shop_id.String(),
|
||||||
|
},
|
||||||
|
Name: v.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shops, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Store) GetMockShop(ctx context.Context, acctID int64, platform Platform, shopID string) (*MockShop, error) {
|
||||||
|
shopTableName, err := getMockShopTableName(platform)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := db.db.Query(
|
||||||
|
ctx,
|
||||||
|
fmt.Sprintf(
|
||||||
|
`
|
||||||
|
SELECT
|
||||||
|
name
|
||||||
|
FROM
|
||||||
|
%s
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
AND shop_id = @shop_id
|
||||||
|
`,
|
||||||
|
shopTableName,
|
||||||
|
),
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
"shop_id": shopID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to perform query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
name, err := pgx.CollectExactlyOneRow(rows, pgx.RowTo[string])
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
return nil, consts.ErrNotFound
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("failed to scan rows: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &MockShop{
|
||||||
|
AccountShopIDs: AccountShopIDs{
|
||||||
|
AccountIDs: AccountIDs{
|
||||||
|
AccountID: acctID,
|
||||||
|
},
|
||||||
|
Platform: platform,
|
||||||
|
ShopID: shopID,
|
||||||
|
},
|
||||||
|
Name: name,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMockShopTableName(platform Platform) (string, error) {
|
||||||
|
switch platform {
|
||||||
|
case Amazon:
|
||||||
|
return "mock.shop_amazon", nil
|
||||||
|
case BigCartel:
|
||||||
|
return "mock.shop_big_cartel", nil
|
||||||
|
case Ebay:
|
||||||
|
return "mock.shop_ebay", nil
|
||||||
|
case Ecwid:
|
||||||
|
return "mock.shop_ecwid", nil
|
||||||
|
case Etsy:
|
||||||
|
return "mock.shop_etsy", nil
|
||||||
|
case Shopify:
|
||||||
|
return "mock.shop_shopify", nil
|
||||||
|
case SquareOnline:
|
||||||
|
return "mock.shop_square_online", nil
|
||||||
|
case Squarespace:
|
||||||
|
return "mock.shop_squarespace", nil
|
||||||
|
case Tiktok:
|
||||||
|
return "mock.shop_tiktok", nil
|
||||||
|
case WalmartMarketplace:
|
||||||
|
return "mock.shop_walmart_marketplace", nil
|
||||||
|
case Wix:
|
||||||
|
return "mock.shop_wix", nil
|
||||||
|
case WooCommerce:
|
||||||
|
return "mock.shop_woo_commerce", nil
|
||||||
|
case Zoho:
|
||||||
|
return "mock.shop_zoho", nil
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("%w: unrecognized platform", consts.ErrBadRequest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// additional context
|
// additional context
|
||||||
|
|
||||||
func (db *Store) GetAccountPointerByUserID(ctx context.Context, userID string) (*Account, error) {
|
func (db *Store) GetAccountPointerByUserID(ctx context.Context, userID string) (*Account, error) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package accounts
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StoreWithContext struct {
|
type StoreWithContext struct {
|
||||||
@@ -47,6 +48,18 @@ func (v_ctx *StoreWithContext) GetListingsForShop(acctID int64, platform Platfor
|
|||||||
return v_ctx.Store.GetListingsForShop(v_ctx.ctx, acctID, platform, shopID)
|
return v_ctx.Store.GetListingsForShop(v_ctx.ctx, acctID, platform, shopID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v_ctx *StoreWithContext) CreateMockShop(acctID int64, platform Platform, name string) (uuid.UUID, error) {
|
||||||
|
return v_ctx.Store.CreateMockShop(v_ctx.ctx, acctID, platform, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v_ctx *StoreWithContext) ListMockShopsForPlatform(acctID int64, platform Platform) ([]MockShop, error) {
|
||||||
|
return v_ctx.Store.ListMockShopsForPlatform(v_ctx.ctx, acctID, platform)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v_ctx *StoreWithContext) GetMockShop(acctID int64, platform Platform, shopID string) (*MockShop, error) {
|
||||||
|
return v_ctx.Store.GetMockShop(v_ctx.ctx, acctID, platform, shopID)
|
||||||
|
}
|
||||||
|
|
||||||
func (v_ctx *StoreWithContext) GetAccountPointerByUserID(userID string) (*Account, error) {
|
func (v_ctx *StoreWithContext) GetAccountPointerByUserID(userID string) (*Account, error) {
|
||||||
return v_ctx.Store.GetAccountPointerByUserID(v_ctx.ctx, userID)
|
return v_ctx.Store.GetAccountPointerByUserID(v_ctx.ctx, userID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,10 @@ func Routes(
|
|||||||
}
|
}
|
||||||
|
|
||||||
r.POST("", response.Handler(as.createAccount))
|
r.POST("", response.Handler(as.createAccount))
|
||||||
r.PUT("/:acctID/platforms/:platform/order-index", pub.Publish("/:acctID/platforms"), response.Handler(as.setOrderOfPlatformOnAccountPage))
|
|
||||||
|
platformGroup := r.Group("/:acctID/platforms/:platform", pub.Publish("/:acctID/platforms"))
|
||||||
|
platformGroup.PUT("/order-index", response.Handler(as.setOrderOfPlatformOnAccountPage))
|
||||||
|
platformGroup.POST("/shops/mocks", response.Handler(as.createMockShop))
|
||||||
|
|
||||||
syncGroups := r.Group("/:acctID/inventory/sync-groups")
|
syncGroups := r.Group("/:acctID/inventory/sync-groups")
|
||||||
syncGroups.POST("", pub.Publish("/:acctID/inventory/sync-groups"), response.Handler(as.saveNewSyncGroup))
|
syncGroups.POST("", pub.Publish("/:acctID/inventory/sync-groups"), response.Handler(as.saveNewSyncGroup))
|
||||||
@@ -251,6 +254,53 @@ func (s *accountSubrouter) setOrderOfPlatformOnAccountPage(c *gin.Context) (resp
|
|||||||
return response.StatusNoContent(), nil
|
return response.StatusNoContent(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// POST /:acctID/platforms/:platform/shops/mocks
|
||||||
|
func (s *accountSubrouter) createMockShop(c *gin.Context) (response.Response, error) {
|
||||||
|
acctID := auth.GetIdentity(c).Account.AccountID
|
||||||
|
|
||||||
|
// validate parameters
|
||||||
|
|
||||||
|
var platform accounts.Platform
|
||||||
|
if v := c.Param("platform"); v == "" {
|
||||||
|
return nil, response.BadRequest().
|
||||||
|
Msg("no platform provided")
|
||||||
|
} else if p, err := accounts.NewPlatform(v); err != nil {
|
||||||
|
return nil, response.BadRequest().
|
||||||
|
Wrap(err).
|
||||||
|
Msgf("unrecognized platform: %v", v)
|
||||||
|
} else {
|
||||||
|
platform = p
|
||||||
|
}
|
||||||
|
|
||||||
|
var name string
|
||||||
|
if v, ok := c.GetPostForm("name"); !ok || v == "" {
|
||||||
|
return nil, response.BadRequest().
|
||||||
|
Msg("no order-index provided")
|
||||||
|
} else {
|
||||||
|
name = v
|
||||||
|
}
|
||||||
|
|
||||||
|
s.log.Warnf("not implemented: mock store created: account_id = %d; platform = %s; name = %s", acctID, platform, name)
|
||||||
|
|
||||||
|
// create the mock account
|
||||||
|
|
||||||
|
id, err := s.accts.CreateMockShop(c, acctID, platform, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to save record: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
location := fmt.Sprintf("/ui/accounts/%d/platforms/%s/mock-shops/%s", acctID, lowerSnakeCase(platform), id)
|
||||||
|
|
||||||
|
var res response.Response
|
||||||
|
if c.GetHeader("HX-Request") == "true" {
|
||||||
|
res = response.StatusCreated()
|
||||||
|
} else {
|
||||||
|
res = response.SeeOther(location)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.HXLocation(location), nil
|
||||||
|
}
|
||||||
|
|
||||||
func lowerSnakeCase(s accounts.Platform) string {
|
func lowerSnakeCase(s accounts.Platform) string {
|
||||||
return strings.ToLower(strings.Join(strings.Split(string(s), " "), "_"))
|
return strings.ToLower(strings.Join(strings.Split(string(s), " "), "_"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,21 @@ func Routes(
|
|||||||
"lowerSnakeCase": func(s string) string {
|
"lowerSnakeCase": func(s string) string {
|
||||||
return strings.ToLower(strings.Join(strings.Split(s, " "), "_"))
|
return strings.ToLower(strings.Join(strings.Split(s, " "), "_"))
|
||||||
},
|
},
|
||||||
|
"splitSnakeCase": func(s string) string {
|
||||||
|
return strings.Join(strings.Split(s, "_"), " ")
|
||||||
|
},
|
||||||
|
"capitalize": func(s string) string {
|
||||||
|
ss := strings.Split(s, " ")
|
||||||
|
us := make([]string, len(ss))
|
||||||
|
for i, v := range ss {
|
||||||
|
if len(v) == 0 {
|
||||||
|
us[i] = v
|
||||||
|
} else {
|
||||||
|
us[i] = strings.ToUpper(v[:1]) + v[1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.Join(us, " ")
|
||||||
|
},
|
||||||
|
|
||||||
// arithmetic
|
// arithmetic
|
||||||
"addInt": func(a, b int) int {
|
"addInt": func(a, b int) int {
|
||||||
|
|||||||
+85
-690
File diff suppressed because it is too large
Load Diff
+38
-5
@@ -1,11 +1,15 @@
|
|||||||
{{- $acctID := .PathParams.acctID }}
|
{{- $acctID := .PathParams.acctID }}
|
||||||
{{- $platform := .PathParams.platform }}
|
{{- $platform := .PathParams.platform }}
|
||||||
|
{{- $parsedPlatform := parsePlatform $platform }}
|
||||||
|
|
||||||
<details
|
<details
|
||||||
open
|
name={{$platform}}
|
||||||
class="
|
class="
|
||||||
flex flex-col items-center
|
flex flex-col items-center
|
||||||
open:mb-[2em]
|
open:pb-[1em]
|
||||||
|
open:border-b-[1px]
|
||||||
|
open:border-b-background
|
||||||
|
open:mb-[1em]
|
||||||
|
|
||||||
group/create-mock-shop
|
group/create-mock-shop
|
||||||
|
|
||||||
@@ -52,7 +56,35 @@
|
|||||||
</h4>
|
</h4>
|
||||||
</summary>
|
</summary>
|
||||||
|
|
||||||
<form class="px-[2em] py-[0.5em]">
|
<ul class="flex flex-col items-center my-[0.5em]">
|
||||||
|
{{- $shops := .Accounts.ListMockShopsForPlatform $acctID $parsedPlatform }}
|
||||||
|
{{- range $shop := $shops }}
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href={{ printf "/ui/accounts/%d/platforms/%s/mock-shops/%s" $acctID $platform $shop.ShopID }}
|
||||||
|
hx-boost="false"
|
||||||
|
class="
|
||||||
|
border-foreground
|
||||||
|
border-solid
|
||||||
|
border-thin
|
||||||
|
bg-card
|
||||||
|
font-semibold
|
||||||
|
rounded-md
|
||||||
|
p-[0.5em]
|
||||||
|
m-[0.25em]
|
||||||
|
block
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ $shop.Name }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{{- end }}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<form
|
||||||
|
class="px-[2em] py-[0.5em]"
|
||||||
|
hx-post={{printf "/api/accounts/%d/platforms/%s/shops/mocks" $acctID $platform}}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
grid grid-cols-[max-content_max-content]
|
grid grid-cols-[max-content_max-content]
|
||||||
@@ -72,6 +104,8 @@
|
|||||||
bg-card
|
bg-card
|
||||||
border-input border-[1px] rounded
|
border-input border-[1px] rounded
|
||||||
"
|
"
|
||||||
|
required
|
||||||
|
minlength="5"
|
||||||
/>
|
/>
|
||||||
<!--label>
|
<!--label>
|
||||||
TODO:
|
TODO:
|
||||||
@@ -95,7 +129,7 @@
|
|||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details
|
<details
|
||||||
open
|
name={{$platform}}
|
||||||
class="
|
class="
|
||||||
flex flex-col items-center
|
flex flex-col items-center
|
||||||
|
|
||||||
@@ -144,6 +178,5 @@
|
|||||||
</h4>
|
</h4>
|
||||||
</summary>
|
</summary>
|
||||||
|
|
||||||
{{/* TODO: how to remove the platform from the path twice? */}}
|
|
||||||
{{ component ( printf "/accounts/%d/platform-links/%s" $acctID $platform ) }}
|
{{ component ( printf "/accounts/%d/platform-links/%s" $acctID $platform ) }}
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
{{ $acctID := .Identity.Account.AccountID }}
|
||||||
|
{{ $platform := parsePlatform .PathParams.platform }}
|
||||||
|
{{ $shopID := .PathParams.shopID }}
|
||||||
|
{{- $shop := .Accounts.GetMockShop $acctID $platform $shopID }}
|
||||||
|
|
||||||
|
<h1 class="mt-[1em] text-center">
|
||||||
|
{{ $shop.Name }}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<p class="m-[1em] text-center font-display">
|
||||||
|
{{ .PathParams.platform | splitSnakeCase | capitalize }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="mt-[5em] text-center block">
|
||||||
|
A work in progress...
|
||||||
|
</h2>
|
||||||
Reference in New Issue
Block a user