mock sync group editing: edit, save, and delete listings
This commit is contained in:
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 321 KiB After Width: | Height: | Size: 414 KiB |
@@ -28,6 +28,15 @@ entity "**shop_amazon_listings**" {
|
|||||||
*""description"": //text //
|
*""description"": //text //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**shop_amazon_sync_group_editing_listings**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer //
|
||||||
|
*""shop_id"": //text [FK]//
|
||||||
|
""listing_id"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
entity "**shop_amazon_sync_group_listing_drafts**" {
|
entity "**shop_amazon_sync_group_listing_drafts**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""order_index"": //integer [PK][FK]//
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
@@ -65,6 +74,15 @@ entity "**shop_big_cartel_listings**" {
|
|||||||
*""description"": //text //
|
*""description"": //text //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**shop_big_cartel_sync_group_editing_listings**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer //
|
||||||
|
*""shop_id"": //text //
|
||||||
|
""listing_id"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
entity "**shop_big_cartel_sync_group_listing_drafts**" {
|
entity "**shop_big_cartel_sync_group_listing_drafts**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""order_index"": //integer [PK][FK]//
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
@@ -102,6 +120,15 @@ entity "**shop_ebay_listings**" {
|
|||||||
*""description"": //text //
|
*""description"": //text //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**shop_ebay_sync_group_editing_listings**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer //
|
||||||
|
*""shop_id"": //text [FK]//
|
||||||
|
""listing_id"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
entity "**shop_ebay_sync_group_listing_drafts**" {
|
entity "**shop_ebay_sync_group_listing_drafts**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""order_index"": //integer [PK]//
|
+ ""order_index"": //integer [PK]//
|
||||||
@@ -139,6 +166,15 @@ entity "**shop_ecwid_listings**" {
|
|||||||
*""description"": //text //
|
*""description"": //text //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**shop_ecwid_sync_group_editing_listings**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer //
|
||||||
|
*""shop_id"": //text [FK]//
|
||||||
|
""listing_id"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
entity "**shop_ecwid_sync_group_listing_drafts**" {
|
entity "**shop_ecwid_sync_group_listing_drafts**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""order_index"": //integer [PK][FK]//
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
@@ -176,6 +212,15 @@ entity "**shop_etsy_listings**" {
|
|||||||
*""description"": //text //
|
*""description"": //text //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**shop_etsy_sync_group_editing_listings**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""order_index"": //integer [PK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer //
|
||||||
|
*""shop_id"": //text [FK]//
|
||||||
|
""listing_id"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
entity "**shop_etsy_sync_group_listing_drafts**" {
|
entity "**shop_etsy_sync_group_listing_drafts**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""order_index"": //integer [PK]//
|
+ ""order_index"": //integer [PK]//
|
||||||
@@ -213,6 +258,15 @@ entity "**shop_shopify_listings**" {
|
|||||||
*""description"": //text //
|
*""description"": //text //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**shop_shopify_sync_group_editing_listings**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer //
|
||||||
|
*""shop_id"": //text //
|
||||||
|
""listing_id"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
entity "**shop_shopify_sync_group_listing_drafts**" {
|
entity "**shop_shopify_sync_group_listing_drafts**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""order_index"": //integer [PK][FK]//
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
@@ -250,6 +304,15 @@ entity "**shop_square_online_listings**" {
|
|||||||
*""description"": //text //
|
*""description"": //text //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**shop_square_online_sync_group_editing_listings**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer //
|
||||||
|
*""shop_id"": //text //
|
||||||
|
""listing_id"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
entity "**shop_square_online_sync_group_listing_drafts**" {
|
entity "**shop_square_online_sync_group_listing_drafts**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""order_index"": //integer [PK][FK]//
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
@@ -287,6 +350,15 @@ entity "**shop_squarespace_listings**" {
|
|||||||
*""description"": //text //
|
*""description"": //text //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**shop_squarespace_sync_group_editing_listings**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer //
|
||||||
|
*""shop_id"": //text //
|
||||||
|
""listing_id"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
entity "**shop_squarespace_sync_group_listing_drafts**" {
|
entity "**shop_squarespace_sync_group_listing_drafts**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""order_index"": //integer [PK][FK]//
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
@@ -324,6 +396,15 @@ entity "**shop_tiktok_listings**" {
|
|||||||
*""description"": //text //
|
*""description"": //text //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**shop_tiktok_sync_group_editing_listings**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer //
|
||||||
|
*""shop_id"": //text [FK]//
|
||||||
|
""listing_id"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
entity "**shop_tiktok_sync_group_listing_drafts**" {
|
entity "**shop_tiktok_sync_group_listing_drafts**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""order_index"": //integer [PK][FK]//
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
@@ -361,6 +442,15 @@ entity "**shop_walmart_marketplace_listings**" {
|
|||||||
*""description"": //text //
|
*""description"": //text //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**shop_walmart_marketplace_sync_group_editing_listings**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer //
|
||||||
|
*""shop_id"": //text //
|
||||||
|
""listing_id"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
entity "**shop_walmart_marketplace_sync_group_listing_drafts**" {
|
entity "**shop_walmart_marketplace_sync_group_listing_drafts**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""order_index"": //integer [PK][FK]//
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
@@ -398,6 +488,15 @@ entity "**shop_wix_listings**" {
|
|||||||
*""description"": //text //
|
*""description"": //text //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**shop_wix_sync_group_editing_listings**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer //
|
||||||
|
*""shop_id"": //text [FK]//
|
||||||
|
""listing_id"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
entity "**shop_wix_sync_group_listing_drafts**" {
|
entity "**shop_wix_sync_group_listing_drafts**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""order_index"": //integer [PK]//
|
+ ""order_index"": //integer [PK]//
|
||||||
@@ -435,6 +534,15 @@ entity "**shop_woo_commerce_listings**" {
|
|||||||
*""description"": //text //
|
*""description"": //text //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**shop_woo_commerce_sync_group_editing_listings**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer //
|
||||||
|
*""shop_id"": //text //
|
||||||
|
""listing_id"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
entity "**shop_woo_commerce_sync_group_listing_drafts**" {
|
entity "**shop_woo_commerce_sync_group_listing_drafts**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""order_index"": //integer [PK][FK]//
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
@@ -472,6 +580,15 @@ entity "**shop_zoho_listings**" {
|
|||||||
*""description"": //text //
|
*""description"": //text //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**shop_zoho_sync_group_editing_listings**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""order_index"": //integer [PK][FK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer //
|
||||||
|
*""shop_id"": //text [FK]//
|
||||||
|
""listing_id"": //text //
|
||||||
|
}
|
||||||
|
|
||||||
entity "**shop_zoho_sync_group_listing_drafts**" {
|
entity "**shop_zoho_sync_group_listing_drafts**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""order_index"": //integer [PK]//
|
+ ""order_index"": //integer [PK]//
|
||||||
@@ -490,6 +607,26 @@ entity "**shop_zoho_sync_group_listings**" {
|
|||||||
*""order_index"": //integer //
|
*""order_index"": //integer //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity "**sync_group_drafts**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
--
|
||||||
|
""sync_group_id"": //integer [FK]//
|
||||||
|
}
|
||||||
|
|
||||||
|
entity "**sync_group_editing**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
--
|
||||||
|
*""account_id"": //integer //
|
||||||
|
*""sync_group_id"": //integer [FK]//
|
||||||
|
*""sync_group_id"": //integer //
|
||||||
|
}
|
||||||
|
|
||||||
|
entity "**sync_group_editing_listing_order_indexes**" {
|
||||||
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
|
+ ""order_index"": //integer [PK]//
|
||||||
|
--
|
||||||
|
}
|
||||||
|
|
||||||
entity "**sync_group_listing_draft_order_indexes**" {
|
entity "**sync_group_listing_draft_order_indexes**" {
|
||||||
+ ""account_id"": //integer [PK][FK]//
|
+ ""account_id"": //integer [PK][FK]//
|
||||||
+ ""order_index"": //integer [PK]//
|
+ ""order_index"": //integer [PK]//
|
||||||
@@ -521,6 +658,12 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_amazon_listings**" ||-|| "**shop_amazon**"
|
"**shop_amazon_listings**" ||-|| "**shop_amazon**"
|
||||||
|
|
||||||
|
"**shop_amazon_sync_group_editing_listings**" ||-|| "**sync_group_editing_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**shop_amazon_sync_group_editing_listings**" }-- "**sync_group_editing**"
|
||||||
|
|
||||||
|
"**shop_amazon_sync_group_editing_listings**" }-- "**shop_amazon**"
|
||||||
|
|
||||||
"**shop_amazon_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
"**shop_amazon_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
||||||
|
|
||||||
"**shop_amazon_sync_group_listing_drafts**" }-- "**accounts**"
|
"**shop_amazon_sync_group_listing_drafts**" }-- "**accounts**"
|
||||||
@@ -545,6 +688,12 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_big_cartel_listings**" ||-|| "**shop_big_cartel**"
|
"**shop_big_cartel_listings**" ||-|| "**shop_big_cartel**"
|
||||||
|
|
||||||
|
"**shop_big_cartel_sync_group_editing_listings**" ||-|| "**sync_group_editing_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**shop_big_cartel_sync_group_editing_listings**" }-- "**shop_big_cartel**"
|
||||||
|
|
||||||
|
"**shop_big_cartel_sync_group_editing_listings**" }-- "**sync_group_editing**"
|
||||||
|
|
||||||
"**shop_big_cartel_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
"**shop_big_cartel_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
||||||
|
|
||||||
"**shop_big_cartel_sync_group_listing_drafts**" }-- "**accounts**"
|
"**shop_big_cartel_sync_group_listing_drafts**" }-- "**accounts**"
|
||||||
@@ -569,6 +718,12 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_ebay_listings**" ||-|| "**shop_ebay**"
|
"**shop_ebay_listings**" ||-|| "**shop_ebay**"
|
||||||
|
|
||||||
|
"**shop_ebay_sync_group_editing_listings**" ||-|| "**sync_group_editing_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**shop_ebay_sync_group_editing_listings**" }-- "**sync_group_editing**"
|
||||||
|
|
||||||
|
"**shop_ebay_sync_group_editing_listings**" }-- "**shop_ebay**"
|
||||||
|
|
||||||
"**shop_ebay_sync_group_listing_drafts**" }-- "**accounts**"
|
"**shop_ebay_sync_group_listing_drafts**" }-- "**accounts**"
|
||||||
|
|
||||||
"**shop_ebay_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
"**shop_ebay_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
||||||
@@ -593,6 +748,12 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_ecwid_listings**" ||-|| "**shop_ecwid**"
|
"**shop_ecwid_listings**" ||-|| "**shop_ecwid**"
|
||||||
|
|
||||||
|
"**shop_ecwid_sync_group_editing_listings**" ||-|| "**sync_group_editing_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**shop_ecwid_sync_group_editing_listings**" }-- "**sync_group_editing**"
|
||||||
|
|
||||||
|
"**shop_ecwid_sync_group_editing_listings**" }-- "**shop_ecwid**"
|
||||||
|
|
||||||
"**shop_ecwid_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
"**shop_ecwid_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
||||||
|
|
||||||
"**shop_ecwid_sync_group_listing_drafts**" }-- "**accounts**"
|
"**shop_ecwid_sync_group_listing_drafts**" }-- "**accounts**"
|
||||||
@@ -617,6 +778,12 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_etsy_listings**" ||-|| "**shop_etsy**"
|
"**shop_etsy_listings**" ||-|| "**shop_etsy**"
|
||||||
|
|
||||||
|
"**shop_etsy_sync_group_editing_listings**" ||-|| "**sync_group_editing_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**shop_etsy_sync_group_editing_listings**" }-- "**sync_group_editing**"
|
||||||
|
|
||||||
|
"**shop_etsy_sync_group_editing_listings**" }-- "**shop_etsy**"
|
||||||
|
|
||||||
"**shop_etsy_sync_group_listing_drafts**" }-- "**accounts**"
|
"**shop_etsy_sync_group_listing_drafts**" }-- "**accounts**"
|
||||||
|
|
||||||
"**shop_etsy_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
"**shop_etsy_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
||||||
@@ -641,6 +808,12 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_shopify_listings**" ||-|| "**shop_shopify**"
|
"**shop_shopify_listings**" ||-|| "**shop_shopify**"
|
||||||
|
|
||||||
|
"**shop_shopify_sync_group_editing_listings**" ||-|| "**sync_group_editing_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**shop_shopify_sync_group_editing_listings**" }-- "**shop_shopify**"
|
||||||
|
|
||||||
|
"**shop_shopify_sync_group_editing_listings**" }-- "**sync_group_editing**"
|
||||||
|
|
||||||
"**shop_shopify_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
"**shop_shopify_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
||||||
|
|
||||||
"**shop_shopify_sync_group_listing_drafts**" }-- "**accounts**"
|
"**shop_shopify_sync_group_listing_drafts**" }-- "**accounts**"
|
||||||
@@ -665,6 +838,12 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_square_online_listings**" ||-|| "**shop_square_online**"
|
"**shop_square_online_listings**" ||-|| "**shop_square_online**"
|
||||||
|
|
||||||
|
"**shop_square_online_sync_group_editing_listings**" ||-|| "**sync_group_editing_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**shop_square_online_sync_group_editing_listings**" }-- "**shop_square_online**"
|
||||||
|
|
||||||
|
"**shop_square_online_sync_group_editing_listings**" }-- "**sync_group_editing**"
|
||||||
|
|
||||||
"**shop_square_online_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
"**shop_square_online_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
||||||
|
|
||||||
"**shop_square_online_sync_group_listing_drafts**" }-- "**accounts**"
|
"**shop_square_online_sync_group_listing_drafts**" }-- "**accounts**"
|
||||||
@@ -689,6 +868,12 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_squarespace_listings**" ||-|| "**shop_squarespace**"
|
"**shop_squarespace_listings**" ||-|| "**shop_squarespace**"
|
||||||
|
|
||||||
|
"**shop_squarespace_sync_group_editing_listings**" ||-|| "**sync_group_editing_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**shop_squarespace_sync_group_editing_listings**" }-- "**shop_squarespace**"
|
||||||
|
|
||||||
|
"**shop_squarespace_sync_group_editing_listings**" }-- "**sync_group_editing**"
|
||||||
|
|
||||||
"**shop_squarespace_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
"**shop_squarespace_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
||||||
|
|
||||||
"**shop_squarespace_sync_group_listing_drafts**" }-- "**accounts**"
|
"**shop_squarespace_sync_group_listing_drafts**" }-- "**accounts**"
|
||||||
@@ -713,6 +898,12 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_tiktok_listings**" ||-|| "**shop_tiktok**"
|
"**shop_tiktok_listings**" ||-|| "**shop_tiktok**"
|
||||||
|
|
||||||
|
"**shop_tiktok_sync_group_editing_listings**" ||-|| "**sync_group_editing_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**shop_tiktok_sync_group_editing_listings**" }-- "**sync_group_editing**"
|
||||||
|
|
||||||
|
"**shop_tiktok_sync_group_editing_listings**" }-- "**shop_tiktok**"
|
||||||
|
|
||||||
"**shop_tiktok_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
"**shop_tiktok_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
||||||
|
|
||||||
"**shop_tiktok_sync_group_listing_drafts**" }-- "**accounts**"
|
"**shop_tiktok_sync_group_listing_drafts**" }-- "**accounts**"
|
||||||
@@ -737,6 +928,12 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_walmart_marketplace_listings**" ||-|| "**shop_walmart_marketplace**"
|
"**shop_walmart_marketplace_listings**" ||-|| "**shop_walmart_marketplace**"
|
||||||
|
|
||||||
|
"**shop_walmart_marketplace_sync_group_editing_listings**" ||-|| "**sync_group_editing_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**shop_walmart_marketplace_sync_group_editing_listings**" }-- "**shop_walmart_marketplace**"
|
||||||
|
|
||||||
|
"**shop_walmart_marketplace_sync_group_editing_listings**" }-- "**sync_group_editing**"
|
||||||
|
|
||||||
"**shop_walmart_marketplace_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
"**shop_walmart_marketplace_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
||||||
|
|
||||||
"**shop_walmart_marketplace_sync_group_listing_drafts**" }-- "**accounts**"
|
"**shop_walmart_marketplace_sync_group_listing_drafts**" }-- "**accounts**"
|
||||||
@@ -761,6 +958,12 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_wix_listings**" ||-|| "**shop_wix**"
|
"**shop_wix_listings**" ||-|| "**shop_wix**"
|
||||||
|
|
||||||
|
"**shop_wix_sync_group_editing_listings**" ||-|| "**sync_group_editing_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**shop_wix_sync_group_editing_listings**" }-- "**sync_group_editing**"
|
||||||
|
|
||||||
|
"**shop_wix_sync_group_editing_listings**" }-- "**shop_wix**"
|
||||||
|
|
||||||
"**shop_wix_sync_group_listing_drafts**" }-- "**accounts**"
|
"**shop_wix_sync_group_listing_drafts**" }-- "**accounts**"
|
||||||
|
|
||||||
"**shop_wix_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
"**shop_wix_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
||||||
@@ -785,6 +988,12 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_woo_commerce_listings**" ||-|| "**shop_woo_commerce**"
|
"**shop_woo_commerce_listings**" ||-|| "**shop_woo_commerce**"
|
||||||
|
|
||||||
|
"**shop_woo_commerce_sync_group_editing_listings**" ||-|| "**sync_group_editing_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**shop_woo_commerce_sync_group_editing_listings**" }-- "**shop_woo_commerce**"
|
||||||
|
|
||||||
|
"**shop_woo_commerce_sync_group_editing_listings**" }-- "**sync_group_editing**"
|
||||||
|
|
||||||
"**shop_woo_commerce_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
"**shop_woo_commerce_sync_group_listing_drafts**" ||-|| "**sync_group_listing_draft_order_indexes**"
|
||||||
|
|
||||||
"**shop_woo_commerce_sync_group_listing_drafts**" }-- "**accounts**"
|
"**shop_woo_commerce_sync_group_listing_drafts**" }-- "**accounts**"
|
||||||
@@ -809,6 +1018,12 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_zoho_listings**" ||-|| "**shop_zoho**"
|
"**shop_zoho_listings**" ||-|| "**shop_zoho**"
|
||||||
|
|
||||||
|
"**shop_zoho_sync_group_editing_listings**" ||-|| "**sync_group_editing_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**shop_zoho_sync_group_editing_listings**" }-- "**sync_group_editing**"
|
||||||
|
|
||||||
|
"**shop_zoho_sync_group_editing_listings**" }-- "**shop_zoho**"
|
||||||
|
|
||||||
"**shop_zoho_sync_group_listing_drafts**" }-- "**accounts**"
|
"**shop_zoho_sync_group_listing_drafts**" }-- "**accounts**"
|
||||||
|
|
||||||
"**shop_zoho_sync_group_listing_drafts**" }-- "**sync_group_listing_draft_order_indexes**"
|
"**shop_zoho_sync_group_listing_drafts**" }-- "**sync_group_listing_draft_order_indexes**"
|
||||||
@@ -823,6 +1038,16 @@ entity "**sync_groups**" {
|
|||||||
|
|
||||||
"**shop_zoho_sync_group_listings**" }-- "**sync_group_listing_order_indexes**"
|
"**shop_zoho_sync_group_listings**" }-- "**sync_group_listing_order_indexes**"
|
||||||
|
|
||||||
|
"**sync_group_drafts**" ||-|| "**accounts**"
|
||||||
|
|
||||||
|
"**sync_group_drafts**" }-- "**sync_groups**"
|
||||||
|
|
||||||
|
"**sync_group_editing**" ||-|| "**accounts**"
|
||||||
|
|
||||||
|
"**sync_group_editing**" }-- "**sync_groups**"
|
||||||
|
|
||||||
|
"**sync_group_editing_listing_order_indexes**" }-- "**sync_group_editing**"
|
||||||
|
|
||||||
"**sync_group_listing_draft_order_indexes**" }-- "**accounts**"
|
"**sync_group_listing_draft_order_indexes**" }-- "**accounts**"
|
||||||
|
|
||||||
"**sync_group_listing_order_indexes**" }-- "**sync_groups**"
|
"**sync_group_listing_order_indexes**" }-- "**sync_groups**"
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
@@ -45,6 +47,11 @@ type (
|
|||||||
Description string
|
Description string
|
||||||
Count int64
|
Count int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ListingWithOrderIndex struct {
|
||||||
|
Listing
|
||||||
|
OrderIndex int
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewStore(logger *logging.Logger, db *pgxpool.Pool) *Store {
|
func NewStore(logger *logging.Logger, db *pgxpool.Pool) *Store {
|
||||||
@@ -648,6 +655,212 @@ func (db *Store) StartEditingMockSyncGroup(ctx context.Context, acctID, syncGrou
|
|||||||
return v.Int64, v.Valid, nil
|
return v.Int64, v.Valid, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *Store) SaveMockSyncGroupBeingEdited(ctx context.Context, acctID int64) (syncGroupID int64, err error) {
|
||||||
|
err = db.beginTxn(ctx, func(tx pgx.Tx) error {
|
||||||
|
// delete old sync group listings
|
||||||
|
|
||||||
|
rows, err := tx.Query(
|
||||||
|
ctx,
|
||||||
|
`
|
||||||
|
WITH the_sync_group AS (
|
||||||
|
SELECT
|
||||||
|
sync_group_id
|
||||||
|
FROM
|
||||||
|
mock.sync_group_editing
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
), deleted_indexes AS (
|
||||||
|
DELETE FROM
|
||||||
|
mock.sync_group_listing_order_indexes ind
|
||||||
|
USING
|
||||||
|
mock.sync_group_editing AS ed
|
||||||
|
WHERE
|
||||||
|
ed.account_id = @account_id
|
||||||
|
AND ind.sync_group_id = ed.sync_group_id
|
||||||
|
RETURNING
|
||||||
|
sync_group_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
sync_group_id
|
||||||
|
FROM
|
||||||
|
deleted_indexes
|
||||||
|
LIMIT
|
||||||
|
1
|
||||||
|
`,
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to query editing sync group: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if syncGroupID, err = pgx.CollectExactlyOneRow(rows, pgx.RowTo[int64]); err != nil {
|
||||||
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
return consts.ErrNotFound
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to scan row: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var listingCount int
|
||||||
|
for _, in := range getAllMockShopSchemaInfos() {
|
||||||
|
// look up edited sync group listings
|
||||||
|
|
||||||
|
rows, err := tx.Query(
|
||||||
|
ctx,
|
||||||
|
fmt.Sprintf(
|
||||||
|
`
|
||||||
|
SELECT
|
||||||
|
order_index,
|
||||||
|
shop_id,
|
||||||
|
listing_id
|
||||||
|
FROM
|
||||||
|
%s el
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
`,
|
||||||
|
in.syncGroupEditingListingTable,
|
||||||
|
),
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to perform query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vs, err := pgx.CollectRows(rows, pgx.RowToStructByNameLax[struct {
|
||||||
|
Order_index int
|
||||||
|
Shop_id pgtype.Text
|
||||||
|
Listing_id pgtype.Text
|
||||||
|
}])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to scan rows: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(vs) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail if any shop_id's or listing_id's are NULL
|
||||||
|
for _, v := range vs {
|
||||||
|
if !v.Shop_id.Valid {
|
||||||
|
return fmt.Errorf("%w: shop id missing on listing", consts.ErrConflict)
|
||||||
|
}
|
||||||
|
if !v.Listing_id.Valid {
|
||||||
|
return fmt.Errorf("%w: listing id missing on listing", consts.ErrConflict)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create new sync group listing order indexes
|
||||||
|
|
||||||
|
values := make([]string, len(vs))
|
||||||
|
args := make(pgx.NamedArgs, len(vs))
|
||||||
|
for i, v := range vs {
|
||||||
|
values[i] = fmt.Sprintf("(@sync_group_id_%[1]d, @order_index_%[1]d)", i)
|
||||||
|
args[fmt.Sprintf("sync_group_id_%d", i)] = syncGroupID
|
||||||
|
args[fmt.Sprintf("order_index_%d", i)] = v.Order_index
|
||||||
|
}
|
||||||
|
listingCount += len(vs)
|
||||||
|
|
||||||
|
_, err = tx.Exec(
|
||||||
|
ctx,
|
||||||
|
fmt.Sprintf(
|
||||||
|
`
|
||||||
|
INSERT INTO
|
||||||
|
mock.sync_group_listing_order_indexes (
|
||||||
|
sync_group_id,
|
||||||
|
order_index
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
%s
|
||||||
|
`,
|
||||||
|
strings.Join(values, ", "),
|
||||||
|
),
|
||||||
|
args,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to delete rows for sync group listing order indexes: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create new sync group listings
|
||||||
|
|
||||||
|
values = make([]string, len(vs))
|
||||||
|
args = make(pgx.NamedArgs, len(vs))
|
||||||
|
for i, v := range vs {
|
||||||
|
values[i] = fmt.Sprintf("(@account_id_%[1]d, @sync_group_id_%[1]d, @shop_id_%[1]d, @listing_id_%[1]d, @order_index_%[1]d)", i)
|
||||||
|
args[fmt.Sprintf("account_id_%d", i)] = acctID
|
||||||
|
args[fmt.Sprintf("sync_group_id_%d", i)] = syncGroupID
|
||||||
|
args[fmt.Sprintf("shop_id_%d", i)] = v.Shop_id
|
||||||
|
args[fmt.Sprintf("listing_id_%d", i)] = v.Listing_id
|
||||||
|
args[fmt.Sprintf("order_index_%d", i)] = v.Order_index
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.Exec(
|
||||||
|
ctx,
|
||||||
|
fmt.Sprintf(
|
||||||
|
`
|
||||||
|
INSERT INTO
|
||||||
|
%s (
|
||||||
|
account_id,
|
||||||
|
sync_group_id,
|
||||||
|
shop_id,
|
||||||
|
listing_id,
|
||||||
|
order_index
|
||||||
|
)
|
||||||
|
VALUES
|
||||||
|
%s
|
||||||
|
`,
|
||||||
|
in.syncGroupListingsTable,
|
||||||
|
strings.Join(values, ", "),
|
||||||
|
),
|
||||||
|
args,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to perform query inserting new sync group listings: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// there must be at least two listings per sync group
|
||||||
|
|
||||||
|
if listingCount < 2 {
|
||||||
|
return fmt.Errorf("%w: invalid number of listings for sync group: %d: minimum of two required", consts.ErrConflict, listingCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete the sync group editing record
|
||||||
|
// this will cascade the editing listing records
|
||||||
|
|
||||||
|
rows, err = tx.Query(
|
||||||
|
ctx,
|
||||||
|
`
|
||||||
|
DELETE FROM
|
||||||
|
mock.sync_group_editing
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
RETURNING
|
||||||
|
sync_group_id
|
||||||
|
`,
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to perform query deleting editing sync group: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if syncGroupID, err = pgx.CollectExactlyOneRow(rows, pgx.RowTo[int64]); err != nil {
|
||||||
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
return consts.ErrNotFound
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to scan row: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return syncGroupID, err
|
||||||
|
}
|
||||||
|
|
||||||
func (db *Store) CancelEditingOfMockSyncGroupForAccount(ctx context.Context, acctID int64) (prevSyncGroupID int64, prevSyncGroupExists bool, err error) {
|
func (db *Store) CancelEditingOfMockSyncGroupForAccount(ctx context.Context, acctID int64) (prevSyncGroupID int64, prevSyncGroupExists bool, err error) {
|
||||||
rows, err := db.db.Query(
|
rows, err := db.db.Query(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -678,6 +891,156 @@ func (db *Store) CancelEditingOfMockSyncGroupForAccount(ctx context.Context, acc
|
|||||||
return prevSyncGroupID, true, nil
|
return prevSyncGroupID, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *Store) GetMockSyncGroupEditingListings(ctx context.Context, acctID int64) ([]ListingWithOrderIndex, error) {
|
||||||
|
var (
|
||||||
|
listings []ListingWithOrderIndex
|
||||||
|
allOrderIndexes []int
|
||||||
|
)
|
||||||
|
//orderIndexPerListing := make(map[Platform]map[string]int)
|
||||||
|
|
||||||
|
err := db.beginReadonlyTxn(ctx, func(tx pgx.Tx) error {
|
||||||
|
// get the mock sync group editing listings from each table
|
||||||
|
|
||||||
|
for _, in := range getAllMockShopSchemaInfos() {
|
||||||
|
rows, err := tx.Query(
|
||||||
|
ctx,
|
||||||
|
fmt.Sprintf(
|
||||||
|
`
|
||||||
|
SELECT
|
||||||
|
eli.shop_id,
|
||||||
|
eli.listing_id,
|
||||||
|
eli.order_index,
|
||||||
|
li.name,
|
||||||
|
li.count,
|
||||||
|
li.sku,
|
||||||
|
li.description,
|
||||||
|
sh.name as shop_name
|
||||||
|
FROM
|
||||||
|
%s AS eli
|
||||||
|
LEFT JOIN
|
||||||
|
%s AS li
|
||||||
|
USING
|
||||||
|
(account_id, shop_id, listing_id)
|
||||||
|
JOIN
|
||||||
|
%s AS sh
|
||||||
|
USING
|
||||||
|
(account_id, shop_id)
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
`,
|
||||||
|
in.syncGroupEditingListingTable,
|
||||||
|
in.listingsTable,
|
||||||
|
in.shopTable,
|
||||||
|
),
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to perform query to get mock sync group editing listings: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vs, err := pgx.CollectRows(rows, pgx.RowToStructByNameLax[struct {
|
||||||
|
Shop_id string
|
||||||
|
Listing_id pgtype.Text
|
||||||
|
Order_index int
|
||||||
|
Name pgtype.Text
|
||||||
|
Count pgtype.Int8
|
||||||
|
Sku pgtype.Text
|
||||||
|
Description pgtype.Text
|
||||||
|
Shop_name string
|
||||||
|
}])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to scan rows: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range vs {
|
||||||
|
listings = append(listings, ListingWithOrderIndex{
|
||||||
|
Listing: Listing{
|
||||||
|
AccountShopListingIDs: NewAccountIDs(acctID).
|
||||||
|
ShopID(in.platform, v.Shop_id).
|
||||||
|
ListingID(v.Listing_id.String),
|
||||||
|
ShopName: v.Shop_name,
|
||||||
|
SKU: v.Sku.String,
|
||||||
|
Name: v.Name.String,
|
||||||
|
Description: v.Description.String,
|
||||||
|
Count: v.Count.Int64,
|
||||||
|
},
|
||||||
|
OrderIndex: v.Order_index,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// loading the empty indexes, too
|
||||||
|
rows, err := tx.Query(
|
||||||
|
ctx,
|
||||||
|
`
|
||||||
|
SELECT
|
||||||
|
order_index
|
||||||
|
FROM
|
||||||
|
mock.sync_group_editing_listing_order_indexes
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
`,
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to perform query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if allOrderIndexes, err = pgx.CollectRows(rows, pgx.RowTo[int]); err != nil {
|
||||||
|
return fmt.Errorf("failed to scan rows: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
slices.SortFunc(listings, func(a, b ListingWithOrderIndex) int {
|
||||||
|
return a.OrderIndex - b.OrderIndex
|
||||||
|
})
|
||||||
|
|
||||||
|
indexPerOrderIndex := make(map[int]int)
|
||||||
|
for i, v := range listings {
|
||||||
|
indexPerOrderIndex[v.OrderIndex] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, i := range allOrderIndexes {
|
||||||
|
if _, ok := indexPerOrderIndex[i]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := i - 1; j >= 0; j -= 1 {
|
||||||
|
index, ok := indexPerOrderIndex[j]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert the new empty listing into the list
|
||||||
|
|
||||||
|
listings = slices.Insert(listings, index+1, ListingWithOrderIndex{
|
||||||
|
Listing: Listing{
|
||||||
|
AccountShopListingIDs: NewAccountIDs(acctID).
|
||||||
|
ShopID("", "").
|
||||||
|
ListingID(""),
|
||||||
|
},
|
||||||
|
OrderIndex: i,
|
||||||
|
})
|
||||||
|
|
||||||
|
indexPerOrderIndex[i] = index + 1
|
||||||
|
for k, v := range indexPerOrderIndex {
|
||||||
|
if k > i {
|
||||||
|
indexPerOrderIndex[k] = v + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return listings, err
|
||||||
|
}
|
||||||
|
|
||||||
func (db *Store) MockSyncGroupIsBeingEdited(ctx context.Context, acctID, syncGroupID int64) (bool, error) {
|
func (db *Store) MockSyncGroupIsBeingEdited(ctx context.Context, acctID, syncGroupID int64) (bool, error) {
|
||||||
rows, err := db.db.Query(
|
rows, err := db.db.Query(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -709,6 +1072,395 @@ func (db *Store) MockSyncGroupIsBeingEdited(ctx context.Context, acctID, syncGro
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *Store) GetMockSyncGroupEditingListing(ctx context.Context, acctID, syncGroupID, orderIndex int64) (*Listing, error) {
|
||||||
|
var listing *Listing
|
||||||
|
|
||||||
|
err := db.beginReadonlyTxn(ctx, func(tx pgx.Tx) error {
|
||||||
|
// assert the sync group is being edited
|
||||||
|
|
||||||
|
rows, err := tx.Query(
|
||||||
|
ctx,
|
||||||
|
`
|
||||||
|
SELECT
|
||||||
|
true
|
||||||
|
FROM
|
||||||
|
mock.sync_group_editing
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
AND sync_group_id = @sync_group_id
|
||||||
|
`,
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
"sync_group_id": syncGroupID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to perform query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := pgx.CollectExactlyOneRow(rows, pgx.RowTo[bool]); err != nil {
|
||||||
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
return consts.ErrNotFound
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to scan rows: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the editing listing
|
||||||
|
|
||||||
|
for _, in := range getAllMockShopSchemaInfos() {
|
||||||
|
rows, err := tx.Query(
|
||||||
|
ctx,
|
||||||
|
fmt.Sprintf(
|
||||||
|
`
|
||||||
|
SELECT
|
||||||
|
eli.shop_id,
|
||||||
|
eli.listing_id,
|
||||||
|
eli.order_index,
|
||||||
|
li.name,
|
||||||
|
li.count,
|
||||||
|
li.sku,
|
||||||
|
li.description,
|
||||||
|
sh.name as shop_name
|
||||||
|
FROM
|
||||||
|
%s AS eli
|
||||||
|
JOIN
|
||||||
|
%s AS li
|
||||||
|
USING
|
||||||
|
(account_id, shop_id, listing_id)
|
||||||
|
JOIN
|
||||||
|
%s AS sh
|
||||||
|
USING
|
||||||
|
(account_id, shop_id)
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
AND eli.order_index = @order_index
|
||||||
|
`,
|
||||||
|
in.syncGroupEditingListingTable,
|
||||||
|
in.listingsTable,
|
||||||
|
in.shopTable,
|
||||||
|
),
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
"order_index": orderIndex,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to perform query to get mock sync group editing listings: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByNameLax[struct {
|
||||||
|
Shop_id string
|
||||||
|
Listing_id string
|
||||||
|
Order_index int
|
||||||
|
Name string
|
||||||
|
Count int64
|
||||||
|
Sku string
|
||||||
|
Description string
|
||||||
|
Shop_name string
|
||||||
|
}])
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to scan rows: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
listing = &Listing{
|
||||||
|
AccountShopListingIDs: NewAccountIDs(acctID).
|
||||||
|
ShopID(in.platform, v.Shop_id).
|
||||||
|
ListingID(v.Listing_id),
|
||||||
|
ShopName: v.Shop_name,
|
||||||
|
SKU: v.Sku,
|
||||||
|
Name: v.Name,
|
||||||
|
Description: v.Description,
|
||||||
|
Count: v.Count,
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return consts.ErrNotFound
|
||||||
|
})
|
||||||
|
|
||||||
|
return listing, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Store) AddListingToMockSyncGroupBeingEdited(ctx context.Context, acctID int64) (syncGroupID int64, orderIndex int, err error) {
|
||||||
|
err = db.beginTxn(ctx, func(tx pgx.Tx) error {
|
||||||
|
// assert the sync group is being edited
|
||||||
|
|
||||||
|
rows, err := tx.Query(
|
||||||
|
ctx,
|
||||||
|
`
|
||||||
|
SELECT
|
||||||
|
sync_group_id
|
||||||
|
FROM
|
||||||
|
mock.sync_group_editing
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
`,
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to perform query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
syncGroupID, err = pgx.CollectExactlyOneRow(rows, pgx.RowTo[int64])
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
return consts.ErrNotFound
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to scan rows: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err = tx.Query(
|
||||||
|
ctx,
|
||||||
|
`
|
||||||
|
WITH new_order_index AS (
|
||||||
|
SELECT
|
||||||
|
COALESCE(MAX(order_index)+1, 0) AS order_index
|
||||||
|
FROM
|
||||||
|
mock.sync_group_editing_listing_order_indexes
|
||||||
|
)
|
||||||
|
INSERT INTO
|
||||||
|
mock.sync_group_editing_listing_order_indexes (
|
||||||
|
account_id,
|
||||||
|
order_index
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
@account_id,
|
||||||
|
new_order_index.order_index
|
||||||
|
FROM
|
||||||
|
new_order_index
|
||||||
|
RETURNING
|
||||||
|
order_index
|
||||||
|
`,
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to insert new order index row: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
orderIndex, err = pgx.CollectExactlyOneRow(rows, pgx.RowTo[int])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to scan rows: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return syncGroupID, orderIndex, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Store) SetShopInListingInMockSyncGroupBeingEdited(ctx context.Context, acctID, syncGroupID int64, orderIndex int, platform Platform, shopID string) error {
|
||||||
|
in, ok := getMockShopSchemaInfo(platform)
|
||||||
|
if !ok {
|
||||||
|
return consts.ErrNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.beginTxn(ctx, func(tx pgx.Tx) error {
|
||||||
|
// assert the sync group is being edited
|
||||||
|
|
||||||
|
rows, err := tx.Query(
|
||||||
|
ctx,
|
||||||
|
`
|
||||||
|
SELECT
|
||||||
|
true
|
||||||
|
FROM
|
||||||
|
mock.sync_group_editing
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
AND sync_group_id = @sync_group_id
|
||||||
|
`,
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
"sync_group_id": syncGroupID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to perform query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := pgx.CollectExactlyOneRow(rows, pgx.RowTo[bool]); err != nil {
|
||||||
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
return consts.ErrNotFound
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to scan rows: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete old listing: this will delete the store-specific listing row implicitly without the lookup
|
||||||
|
|
||||||
|
tags, err := tx.Exec(
|
||||||
|
ctx,
|
||||||
|
`
|
||||||
|
DELETE FROM
|
||||||
|
mock.sync_group_editing_listing_order_indexes
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
AND order_index = @order_index
|
||||||
|
`,
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
"order_index": orderIndex,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to deleted order index record: %w", err)
|
||||||
|
}
|
||||||
|
if tags.RowsAffected() == 0 {
|
||||||
|
return consts.ErrNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
// create new listing
|
||||||
|
|
||||||
|
_, err = tx.Exec(
|
||||||
|
ctx,
|
||||||
|
fmt.Sprintf(
|
||||||
|
`
|
||||||
|
WITH new_order_index_row(account_id, order_index) AS (
|
||||||
|
INSERT INTO
|
||||||
|
mock.sync_group_editing_listing_order_indexes (
|
||||||
|
account_id,
|
||||||
|
order_index
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
@account_id,
|
||||||
|
@order_index
|
||||||
|
)
|
||||||
|
RETURNING
|
||||||
|
account_id,
|
||||||
|
order_index
|
||||||
|
)
|
||||||
|
INSERT INTO
|
||||||
|
%s AS eli (
|
||||||
|
account_id,
|
||||||
|
order_index,
|
||||||
|
shop_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
account_id,
|
||||||
|
order_index,
|
||||||
|
@shop_id as shop_id
|
||||||
|
FROM
|
||||||
|
new_order_index_row
|
||||||
|
`,
|
||||||
|
in.syncGroupEditingListingTable,
|
||||||
|
),
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
"order_index": orderIndex,
|
||||||
|
"shop_id": shopID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to perform query to insert mock sync group editing listings: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Store) SetListingInListingInMockSyncGroupBeingEdited(ctx context.Context, acctID, syncGroupID int64, orderIndex int, listingID string) error {
|
||||||
|
return db.beginTxn(ctx, func(tx pgx.Tx) error {
|
||||||
|
// assert the sync group is being edited
|
||||||
|
|
||||||
|
rows, err := tx.Query(
|
||||||
|
ctx,
|
||||||
|
`
|
||||||
|
SELECT
|
||||||
|
true
|
||||||
|
FROM
|
||||||
|
mock.sync_group_editing
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
AND sync_group_id = @sync_group_id
|
||||||
|
`,
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
"sync_group_id": syncGroupID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to perform query: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := pgx.CollectExactlyOneRow(rows, pgx.RowTo[bool]); err != nil {
|
||||||
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
return consts.ErrNotFound
|
||||||
|
}
|
||||||
|
return fmt.Errorf("failed to scan rows: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the editing listing
|
||||||
|
|
||||||
|
for _, in := range getAllMockShopSchemaInfos() {
|
||||||
|
tag, err := tx.Exec(
|
||||||
|
ctx,
|
||||||
|
fmt.Sprintf(
|
||||||
|
`
|
||||||
|
UPDATE
|
||||||
|
%s AS eli
|
||||||
|
SET
|
||||||
|
listing_id = @listing_id
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
AND order_index = @order_index
|
||||||
|
`,
|
||||||
|
in.syncGroupEditingListingTable,
|
||||||
|
),
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
"order_index": orderIndex,
|
||||||
|
"listing_id": listingID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to perform query to update mock sync group editing listings: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch n := tag.RowsAffected(); n {
|
||||||
|
case 0:
|
||||||
|
continue
|
||||||
|
case 1:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unexpected number of rows affected: %d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return consts.ErrNotFound
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Store) DeleteListingInListingInMockSyncGroupBeingEdited(ctx context.Context, acctID int64, orderIndex int) error {
|
||||||
|
tag, err := db.db.Exec(
|
||||||
|
ctx,
|
||||||
|
`
|
||||||
|
DELETE FROM
|
||||||
|
mock.sync_group_editing_listing_order_indexes
|
||||||
|
WHERE
|
||||||
|
account_id = @account_id
|
||||||
|
AND order_index = @order_index
|
||||||
|
`,
|
||||||
|
pgx.NamedArgs{
|
||||||
|
"account_id": acctID,
|
||||||
|
"order_index": orderIndex,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to perform query: %w", err)
|
||||||
|
}
|
||||||
|
if tag.RowsAffected() == 0 {
|
||||||
|
return consts.ErrNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// 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) {
|
||||||
@@ -721,3 +1473,11 @@ func (db *Store) GetAccountPointerByUserID(ctx context.Context, userID string) (
|
|||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *Store) beginReadonlyTxn(ctx context.Context, cb func(pgx.Tx) error) error {
|
||||||
|
return pgx.BeginTxFunc(ctx, db.db, pgx.TxOptions{AccessMode: pgx.ReadOnly}, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Store) beginTxn(ctx context.Context, cb func(pgx.Tx) error) error {
|
||||||
|
return pgx.BeginFunc(ctx, db.db, cb)
|
||||||
|
}
|
||||||
|
|||||||
@@ -69,14 +69,34 @@ func (v_ctx *StoreWithContext) StartEditingMockSyncGroup(acctID int64, syncGroup
|
|||||||
return v_ctx.Store.StartEditingMockSyncGroup(v_ctx.ctx, acctID, syncGroupID)
|
return v_ctx.Store.StartEditingMockSyncGroup(v_ctx.ctx, acctID, syncGroupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v_ctx *StoreWithContext) CancelEditingOfMockSyncGroupForAccount(acctID int64) (int64, bool, error) {
|
||||||
|
return v_ctx.Store.CancelEditingOfMockSyncGroupForAccount(v_ctx.ctx, acctID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v_ctx *StoreWithContext) GetMockSyncGroupEditingListings(acctID int64) ([]ListingWithOrderIndex, error) {
|
||||||
|
return v_ctx.Store.GetMockSyncGroupEditingListings(v_ctx.ctx, acctID)
|
||||||
|
}
|
||||||
|
|
||||||
func (v_ctx *StoreWithContext) MockSyncGroupIsBeingEdited(acctID int64, syncGroupID int64) (bool, error) {
|
func (v_ctx *StoreWithContext) MockSyncGroupIsBeingEdited(acctID int64, syncGroupID int64) (bool, error) {
|
||||||
return v_ctx.Store.MockSyncGroupIsBeingEdited(v_ctx.ctx, acctID, syncGroupID)
|
return v_ctx.Store.MockSyncGroupIsBeingEdited(v_ctx.ctx, acctID, syncGroupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v_ctx *StoreWithContext) GetMockSyncGroupEditingListing(acctID int64, syncGroupID int64, orderIndex int64) (*Listing, error) {
|
||||||
|
return v_ctx.Store.GetMockSyncGroupEditingListing(v_ctx.ctx, acctID, syncGroupID, orderIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v_ctx *StoreWithContext) SetShopInListingInMockSyncGroupBeingEdited(acctID int64, syncGroupID int64, orderIndex int, platform Platform, shopID string) error {
|
||||||
|
return v_ctx.Store.SetShopInListingInMockSyncGroupBeingEdited(v_ctx.ctx, acctID, syncGroupID, orderIndex, 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v_ctx *StoreWithContext) beginReadonlyTxn(cb func(pgx.Tx) error) error {
|
||||||
|
return v_ctx.Store.beginReadonlyTxn(v_ctx.ctx, cb)
|
||||||
|
}
|
||||||
|
|
||||||
func (v_ctx *StoreWithContext) CreateMockShop(acctID int64, platform Platform, name string) (uuid.UUID, error) {
|
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)
|
return v_ctx.Store.CreateMockShop(v_ctx.ctx, acctID, platform, name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,8 +58,17 @@ func Routes(
|
|||||||
mockSyncGroups := syncGroups.Group("/mock")
|
mockSyncGroups := syncGroups.Group("/mock")
|
||||||
mockSyncGroups.POST("", pub.Publish("/:acctID/inventory/sync-groups/mock"), response.Handler(as.saveNewMockSyncGroup))
|
mockSyncGroups.POST("", pub.Publish("/:acctID/inventory/sync-groups/mock"), response.Handler(as.saveNewMockSyncGroup))
|
||||||
mockSyncGroups.DELETE("/:syncGroupID", pub.Publish("/:acctID/inventory/sync-groups/mock"), response.Handler(as.deleteMockSyncGroup))
|
mockSyncGroups.DELETE("/:syncGroupID", pub.Publish("/:acctID/inventory/sync-groups/mock"), response.Handler(as.deleteMockSyncGroup))
|
||||||
mockSyncGroups.PUT("/editing", pub.Publish("/:acctID/inventory/sync-groups/mock/editing"), response.Handler(as.selectMockSyncGroupForEditing))
|
|
||||||
mockSyncGroups.DELETE("/editing", pub.Publish("/:acctID/inventory/sync-groups/mock/editing"), response.Handler(as.cancelMockSyncGroupEdits))
|
setMockSyncGroupForEditingEndpoints := mockSyncGroups.Group("/editing", pub.Publish("/:acctID/inventory/sync-groups/mock/editing"))
|
||||||
|
setMockSyncGroupForEditingEndpoints.PUT("", response.Handler(as.selectMockSyncGroupForEditing))
|
||||||
|
setMockSyncGroupForEditingEndpoints.POST("", response.Handler(as.saveMockSyncGroupBeingEdited))
|
||||||
|
setMockSyncGroupForEditingEndpoints.DELETE("", response.Handler(as.cancelMockSyncGroupEdits))
|
||||||
|
setMockSyncGroupForEditingEndpoints.POST("/listings", response.Handler(as.addListingToMockSyncGroupBeingEdited))
|
||||||
|
|
||||||
|
mockSyncGroupBeingEdited := mockSyncGroups.Group("/:syncGroupID/editing", pub.Publish("/:acctID/inventory/sync-groups/mock/:syncGroupID/editing"))
|
||||||
|
mockSyncGroupBeingEdited.PUT("/listings/:orderIndex/shop", response.Handler(as.setShopInListingInMockSyncGroupBeingEdited))
|
||||||
|
mockSyncGroupBeingEdited.PUT("/listings/:orderIndex/listing", response.Handler(as.setListingInListingInMockSyncGroupBeingEdited))
|
||||||
|
mockSyncGroupBeingEdited.DELETE("/listings/:orderIndex", response.Handler(as.deleteListingInListingInMockSyncGroupBeingEdited))
|
||||||
|
|
||||||
mockDraftListings := mockSyncGroups.Group("/draft/listings", pub.Publish("/:acctID/inventory/sync-groups/mock/draft/listings"))
|
mockDraftListings := mockSyncGroups.Group("/draft/listings", pub.Publish("/:acctID/inventory/sync-groups/mock/draft/listings"))
|
||||||
mockDraftListings.POST("", response.Handler(as.createMockSyncGroupListingDraft))
|
mockDraftListings.POST("", response.Handler(as.createMockSyncGroupListingDraft))
|
||||||
@@ -571,6 +580,31 @@ func (s *accountSubrouter) selectMockSyncGroupForEditing(c *gin.Context) (respon
|
|||||||
return response.StatusOK(), nil
|
return response.StatusOK(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// POST /:acctID/inventory/sync-groups/mock/editing
|
||||||
|
func (s *accountSubrouter) saveMockSyncGroupBeingEdited(c *gin.Context) (response.Response, error) {
|
||||||
|
r := c.Request
|
||||||
|
ctx := r.Context()
|
||||||
|
acctID := auth.GetIdentity(ctx).Account.AccountID
|
||||||
|
|
||||||
|
syncGroupID, err := s.accts.SaveMockSyncGroupBeingEdited(ctx, acctID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, response.Errorf("failed to save mock sync group being edited: %w", response.ErrorFromConstant(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// emit events indicating sync groups being edited and no longer being edited
|
||||||
|
|
||||||
|
if err := s.pub.Push(
|
||||||
|
c,
|
||||||
|
acctID,
|
||||||
|
fmt.Sprintf("accounts_%d_inventory_sync-groups_mock_%d", acctID, syncGroupID),
|
||||||
|
fmt.Sprintf("accounts_%d_inventory_sync-groups_mock_%d_editing", acctID, syncGroupID),
|
||||||
|
); err != nil {
|
||||||
|
s.log.Errorf("failed to publish mock sync group editing events: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.StatusOK(), nil
|
||||||
|
}
|
||||||
|
|
||||||
// DELETE /:acctID/inventory/sync-groups/mock/editing
|
// DELETE /:acctID/inventory/sync-groups/mock/editing
|
||||||
func (s *accountSubrouter) cancelMockSyncGroupEdits(c *gin.Context) (response.Response, error) {
|
func (s *accountSubrouter) cancelMockSyncGroupEdits(c *gin.Context) (response.Response, error) {
|
||||||
r := c.Request
|
r := c.Request
|
||||||
@@ -593,6 +627,89 @@ func (s *accountSubrouter) cancelMockSyncGroupEdits(c *gin.Context) (response.Re
|
|||||||
return response.StatusOK(), nil
|
return response.StatusOK(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// POST /:acctID/inventory/sync-groups/mock/editing/listings
|
||||||
|
func (s *accountSubrouter) addListingToMockSyncGroupBeingEdited(c *gin.Context) (response.Response, error) {
|
||||||
|
r := c.Request
|
||||||
|
ctx := r.Context()
|
||||||
|
acctID := auth.GetIdentity(ctx).Account.AccountID
|
||||||
|
|
||||||
|
if _, _, err := s.accts.AddListingToMockSyncGroupBeingEdited(ctx, acctID); err != nil {
|
||||||
|
return nil, response.Errorf("failed to add listing to mock sync group being edited: %w", response.ErrorFromConstant(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.StatusCreated(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /:acctID/inventory/sync-groups/mock/editing/listings/:orderIndex/shop
|
||||||
|
func (s *accountSubrouter) setShopInListingInMockSyncGroupBeingEdited(c *gin.Context) (response.Response, error) {
|
||||||
|
acctID := auth.GetIdentity(c).Account.AccountID
|
||||||
|
|
||||||
|
var (
|
||||||
|
syncGroupID int64
|
||||||
|
orderIndex int
|
||||||
|
platform accounts.Platform
|
||||||
|
shopID string
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := param.Path("syncGroupID", param.Int64(&syncGroupID)).
|
||||||
|
Path("orderIndex", param.Int(&orderIndex)).
|
||||||
|
Form("platform", param.Platform(&platform)).
|
||||||
|
Form("shop-id", param.Text(&shopID)).
|
||||||
|
Unmarshal(c); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.accts.SetShopInListingInMockSyncGroupBeingEdited(c, acctID, syncGroupID, orderIndex, platform, shopID); err != nil {
|
||||||
|
return nil, response.Errorf("failed to set shop in listing in mock sync group being edited: %w", response.ErrorFromConstant(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.StatusOK(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /:acctID/inventory/sync-groups/mock/editing/listings/:orderIndex/listing
|
||||||
|
func (s *accountSubrouter) setListingInListingInMockSyncGroupBeingEdited(c *gin.Context) (response.Response, error) {
|
||||||
|
acctID := auth.GetIdentity(c).Account.AccountID
|
||||||
|
|
||||||
|
var (
|
||||||
|
syncGroupID int64
|
||||||
|
orderIndex int
|
||||||
|
listingID string
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := param.Path("syncGroupID", param.Int64(&syncGroupID)).
|
||||||
|
Path("orderIndex", param.Int(&orderIndex)).
|
||||||
|
Form("listing-id", param.Text(&listingID)).
|
||||||
|
Unmarshal(c); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.accts.SetListingInListingInMockSyncGroupBeingEdited(c, acctID, syncGroupID, orderIndex, listingID); err != nil {
|
||||||
|
return nil, response.Errorf("failed to set listing in listing in mock sync group being edited: %w", response.ErrorFromConstant(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.StatusOK(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /:acctID/inventory/sync-groups/mock/editing/listings/:orderIndex
|
||||||
|
func (s *accountSubrouter) deleteListingInListingInMockSyncGroupBeingEdited(c *gin.Context) (response.Response, error) {
|
||||||
|
acctID := auth.GetIdentity(c).Account.AccountID
|
||||||
|
|
||||||
|
var (
|
||||||
|
orderIndex int
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := param.Path("orderIndex", param.Int(&orderIndex)).
|
||||||
|
Unmarshal(c); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.accts.DeleteListingInListingInMockSyncGroupBeingEdited(c, acctID, orderIndex); err != nil {
|
||||||
|
return nil, response.Errorf("failed to delete listing in mock sync group being edited: %w", response.ErrorFromConstant(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.StatusOK(), 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), " "), "_"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,29 +197,6 @@
|
|||||||
.bottom-0 {
|
.bottom-0 {
|
||||||
bottom: calc(var(--spacing) * 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\] {
|
.grid-table-\[1fr_1fr_1fr_1fr_1fr_1fr_1fr\] {
|
||||||
&:is(table) {
|
&:is(table) {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|||||||
+1
-2
@@ -29,13 +29,12 @@
|
|||||||
on setListing(listing)
|
on setListing(listing)
|
||||||
call setFilledOut(true)
|
call setFilledOut(true)
|
||||||
|
|
||||||
|
|
||||||
on resetListing
|
on resetListing
|
||||||
call setFilledOut(false)
|
call setFilledOut(false)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<td class="text-nowrap">
|
<td class="text-nowrap">
|
||||||
{{/* TODO: filter out shops that are already selected */}}
|
{{/* filter out shops that are already selected */}}
|
||||||
{{- $shops := .Accounts.GetMockShops $acctID -}}
|
{{- $shops := .Accounts.GetMockShops $acctID -}}
|
||||||
<select
|
<select
|
||||||
class="min-w-fit cursor-pointer"
|
class="min-w-fit cursor-pointer"
|
||||||
|
|||||||
-211
@@ -1,211 +0,0 @@
|
|||||||
{{/* .SyncGroup: optional for performance */}}
|
|
||||||
|
|
||||||
{{- $syncGroupID := .PathParams.syncGroupID }}
|
|
||||||
{{- $acctID := .PathParams.acctID }}
|
|
||||||
{{- $isBeingEditing := .Accounts.MockSyncGroupIsBeingEdited $acctID $syncGroupID }}
|
|
||||||
|
|
||||||
{{- $open := or $isBeingEditing (and .Request (eq (.Request.URL.Query.Get "open") "true")) }}
|
|
||||||
|
|
||||||
{{- $grp := .SyncGroup }}
|
|
||||||
{{- if not $grp }}
|
|
||||||
{{- $grp = .Accounts.GetMockSyncGroup $acctID $syncGroupID }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
|
|
||||||
{{- $id := (printf "sync-group-%d" $syncGroupID) }}
|
|
||||||
<li
|
|
||||||
id="{{$id}}"
|
|
||||||
class="mx-[1em]"
|
|
||||||
hx-get="{{ printf "/ui/accounts/%d/inventory/sync-groups/mock/%d/list-item" $acctID $syncGroupID }}"
|
|
||||||
hx-trigger="{{ printf "sse:accounts_%d_inventory_sync-groups_mock_%d" $acctID $syncGroupID }}"
|
|
||||||
hx-swap="morph:outerHTML"
|
|
||||||
hx-select="#{{$id}}"
|
|
||||||
hx-vals="js:{open: this.getElementsByTagName('details')[0].open}"
|
|
||||||
>
|
|
||||||
{{- define "sync-group-accordion-header" }}
|
|
||||||
<h3 class="text-center">
|
|
||||||
{{ .Group.Name }}
|
|
||||||
</h3>
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "sync-group-accordion-editing-header" }}
|
|
||||||
<div class="flex flex-col items-center">
|
|
||||||
<h3 class="text-center">
|
|
||||||
{{ .Group.Name }}
|
|
||||||
</h3>
|
|
||||||
<h5>
|
|
||||||
Editing
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "sync-group-accordion-static-body" }}
|
|
||||||
{{- $acctID := .Identity.Account.AccountID }}
|
|
||||||
{{- $syncGroupID := .Group.SyncGroupID }}
|
|
||||||
<table id="sync-group-data-{{$syncGroupID}}">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
Shop
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
Platform
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
Name
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
SKU
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
Description
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
Count
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{- $dot := . }}
|
|
||||||
{{- range $listing := .Group.Listings }}
|
|
||||||
<tr>
|
|
||||||
{{- $val := $dot.Accounts.GetMockListing $acctID $listing.Platform $listing.ShopID $listing.ListingID }}
|
|
||||||
<td class="text-nowrap">
|
|
||||||
{{ $val.ShopName }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ $val.Platform }}
|
|
||||||
</td>
|
|
||||||
<td class="text-nowrap">
|
|
||||||
{{ $val.Name }}
|
|
||||||
</td>
|
|
||||||
<td class="text-nowrap">
|
|
||||||
{{ $val.SKU }}
|
|
||||||
</td>
|
|
||||||
<td class="text-nowrap">
|
|
||||||
{{ $val.Description }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ $val.Count }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{- end }}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div
|
|
||||||
id="sync-group-{{$syncGroupID}}-buttons"
|
|
||||||
class="flex justify-center flex-grow-[1] gap-[0.5em]"
|
|
||||||
>
|
|
||||||
{{- component "button"
|
|
||||||
"Class" "mt-[1em]"
|
|
||||||
"Text" "Edit"
|
|
||||||
"HXPut" (printf "/api/accounts/%d/inventory/sync-groups/mock/editing" $acctID)
|
|
||||||
"HXVals" (printf `js:{"syncGroupID":%d}` $syncGroupID)
|
|
||||||
"HXSwap" "none"
|
|
||||||
}}
|
|
||||||
|
|
||||||
{{- component "button"
|
|
||||||
"Class" "mt-[1em]"
|
|
||||||
"Text" "Delete"
|
|
||||||
"HXDelete" (printf "/api/accounts/%d/inventory/sync-groups/mock/%d" $acctID $syncGroupID)
|
|
||||||
"HXSwap" "none"
|
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "sync-group-accordion-form-body" }}
|
|
||||||
{{- $acctID := .Identity.Account.AccountID }}
|
|
||||||
{{- $syncGroupID := .Group.SyncGroupID }}
|
|
||||||
<form>
|
|
||||||
<table id="sync-group-{{$syncGroupID}}-form">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
Shop
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
Platform
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
Name
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
SKU
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
Description
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
Count
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{- $dot := . }}
|
|
||||||
{{- range $listing := .Group.Listings }}
|
|
||||||
<tr>
|
|
||||||
{{- $val := $dot.Accounts.GetMockListing $acctID $listing.Platform $listing.ShopID $listing.ListingID }}
|
|
||||||
<td>
|
|
||||||
{{ $val.ShopName }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ $val.Platform }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ $val.Name }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ $val.SKU }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ $val.Description }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ $val.Count }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{- end }}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div
|
|
||||||
id="sync-group-{{$syncGroupID}}-editing-buttons"
|
|
||||||
class="flex justify-center flex-grow-[1] gap-[0.5em]"
|
|
||||||
>
|
|
||||||
{{/* TODO: implement saving */}}
|
|
||||||
{{- component "button"
|
|
||||||
"Class" "mt-[1em]"
|
|
||||||
"Text" "Save"
|
|
||||||
"HXSwap" "none"
|
|
||||||
}}
|
|
||||||
|
|
||||||
{{- component "button"
|
|
||||||
"Class" "mt-[1em]"
|
|
||||||
"Text" "Cancel"
|
|
||||||
"HXDelete" (printf "/api/accounts/%d/inventory/sync-groups/mock/editing" $acctID)
|
|
||||||
"HXSwap" "none"
|
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- $accordionHeader := "sync-group-accordion-header" }}
|
|
||||||
{{- $accordionBody := "sync-group-accordion-static-body" }}
|
|
||||||
{{- $summaryClass := "" }}
|
|
||||||
{{- if $isBeingEditing }}
|
|
||||||
{{- $accordionBody = "sync-group-accordion-form-body" }}
|
|
||||||
{{- $accordionHeader = "sync-group-accordion-editing-header" }}
|
|
||||||
{{- $summaryClass = "bg-accent-secondary" }}
|
|
||||||
{{- end }}
|
|
||||||
{{ component "accordion"
|
|
||||||
"Name" "sync-group-page"
|
|
||||||
"Open" $open
|
|
||||||
"GroupName" "sync-group"
|
|
||||||
"Group" $grp
|
|
||||||
"Smooth" false
|
|
||||||
"SummaryClass" $summaryClass
|
|
||||||
"#accordion-header" $accordionHeader
|
|
||||||
"#accordion-body" $accordionBody
|
|
||||||
}}
|
|
||||||
</li>
|
|
||||||
+117
@@ -0,0 +1,117 @@
|
|||||||
|
{{- $acctID := .Identity.Account.AccountID }}
|
||||||
|
{{- $syncGroupID := .PathParams.syncGroupID }}
|
||||||
|
|
||||||
|
<form class="w-full">
|
||||||
|
<table
|
||||||
|
id="sync-group-{{$syncGroupID}}-form"
|
||||||
|
class="w-full overflow-x-auto"
|
||||||
|
hx-get="/ui/accounts/{{$acctID}}/inventory/sync-groups/mock/{{$syncGroupID}}/list-item/edit-form"
|
||||||
|
hx-trigger="sse:{{ printf "accounts_%d_inventory_sync-groups_mock_%d_editing" $acctID $syncGroupID }},sse:{{ printf "accounts_%d_inventory_sync-groups_mock_editing" $acctID }}"
|
||||||
|
hx-select="#sync-group-{{$syncGroupID}}-form"
|
||||||
|
hx-swap="morph"
|
||||||
|
>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Shop
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Platform
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Listing
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
SKU
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Description
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Count
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{- $dot := . }}
|
||||||
|
|
||||||
|
{{- $editListings := .Accounts.GetMockSyncGroupEditingListings $acctID }}
|
||||||
|
{{- range $listing := $editListings }}
|
||||||
|
{{- component (printf "accounts/%d/inventory/sync-groups/mock/%d/list-item/edit-form/edit-form-listing/%d" $acctID $syncGroupID $listing.OrderIndex)
|
||||||
|
"Listing" $listing
|
||||||
|
"Listings" $editListings
|
||||||
|
}}
|
||||||
|
{{- end }}
|
||||||
|
</tbody>
|
||||||
|
{{- if gt (len $editListings) 5 }}
|
||||||
|
<tfoot class="sticky bottom-0 outline-1 outline-(--table-tfoot)">
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Shop
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Platform
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Listing
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
SKU
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Description
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Count
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
{{- end }}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="sync-group-{{$syncGroupID}}-editing-buttons"
|
||||||
|
class="flex justify-center flex-grow-[1] gap-[0.5em]"
|
||||||
|
>
|
||||||
|
{{/* TODO: implement */}}
|
||||||
|
{{- component "button"
|
||||||
|
"ID" "add-mock-sync-group-listing-button"
|
||||||
|
"Class" "mt-[1em]"
|
||||||
|
"Text" "Add Listing"
|
||||||
|
"HXPost" (printf "/api/accounts/%d/inventory/sync-groups/mock/editing/listings" $acctID)
|
||||||
|
"HXSwap" "none"
|
||||||
|
}}
|
||||||
|
|
||||||
|
{{- component "button"
|
||||||
|
"ID" "save-mock-sync-group-button"
|
||||||
|
"Class" "mt-[1em]"
|
||||||
|
"Text" "Save"
|
||||||
|
"HXPost" (printf "/api/accounts/%d/inventory/sync-groups/mock/editing" $acctID)
|
||||||
|
"HXSwap" "none"
|
||||||
|
}}
|
||||||
|
|
||||||
|
{{- component "button"
|
||||||
|
"Class" "mt-[1em]"
|
||||||
|
"Text" "Cancel"
|
||||||
|
"HXDelete" (printf "/api/accounts/%d/inventory/sync-groups/mock/editing" $acctID)
|
||||||
|
"HXSwap" "none"
|
||||||
|
}}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
<div
|
||||||
|
hidden
|
||||||
|
hx-get="{{ printf "/ui/accounts/%d/inventory/sync-groups/mock/draft/table/save-sync-group-button" $acctID }}"
|
||||||
|
hx-trigger="sse:{{ printf "accounts_%d_inventory_sync-groups_mock_%d_editing_listings" $acctID $syncGroupID }}"
|
||||||
|
hx-target="#save-mock-sync-group-button"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
*/}}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
+140
@@ -0,0 +1,140 @@
|
|||||||
|
{{/* .Listing */}}
|
||||||
|
{{/* optional props: .Listings = .Accounts.GetMockSyncGroupListingDrafts */}}
|
||||||
|
|
||||||
|
{{- $acctID := .PathParams.acctID }}
|
||||||
|
{{- $syncGroupID := .PathParams.syncGroupID }}
|
||||||
|
{{- $orderIndex := .PathParams.orderIndex }}
|
||||||
|
{{- $entry := .Listing }}
|
||||||
|
{{- if not $entry }}
|
||||||
|
{{- $entry = .Accounts.GetMockSyncGroupEditingListing $acctID $syncGroupID $orderIndex }}
|
||||||
|
{{- end }}
|
||||||
|
{{- $selectedShopPlatform := $entry.Platform }}
|
||||||
|
{{- $selectedShopID := $entry.ShopID }}
|
||||||
|
{{- $selectedListingID := $entry.ListingID }}
|
||||||
|
|
||||||
|
{{- $listings := .Listings }}
|
||||||
|
{{- if not $listings }}
|
||||||
|
{{- $listings := .Accounts.GetMockSyncGroupEditingListings $acctID }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{{- $listing := .Listing }}
|
||||||
|
<tr id="{{$syncGroupID}}-editing-{{$orderIndex}}">
|
||||||
|
<td class="text-nowrap">
|
||||||
|
{{/* filter out shops that are already selected */}}
|
||||||
|
{{/* $listing.ShopName */}}
|
||||||
|
|
||||||
|
|
||||||
|
{{- $shops := .Accounts.GetMockShops $acctID -}}
|
||||||
|
<select
|
||||||
|
class="min-w-fit cursor-pointer"
|
||||||
|
hx-put="/api/accounts/{{$acctID}}/inventory/sync-groups/mock/{{$syncGroupID}}/editing/listings/{{$orderIndex}}/shop"
|
||||||
|
hx-vals='js:{
|
||||||
|
platform: event.target.value.replace(/-[^ ]*/, ""),
|
||||||
|
"shop-id": event.target.value.replace(/^[a-zA-Z_]*-/, "")
|
||||||
|
}'
|
||||||
|
hx-swap="none"
|
||||||
|
{{/* TODO: drop events if not used */}}
|
||||||
|
_="
|
||||||
|
on change
|
||||||
|
send resetListing() to closest <tr/>
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<option disabled {{- if not $selectedShopID }} selected{{- end }}>- Shops -</option>
|
||||||
|
{{- range $shop := $shops }}
|
||||||
|
{{- $shopSelectedInOtherListing := false }}
|
||||||
|
{{- if not (eq $shop.ShopID $selectedShopID ) }}
|
||||||
|
{{- range $listing := $listings }}
|
||||||
|
{{- if eq $listing.ShopID $shop.ShopID }}
|
||||||
|
{{- $shopSelectedInOtherListing = true }}
|
||||||
|
{{- break }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if $shopSelectedInOtherListing }}
|
||||||
|
{{- continue }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- $isSelectedShop := and
|
||||||
|
(eq $selectedShopPlatform $shop.Platform)
|
||||||
|
(eq $selectedShopID $shop.ShopID)
|
||||||
|
}}
|
||||||
|
<option
|
||||||
|
id="{{$shop.Platform}}-{{$shop.ShopID}}"
|
||||||
|
value="{{$shop.Platform}}-{{$shop.ShopID}}"
|
||||||
|
{{- if $isSelectedShop }} selected{{- end }}
|
||||||
|
>
|
||||||
|
{{ $shop.Name }}
|
||||||
|
</option>
|
||||||
|
{{- end }}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{- if $entry.Platform }}{{ $entry.Platform }}{{ else }}-{{ end }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{/* $listing.Name */}}
|
||||||
|
{{- $selectedListing := "" }}
|
||||||
|
{{- if $selectedShopID }}
|
||||||
|
{{- $shopListings := .Accounts.GetMockListingsForShop $acctID $selectedShopPlatform $selectedShopID }}
|
||||||
|
{{- if $shopListings }}
|
||||||
|
<select
|
||||||
|
class="min-w-fit cursor-pointer"
|
||||||
|
|
||||||
|
hx-put="/api/accounts/{{$acctID}}/inventory/sync-groups/mock/{{$syncGroupID}}/editing/listings/{{$orderIndex}}/listing"
|
||||||
|
hx-vals='js:{
|
||||||
|
"listing-id": event.target.value,
|
||||||
|
}'
|
||||||
|
hx-swap="none"
|
||||||
|
|
||||||
|
_="
|
||||||
|
on input
|
||||||
|
set dataset to (my selectedOptions)[0].dataset
|
||||||
|
send setListing(listing: dataset) to the closest <tr/>
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<option disabled {{if not $selectedListingID}}selected{{end}}>- Listings -</option>
|
||||||
|
{{- range $i, $shopListing := $shopListings }}
|
||||||
|
{{- if eq $selectedListingID $shopListing.ListingID }}
|
||||||
|
{{ $selectedListing = $shopListing }}
|
||||||
|
{{- end }}
|
||||||
|
<option
|
||||||
|
value="{{$shopListing.ListingID}}"
|
||||||
|
{{if eq $selectedListingID $shopListing.ListingID}}selected{{end}}
|
||||||
|
data-name="{{ $shopListing.Name }}"
|
||||||
|
data-sku="{{ $shopListing.SKU }}"
|
||||||
|
data-description="{{ $shopListing.Description }}"
|
||||||
|
data-count="{{ $shopListing.Count }}"
|
||||||
|
>
|
||||||
|
{{ $shopListing.Name }}
|
||||||
|
</option>
|
||||||
|
{{- end }}
|
||||||
|
</select>
|
||||||
|
{{- else }}
|
||||||
|
no listings found
|
||||||
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
-
|
||||||
|
{{- end }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ $listing.SKU }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ $listing.Description }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ $listing.Count }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
{{ component "button"
|
||||||
|
"HXDelete" (printf "/api/accounts/%d/inventory/sync-groups/mock/%d/editing/listings/%d" $acctID $syncGroupID $orderIndex)
|
||||||
|
"HXTarget" "#accounts-acct-id-inventory-sync-groups-mock-draft-table"
|
||||||
|
"HXSwap" "none"
|
||||||
|
"Text" "Remove"
|
||||||
|
}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
+76
@@ -0,0 +1,76 @@
|
|||||||
|
{{/* .SyncGroup: optional for performance */}}
|
||||||
|
|
||||||
|
{{- $syncGroupID := .PathParams.syncGroupID }}
|
||||||
|
{{- $acctID := .PathParams.acctID }}
|
||||||
|
{{- $isBeingEditing := .Accounts.MockSyncGroupIsBeingEdited $acctID $syncGroupID }}
|
||||||
|
|
||||||
|
{{- $open := or $isBeingEditing (and .Request (eq (.Request.URL.Query.Get "open") "true")) }}
|
||||||
|
|
||||||
|
{{- $grp := .SyncGroup }}
|
||||||
|
{{- if not $grp }}
|
||||||
|
{{- $grp = .Accounts.GetMockSyncGroup $acctID $syncGroupID }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{- $id := (printf "sync-group-%d" $syncGroupID) }}
|
||||||
|
<li
|
||||||
|
id="{{$id}}"
|
||||||
|
class="mx-[1em]"
|
||||||
|
hx-get="{{ printf "/ui/accounts/%d/inventory/sync-groups/mock/%d/list-item" $acctID $syncGroupID }}"
|
||||||
|
hx-trigger="{{ printf "sse:accounts_%d_inventory_sync-groups_mock_%d" $acctID $syncGroupID }}"
|
||||||
|
hx-swap="morph:outerHTML"
|
||||||
|
hx-select="#{{$id}}"
|
||||||
|
hx-vals="js:{open: this.getElementsByTagName('details')[0].open}"
|
||||||
|
>
|
||||||
|
{{- define "sync-group-accordion-header" }}
|
||||||
|
<h3 class="text-center">
|
||||||
|
{{ .Group.Name }}
|
||||||
|
</h3>
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "sync-group-accordion-editing-header" }}
|
||||||
|
<div class="flex flex-col items-center">
|
||||||
|
<h3 class="text-center">
|
||||||
|
{{ .Group.Name }}
|
||||||
|
</h3>
|
||||||
|
<h5>
|
||||||
|
Editing
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "sync-group-accordion-static-table" }}
|
||||||
|
{{- component (
|
||||||
|
printf "accounts/%d/inventory/sync-groups/mock/%d/list-item/static-table"
|
||||||
|
.Identity.Account.AccountID
|
||||||
|
.Group.SyncGroupID
|
||||||
|
)}}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "sync-group-accordion-edit-form" }}
|
||||||
|
{{- component (
|
||||||
|
printf "accounts/%d/inventory/sync-groups/mock/%d/list-item/edit-form"
|
||||||
|
.Identity.Account.AccountID
|
||||||
|
.Group.SyncGroupID
|
||||||
|
)}}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- $accordionHeader := "sync-group-accordion-header" }}
|
||||||
|
{{- $accordionBody := "sync-group-accordion-static-table" }}
|
||||||
|
{{- $summaryClass := "" }}
|
||||||
|
{{- if $isBeingEditing }}
|
||||||
|
{{- $accordionBody = "sync-group-accordion-edit-form" }}
|
||||||
|
{{- $accordionHeader = "sync-group-accordion-editing-header" }}
|
||||||
|
{{- $summaryClass = "bg-accent-secondary" }}
|
||||||
|
{{- end }}
|
||||||
|
{{ component "accordion"
|
||||||
|
"Name" "sync-group-page"
|
||||||
|
"Open" $open
|
||||||
|
"GroupName" "sync-group"
|
||||||
|
"Group" $grp
|
||||||
|
"Smooth" false
|
||||||
|
"SummaryClass" $summaryClass
|
||||||
|
"#accordion-header" $accordionHeader
|
||||||
|
"#accordion-body" $accordionBody
|
||||||
|
}}
|
||||||
|
</li>
|
||||||
+74
@@ -0,0 +1,74 @@
|
|||||||
|
{{/* .Group */}}
|
||||||
|
{{- $acctID := .Identity.Account.AccountID }}
|
||||||
|
{{- $syncGroupID := .PathParams.syncGroupID -}}
|
||||||
|
|
||||||
|
<table id="sync-group-data-{{$syncGroupID}}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Shop
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Platform
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Name
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
SKU
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Description
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Count
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{- $dot := . }}
|
||||||
|
{{- range $listing := .Group.Listings }}
|
||||||
|
<tr>
|
||||||
|
{{- $val := $dot.Accounts.GetMockListing $acctID $listing.Platform $listing.ShopID $listing.ListingID }}
|
||||||
|
<td class="text-nowrap">
|
||||||
|
{{ $val.ShopName }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ $val.Platform }}
|
||||||
|
</td>
|
||||||
|
<td class="text-nowrap">
|
||||||
|
{{ $val.Name }}
|
||||||
|
</td>
|
||||||
|
<td class="text-nowrap">
|
||||||
|
{{ $val.SKU }}
|
||||||
|
</td>
|
||||||
|
<td class="text-nowrap">
|
||||||
|
{{ $val.Description }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ $val.Count }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{- end }}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="sync-group-{{$syncGroupID}}-buttons"
|
||||||
|
class="flex justify-center flex-grow-[1] gap-[0.5em]"
|
||||||
|
>
|
||||||
|
{{- component "button"
|
||||||
|
"Class" "mt-[1em]"
|
||||||
|
"Text" "Edit"
|
||||||
|
"HXPut" (printf "/api/accounts/%d/inventory/sync-groups/mock/editing" $acctID)
|
||||||
|
"HXVals" (printf `js:{"syncGroupID":%d}` $syncGroupID)
|
||||||
|
"HXSwap" "none"
|
||||||
|
}}
|
||||||
|
|
||||||
|
{{- component "button"
|
||||||
|
"Class" "mt-[1em]"
|
||||||
|
"Text" "Delete"
|
||||||
|
"HXDelete" (printf "/api/accounts/%d/inventory/sync-groups/mock/%d" $acctID $syncGroupID)
|
||||||
|
"HXSwap" "none"
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user