@medusajs/dashboard 2.22.0 → 2.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{add-campaign-promotions-VGH4LCDR.mjs → add-campaign-promotions-IUQHZ5QA.mjs} +1 -1
- package/dist/{add-locales-3OTB5FQM.mjs → add-locales-FQQ5W3MB.mjs} +2 -2
- package/dist/{adjust-inventory-UPEEXXFU.mjs → adjust-inventory-DJFQZTLA.mjs} +1 -1
- package/dist/{api-key-management-create-ROQ6LKUO.mjs → api-key-management-create-7T2MCQ3T.mjs} +1 -1
- package/dist/{api-key-management-detail-PPQ6XGZ4.mjs → api-key-management-detail-X3AUNHCO.mjs} +9 -8
- package/dist/{api-key-management-edit-QGKZADJX.mjs → api-key-management-edit-S3GYYNWM.mjs} +1 -1
- package/dist/{api-key-management-list-OCQN2VOQ.mjs → api-key-management-list-WHT7LED5.mjs} +8 -7
- package/dist/{api-key-management-sales-channels-4NTNDHYS.mjs → api-key-management-sales-channels-3WYYKLST.mjs} +1 -1
- package/dist/app.js +13056 -12895
- package/dist/app.mjs +6 -6
- package/dist/{campaign-budget-edit-U6ZGFZCN.mjs → campaign-budget-edit-MVPC66RJ.mjs} +2 -2
- package/dist/{campaign-configuration-SESM5XWE.mjs → campaign-configuration-LTA6NKGQ.mjs} +1 -1
- package/dist/{campaign-create-KUN2YHP2.mjs → campaign-create-XZ3ZCDTE.mjs} +4 -4
- package/dist/{campaign-detail-EW4RJY64.mjs → campaign-detail-ILZA4DJG.mjs} +9 -8
- package/dist/{campaign-edit-TPU6ACYT.mjs → campaign-edit-V7KUN7M5.mjs} +1 -1
- package/dist/{campaign-list-ZGAMG2HJ.mjs → campaign-list-TPH4BBDI.mjs} +8 -7
- package/dist/{categories-metadata-3IX3Y7NM.mjs → categories-metadata-H3TZ7ZC7.mjs} +2 -2
- package/dist/{category-create-NMOUVBVL.mjs → category-create-AKYJLVJ2.mjs} +1 -1
- package/dist/{category-detail-ZIEUC7DM.mjs → category-detail-I6RNSMTN.mjs} +8 -7
- package/dist/{category-edit-HXRXUXIX.mjs → category-edit-PS34TOQX.mjs} +1 -1
- package/dist/{category-products-5GM6K37K.mjs → category-products-6DCNKT6C.mjs} +1 -1
- package/dist/{chunk-QQOHHUDU.mjs → chunk-23BHNQ2L.mjs} +2 -2
- package/dist/chunk-25A53KSK.mjs +156 -0
- package/dist/{chunk-SWN424AE.mjs → chunk-2XG5UPAM.mjs} +3 -3
- package/dist/{chunk-ZCERNCOX.mjs → chunk-34AF5R5P.mjs} +193 -193
- package/dist/{chunk-SOUK6BUQ.mjs → chunk-3M5AAW4J.mjs} +4 -4
- package/dist/{chunk-NANNVVYP.mjs → chunk-4KQBZRB4.mjs} +1 -1
- package/dist/{chunk-JLY6YSEE.mjs → chunk-7FR6ZF6H.mjs} +18 -181
- package/dist/{chunk-JNIMWJV2.mjs → chunk-AFAE54E2.mjs} +2 -2
- package/dist/{chunk-6HTZNHPT.mjs → chunk-B3R53QK3.mjs} +1 -1
- package/dist/{chunk-7ZGGLSE2.mjs → chunk-BXF2VPJX.mjs} +1 -1
- package/dist/{chunk-C36TGGI7.mjs → chunk-DBSNE3L2.mjs} +2 -2
- package/dist/{chunk-DJF6GPIA.mjs → chunk-DOJWUV5E.mjs} +1 -1
- package/dist/{chunk-L6OMZR2J.mjs → chunk-EBK5S7WC.mjs} +1 -1
- package/dist/chunk-HGXZ5BJO.mjs +153 -0
- package/dist/{chunk-WCLL7RVP.mjs → chunk-JPXF73N2.mjs} +1 -1
- package/dist/{chunk-G6CQOB4G.mjs → chunk-JZXJXG3V.mjs} +1 -1
- package/dist/{chunk-AKDC6BWT.mjs → chunk-M7FQTSDS.mjs} +2 -2
- package/dist/{chunk-3UMI3ISU.mjs → chunk-PRJK2BND.mjs} +41 -0
- package/dist/{chunk-LT7MP5JO.mjs → chunk-QFE4OVWT.mjs} +1 -1
- package/dist/{chunk-HZXJDVPI.mjs → chunk-QIK2SODO.mjs} +1 -1
- package/dist/{chunk-6MTTMX7E.mjs → chunk-QW3P2QHZ.mjs} +1 -1
- package/dist/{chunk-UHB4DWUF.mjs → chunk-R2A5UDCT.mjs} +1 -1
- package/dist/{chunk-ZH57KBU7.mjs → chunk-RDBROTJE.mjs} +6 -0
- package/dist/{chunk-Y5ZQ26VN.mjs → chunk-V3TXAU2Y.mjs} +1 -1
- package/dist/{chunk-3NS4FYII.mjs → chunk-VJIURRDA.mjs} +3 -3
- package/dist/{chunk-7QQQEODJ.mjs → chunk-WHWDHRC2.mjs} +1 -1
- package/dist/{chunk-O6JNJQ4K.mjs → chunk-Y2CXBS7S.mjs} +1 -1
- package/dist/{chunk-ZNSPQGIO.mjs → chunk-Z4CMG3I4.mjs} +1 -1
- package/dist/{collection-add-products-JZIEEVAD.mjs → collection-add-products-VHX3EDMB.mjs} +1 -1
- package/dist/{collection-create-ZGCQ3UZ4.mjs → collection-create-BIMST735.mjs} +1 -1
- package/dist/{collection-detail-STCDEYFR.mjs → collection-detail-7SG445Z7.mjs} +8 -7
- package/dist/{collection-edit-Q6UBZJBA.mjs → collection-edit-7E6KSC2T.mjs} +1 -1
- package/dist/{collection-list-7Q74YH4K.mjs → collection-list-4DQ3KSL6.mjs} +8 -7
- package/dist/{collection-metadata-G7HJW3YY.mjs → collection-metadata-CE5JGMBU.mjs} +2 -2
- package/dist/components.js +303 -294
- package/dist/components.mjs +10 -9
- package/dist/{customer-create-5OKTED3S.mjs → customer-create-DUJEC4OL.mjs} +1 -1
- package/dist/{customer-create-address-DXGXL3AR.mjs → customer-create-address-WB6EQTF7.mjs} +1 -1
- package/dist/{customer-detail-VDUTRECH.mjs → customer-detail-OCGWUEAC.mjs} +9 -8
- package/dist/{customer-edit-FCJB2CR3.mjs → customer-edit-45JRYR7C.mjs} +1 -1
- package/dist/{customer-export-CBHVVHT7.mjs → customer-export-SJ7TPUYZ.mjs} +1 -1
- package/dist/{customer-group-add-customers-2MXCI4AU.mjs → customer-group-add-customers-2LO4JWCL.mjs} +1 -1
- package/dist/{customer-group-create-UWEI2IIX.mjs → customer-group-create-46IX5XKC.mjs} +1 -1
- package/dist/{customer-group-detail-537L3QCV.mjs → customer-group-detail-YF4N3ZJQ.mjs} +8 -7
- package/dist/{customer-group-edit-OVOHPO3H.mjs → customer-group-edit-AE5DT44M.mjs} +1 -1
- package/dist/{customer-group-list-KTNZYQTD.mjs → customer-group-list-3ESALQFX.mjs} +8 -7
- package/dist/{customer-group-metadata-5FBOQTIC.mjs → customer-group-metadata-6VTJ63KW.mjs} +2 -2
- package/dist/{customer-list-F7FBYGDK.mjs → customer-list-6QEB7GKU.mjs} +8 -7
- package/dist/{customer-metadata-4AX44PFG.mjs → customer-metadata-MWH222DL.mjs} +2 -2
- package/dist/{customers-add-customer-group-V6FHGHBA.mjs → customers-add-customer-group-K4URSJBC.mjs} +1 -1
- package/dist/{edit-inventory-item-FIAC6T5S.mjs → edit-inventory-item-SIBKLOQ5.mjs} +1 -1
- package/dist/{edit-inventory-item-attributes-32SIJNVQ.mjs → edit-inventory-item-attributes-FX3YWI36.mjs} +1 -1
- package/dist/{edit-reservation-LKXCTILV.mjs → edit-reservation-E6WLT7GE.mjs} +1 -1
- package/dist/{edit-rules-P2W5U34C.mjs → edit-rules-VDWS7LUQ.mjs} +1 -1
- package/dist/{inventory-create-GZQWBRNZ.mjs → inventory-create-XQ6JNL34.mjs} +3 -3
- package/dist/{inventory-list-TNCHH5AH.mjs → inventory-list-XDAGS3IC.mjs} +8 -7
- package/dist/{inventory-metadata-WFC6F5S4.mjs → inventory-metadata-J5VYM2KL.mjs} +2 -2
- package/dist/{inventory-stock-ALPB5DHU.mjs → inventory-stock-OTM7XOOH.mjs} +4 -4
- package/dist/lib.js +6 -0
- package/dist/lib.mjs +5 -5
- package/dist/{location-create-W3N4OIRN.mjs → location-create-65BKVUH7.mjs} +1 -1
- package/dist/{location-edit-WR3GUO2A.mjs → location-edit-XWALWBUW.mjs} +1 -1
- package/dist/{location-fulfillment-providers-IPV42XHK.mjs → location-fulfillment-providers-KSYCKAE3.mjs} +1 -1
- package/dist/{location-list-WX3A2AFK.mjs → location-list-3YQAKOXL.mjs} +8 -7
- package/dist/{location-metadata-H6KEPDM6.mjs → location-metadata-AL6Y2C5Z.mjs} +2 -2
- package/dist/{location-sales-channels-Z4KJ6TA7.mjs → location-sales-channels-P2EKHRGZ.mjs} +1 -1
- package/dist/{location-service-zone-create-LPN2I2A6.mjs → location-service-zone-create-L7MUFXZ7.mjs} +1 -1
- package/dist/{location-service-zone-edit-J5ZQRLT6.mjs → location-service-zone-edit-EH6B7A24.mjs} +1 -1
- package/dist/{location-service-zone-manage-areas-S3D2NRGT.mjs → location-service-zone-manage-areas-SDLDMJO7.mjs} +1 -1
- package/dist/{location-service-zone-shipping-option-create-ZNL5ZAEF.mjs → location-service-zone-shipping-option-create-LOYMYV5B.mjs} +6 -6
- package/dist/{location-service-zone-shipping-option-edit-DUIVARUT.mjs → location-service-zone-shipping-option-edit-BARLZ7H6.mjs} +1 -1
- package/dist/{location-service-zone-shipping-option-pricing-ESOFTO36.mjs → location-service-zone-shipping-option-pricing-6DR7Z2W5.mjs} +6 -6
- package/dist/{order-allocate-items-WM3SQ6YO.mjs → order-allocate-items-CTQLV42Q.mjs} +1 -1
- package/dist/{order-create-claim-W2PFYFZZ.mjs → order-create-claim-P5WL2XWX.mjs} +5 -5
- package/dist/{order-create-edit-V52ZDF54.mjs → order-create-edit-7NCWX6UB.mjs} +4 -4
- package/dist/{order-create-exchange-5U3ULMBH.mjs → order-create-exchange-MU566SDR.mjs} +5 -5
- package/dist/{order-create-fulfillment-CT5XV576.mjs → order-create-fulfillment-57GSNWKY.mjs} +1 -1
- package/dist/{order-create-refund-VUOUFSMS.mjs → order-create-refund-SZT2AGMZ.mjs} +3 -3
- package/dist/{order-create-return-NWPAQFIJ.mjs → order-create-return-NNDQSKD3.mjs} +5 -5
- package/dist/{order-create-shipment-FVFRAISJ.mjs → order-create-shipment-RQK7EC47.mjs} +1 -1
- package/dist/{order-detail-DMWYRRGT.mjs → order-detail-ERHRK6W3.mjs} +2 -2
- package/dist/{order-edit-billing-address-NDCMYXJ6.mjs → order-edit-billing-address-XCGDGT6L.mjs} +1 -1
- package/dist/{order-edit-email-COPXQGIB.mjs → order-edit-email-7DJEDL7L.mjs} +1 -1
- package/dist/{order-edit-shipping-address-VZKXPB2N.mjs → order-edit-shipping-address-G6UVC32Y.mjs} +1 -1
- package/dist/{order-export-KZ7DK7W7.mjs → order-export-X4GFB4OT.mjs} +1 -1
- package/dist/{order-list-NQT2DVHU.mjs → order-list-Y4KAYHDB.mjs} +9 -8
- package/dist/{order-metadata-STLSWSXP.mjs → order-metadata-LX5ZWHQF.mjs} +2 -2
- package/dist/{order-receive-return-JA3JNAHR.mjs → order-receive-return-QXVVZFHF.mjs} +3 -3
- package/dist/{order-request-transfer-ZD5KDNCB.mjs → order-request-transfer-ZEQOYAL6.mjs} +1 -1
- package/dist/{policy-list-45PG7GBA.mjs → policy-list-ENDXAWFU.mjs} +1 -1
- package/dist/{price-list-configuration-TPUOHUER.mjs → price-list-configuration-BQZRBNXQ.mjs} +1 -1
- package/dist/{price-list-create-QPBMO7LD.mjs → price-list-create-XN53E6RE.mjs} +6 -6
- package/dist/{price-list-detail-SM4DA6L7.mjs → price-list-detail-2R24L2L3.mjs} +8 -7
- package/dist/{price-list-edit-5E2FLEHN.mjs → price-list-edit-7EIZ3FVK.mjs} +1 -1
- package/dist/{price-list-list-V4XVXOAV.mjs → price-list-list-B3PGM3ND.mjs} +8 -7
- package/dist/{price-list-metadata-DCSZAO2C.mjs → price-list-metadata-NTJKQEOE.mjs} +2 -2
- package/dist/{price-list-prices-add-QB2QORIN.mjs → price-list-prices-add-E3O2OI7K.mjs} +6 -6
- package/dist/{price-list-prices-edit-3EWBS4PO.mjs → price-list-prices-edit-L45MXHZR.mjs} +6 -6
- package/dist/{product-attributes-VDTTOEN6.mjs → product-attributes-FXOAXOQ5.mjs} +2 -2
- package/dist/{product-create-WUZ22WMJ.mjs → product-create-3XQUET7Y.mjs} +4 -4
- package/dist/{product-create-variant-ZMBY5CDO.mjs → product-create-variant-KZAUREQY.mjs} +3 -3
- package/dist/{product-detail-Q7R6CEZD.mjs → product-detail-EFCAHRXH.mjs} +2 -2
- package/dist/{product-edit-FIAXOVZP.mjs → product-edit-YKIGN4M3.mjs} +2 -2
- package/dist/product-export-VTUEQCYE.mjs +260 -0
- package/dist/{product-image-variants-edit-6MOKSV2U.mjs → product-image-variants-edit-Y3M56B2U.mjs} +1 -1
- package/dist/{product-list-UKJVYCMV.mjs → product-list-XAW4AQNH.mjs} +32 -174
- package/dist/{product-media-72TTTVV5.mjs → product-media-HGLANNNT.mjs} +10 -6
- package/dist/{product-metadata-4KPGJ36Y.mjs → product-metadata-LTW4M2N3.mjs} +2 -2
- package/dist/{product-option-create-4C2BHWTH.mjs → product-option-create-EIKW4V3P.mjs} +1 -1
- package/dist/{product-option-detail-WQCRUROA.mjs → product-option-detail-LE44YFQQ.mjs} +9 -8
- package/dist/{product-option-edit-O354X7DK.mjs → product-option-edit-5ZP4YBAR.mjs} +1 -1
- package/dist/{product-option-list-52TQV6GJ.mjs → product-option-list-JQGZMNPD.mjs} +8 -7
- package/dist/{product-option-metadata-K5E6CV4U.mjs → product-option-metadata-2G47V6ZL.mjs} +2 -2
- package/dist/{product-option-value-metadata-QJ6D5GPI.mjs → product-option-value-metadata-PDG22GD2.mjs} +2 -2
- package/dist/{product-options-manage-H3RCESKS.mjs → product-options-manage-NXZ6CDGE.mjs} +3 -3
- package/dist/{product-organization-PAEWTW56.mjs → product-organization-K6EGAZZC.mjs} +2 -2
- package/dist/{product-prices-DK6LKOIN.mjs → product-prices-B3DJOMTS.mjs} +3 -3
- package/dist/{product-shipping-profile-CGQN7EL4.mjs → product-shipping-profile-NDMCCENZ.mjs} +1 -1
- package/dist/{product-stock-G3QGRX2B.mjs → product-stock-FNMVF2RH.mjs} +4 -4
- package/dist/{product-tag-create-QRJM6LX5.mjs → product-tag-create-HBIXYJDZ.mjs} +1 -1
- package/dist/{product-tag-detail-27XONTR7.mjs → product-tag-detail-ZSPQRFDC.mjs} +9 -8
- package/dist/{product-tag-edit-XE5MJ7M2.mjs → product-tag-edit-TO2ACUK3.mjs} +1 -1
- package/dist/{product-tag-list-FB25LCY5.mjs → product-tag-list-D5HZNBL3.mjs} +9 -8
- package/dist/{product-tag-metadata-K563ZKCO.mjs → product-tag-metadata-7P3JGVYS.mjs} +2 -2
- package/dist/{product-type-create-T36A3NSA.mjs → product-type-create-2AZKVK35.mjs} +1 -1
- package/dist/{product-type-detail-HCA2AKIV.mjs → product-type-detail-JNFFSUC2.mjs} +8 -7
- package/dist/{product-type-edit-TGVPP66B.mjs → product-type-edit-SOLNOW3Y.mjs} +1 -1
- package/dist/{product-type-list-G3ROKD3W.mjs → product-type-list-2FWI6OVE.mjs} +8 -7
- package/dist/{product-type-metadata-Q4TNWB2C.mjs → product-type-metadata-HTEP2YTQ.mjs} +2 -2
- package/dist/{product-variant-detail-IEV2JJM7.mjs → product-variant-detail-FDCRPWMV.mjs} +2 -2
- package/dist/{product-variant-edit-CVG5DWFB.mjs → product-variant-edit-Z4ELZB47.mjs} +1 -1
- package/dist/{product-variant-manage-inventory-items-GJNQW7JC.mjs → product-variant-manage-inventory-items-W3ZQDUML.mjs} +1 -1
- package/dist/{product-variant-media-XT2EQ5M2.mjs → product-variant-media-JARM7GQW.mjs} +1 -1
- package/dist/{product-variant-metadata-YXMJ3XTG.mjs → product-variant-metadata-LP3RK7D3.mjs} +2 -2
- package/dist/{profile-edit-L3F567PF.mjs → profile-edit-S4F52I66.mjs} +1 -1
- package/dist/{promotion-add-campaign-5Q7YXHM3.mjs → promotion-add-campaign-MFC6I5JW.mjs} +4 -4
- package/dist/{promotion-create-G5A3CLSU.mjs → promotion-create-USUUTWHS.mjs} +5 -5
- package/dist/{promotion-edit-details-7BKQR36L.mjs → promotion-edit-details-3INVCAPZ.mjs} +2 -2
- package/dist/{promotion-list-F4UKF55J.mjs → promotion-list-SRJ6MO3U.mjs} +9 -8
- package/dist/{promotion-metadata-CFGQFARL.mjs → promotion-metadata-QNNWNI6S.mjs} +2 -2
- package/dist/{property-labels-WALH2AGU.mjs → property-labels-4PJQJXTH.mjs} +5 -5
- package/dist/{property-labels-edit-WOGYPDDG.mjs → property-labels-edit-5QFRPGAO.mjs} +3 -3
- package/dist/{refund-reason-create-PY3Z64HW.mjs → refund-reason-create-QXHOKWDZ.mjs} +1 -1
- package/dist/{refund-reason-edit-UYQP4C6W.mjs → refund-reason-edit-RQFGSNGN.mjs} +1 -1
- package/dist/{refund-reason-list-SM5XTUD5.mjs → refund-reason-list-RKULHAWA.mjs} +9 -8
- package/dist/{region-add-countries-ICNGZMFP.mjs → region-add-countries-L3LBC5SS.mjs} +1 -1
- package/dist/{region-create-VWAGH4BK.mjs → region-create-IISVSM64.mjs} +2 -2
- package/dist/{region-detail-IXDWO6A6.mjs → region-detail-L3YT7CAJ.mjs} +1 -1
- package/dist/{region-edit-LDKU5GRF.mjs → region-edit-6TJFOZ6L.mjs} +2 -2
- package/dist/{region-list-P5BUNYLG.mjs → region-list-UOWKWKH3.mjs} +8 -7
- package/dist/{region-metadata-QNHAH2KJ.mjs → region-metadata-2GTR2Q4K.mjs} +2 -2
- package/dist/{reservation-create-OFCQFQAO.mjs → reservation-create-TJPEHJO4.mjs} +1 -1
- package/dist/{reservation-list-7R3KIRZM.mjs → reservation-list-3IBGFDFV.mjs} +8 -7
- package/dist/{reservation-metadata-W4CVXJXT.mjs → reservation-metadata-H6XWWZ7O.mjs} +2 -2
- package/dist/{return-reason-create-NNPGF6E6.mjs → return-reason-create-GLORKWFC.mjs} +1 -1
- package/dist/{return-reason-edit-BMSZB2JK.mjs → return-reason-edit-G2KHDOVU.mjs} +1 -1
- package/dist/{return-reason-list-IIKH6WL6.mjs → return-reason-list-2NBTNAH3.mjs} +9 -8
- package/dist/{role-add-users-UIEDW5HE.mjs → role-add-users-O7CTRYF2.mjs} +1 -1
- package/dist/{role-create-M3Y7KHT5.mjs → role-create-J5TXRN2A.mjs} +1 -1
- package/dist/{role-edit-76JHBTDL.mjs → role-edit-6CTPHWGH.mjs} +1 -1
- package/dist/{role-permissions-7D7D37MZ.mjs → role-permissions-F6WANR5D.mjs} +1 -1
- package/dist/{sales-channel-add-products-OUWMFPUM.mjs → sales-channel-add-products-S7NJUD3G.mjs} +1 -1
- package/dist/{sales-channel-create-YMFBTQTV.mjs → sales-channel-create-YDM7SRWK.mjs} +1 -1
- package/dist/{sales-channel-edit-CQOUQ4HC.mjs → sales-channel-edit-BPTKLMWV.mjs} +1 -1
- package/dist/{sales-channel-list-26DGOXPN.mjs → sales-channel-list-P7JPONDZ.mjs} +9 -8
- package/dist/{sales-channel-metadata-DYXIDARU.mjs → sales-channel-metadata-R36JO2U7.mjs} +2 -2
- package/dist/{search-index-list-UMBYJEE2.mjs → search-index-list-UUJXL4UL.mjs} +1 -1
- package/dist/{settings-NUX5MO5M.mjs → settings-L3FQOPX3.mjs} +1 -1
- package/dist/{shipping-option-type-create-E3U6A5AP.mjs → shipping-option-type-create-O62NAECA.mjs} +1 -1
- package/dist/{shipping-option-type-edit-AWLY6VGH.mjs → shipping-option-type-edit-NZQQSODS.mjs} +1 -1
- package/dist/{shipping-option-type-list-IS33BXIS.mjs → shipping-option-type-list-MZGGUXYT.mjs} +8 -7
- package/dist/{shipping-profile-create-Q4MANTUB.mjs → shipping-profile-create-WPLVLDXG.mjs} +1 -1
- package/dist/{shipping-profile-metadata-3E3MFK6S.mjs → shipping-profile-metadata-IEQP6IVY.mjs} +2 -2
- package/dist/{shipping-profiles-list-R2OKGF64.mjs → shipping-profiles-list-3TNRV7U4.mjs} +8 -7
- package/dist/{store-add-currencies-PM37F2M6.mjs → store-add-currencies-HBAN3GWA.mjs} +1 -1
- package/dist/{store-add-locales-TF4A4LOI.mjs → store-add-locales-VJWN65EE.mjs} +2 -2
- package/dist/{store-edit-BUNHDYE2.mjs → store-edit-SKGGBBFN.mjs} +1 -1
- package/dist/{store-metadata-XQI3KTO6.mjs → store-metadata-4P3U6G7J.mjs} +2 -2
- package/dist/{tax-region-create-HESVWGCI.mjs → tax-region-create-AI2IQGAX.mjs} +1 -1
- package/dist/{tax-region-detail-4N5VVAA3.mjs → tax-region-detail-OOB7SOFT.mjs} +10 -10
- package/dist/{tax-region-edit-T534TZN6.mjs → tax-region-edit-AAVTEU6A.mjs} +1 -1
- package/dist/{tax-region-province-create-PM3ZTK5Q.mjs → tax-region-province-create-UDBHBE66.mjs} +1 -1
- package/dist/{tax-region-province-detail-LP6LQFU3.mjs → tax-region-province-detail-RW6ORJ3I.mjs} +10 -10
- package/dist/{tax-region-tax-override-create-EOSGUTGM.mjs → tax-region-tax-override-create-7BXNHR5F.mjs} +8 -8
- package/dist/{tax-region-tax-override-edit-RFHZPX7T.mjs → tax-region-tax-override-edit-VTP7B3W3.mjs} +9 -9
- package/dist/{tax-region-tax-rate-create-23WNEWRS.mjs → tax-region-tax-rate-create-4MNRDQMB.mjs} +1 -1
- package/dist/{tax-region-tax-rate-edit-II6LQJU7.mjs → tax-region-tax-rate-edit-EQEPSONV.mjs} +1 -1
- package/dist/{translations-edit-IGHIRXSY.mjs → translations-edit-3264U52X.mjs} +3 -3
- package/dist/{user-edit-QAGGKUD5.mjs → user-edit-UYE4NST2.mjs} +1 -1
- package/dist/{user-invite-DDESHVJK.mjs → user-invite-RLAG4P4K.mjs} +1 -1
- package/dist/{user-list-KIRMDCPZ.mjs → user-list-GN3FM5YA.mjs} +8 -7
- package/dist/{user-metadata-FIHOQQBD.mjs → user-metadata-BVIBE7ID.mjs} +2 -2
- package/package.json +9 -9
- package/src/__tests__/vite-config.spec.ts +46 -0
- package/src/components/table/configurable-data-table/configurable-data-table.tsx +1 -27
- package/src/components/utilities/keybound-form/__tests__/keybound-form.spec.ts +65 -0
- package/src/components/utilities/keybound-form/keybound-form.tsx +3 -1
- package/src/hooks/table/query/index.ts +1 -0
- package/src/hooks/table/query/parse-prefixed-query-params.ts +64 -0
- package/src/hooks/table/use-column-filters.tsx +44 -0
- package/src/hooks/table/use-table-configuration.tsx +3 -34
- package/src/lib/data/currencies.ts +6 -0
- package/src/routes/orders/order-create-claim/components/claim-create-form/claim-inbound-item.tsx +2 -1
- package/src/routes/orders/order-create-exchange/components/exchange-create-form/exchange-inbound-item.tsx +2 -1
- package/src/routes/orders/order-create-return/components/return-create-form/return-item.tsx +2 -1
- package/src/routes/products/product-export/components/configurable-export-filters.spec.tsx +69 -0
- package/src/routes/products/product-export/components/configurable-export-filters.tsx +104 -0
- package/src/routes/products/product-export/components/export-filters.tsx +14 -2
- package/src/routes/products/product-export/product-export.spec.tsx +131 -0
- package/src/routes/products/product-export/product-export.tsx +24 -4
- package/src/routes/products/product-media/components/edit-product-media-form/edit-product-media-form.spec.tsx +164 -0
- package/src/routes/products/product-media/components/edit-product-media-form/edit-product-media-form.tsx +13 -9
- package/dist/product-export-FVEBRZUJ.mjs +0 -138
|
@@ -12,6 +12,7 @@ import { ChatBubble, DocumentText, XCircle, XMark } from "@medusajs/icons"
|
|
|
12
12
|
import { Thumbnail } from "../../../../../components/common/thumbnail"
|
|
13
13
|
import { MoneyAmountCell } from "../../../../../components/table/table-cells/common/money-amount-cell"
|
|
14
14
|
import { Form } from "../../../../../components/common/form"
|
|
15
|
+
import { getReturnableQuantity } from "../../../../../lib/rma"
|
|
15
16
|
import {
|
|
16
17
|
Action,
|
|
17
18
|
ActionMenu,
|
|
@@ -79,7 +80,7 @@ function ReturnItem({
|
|
|
79
80
|
<Input
|
|
80
81
|
className="bg-ui-bg-base txt-small w-[67px] rounded-lg"
|
|
81
82
|
min={1}
|
|
82
|
-
max={item
|
|
83
|
+
max={getReturnableQuantity(item)}
|
|
83
84
|
type="number"
|
|
84
85
|
{...field}
|
|
85
86
|
onChange={(e) => {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { renderToString } from "react-dom/server"
|
|
3
|
+
import { MemoryRouter } from "react-router-dom"
|
|
4
|
+
import { describe, expect, it, vi } from "vitest"
|
|
5
|
+
|
|
6
|
+
import { ConfigurableExportFilters } from "./configurable-export-filters"
|
|
7
|
+
|
|
8
|
+
vi.mock("@medusajs/ui", () => ({
|
|
9
|
+
Text: ({ children }: { children: React.ReactNode }) => (
|
|
10
|
+
<span>{children}</span>
|
|
11
|
+
),
|
|
12
|
+
}))
|
|
13
|
+
|
|
14
|
+
vi.mock("../../../../hooks/api/views", () => ({
|
|
15
|
+
useEntityColumns: () => ({ columns: [] }),
|
|
16
|
+
}))
|
|
17
|
+
|
|
18
|
+
vi.mock("../../../../hooks/table/use-column-filters", () => ({
|
|
19
|
+
useColumnFilters: () => ({
|
|
20
|
+
filters: [
|
|
21
|
+
{
|
|
22
|
+
id: "status",
|
|
23
|
+
label: "Status",
|
|
24
|
+
type: "multiselect",
|
|
25
|
+
options: [
|
|
26
|
+
{ label: "Draft", value: "draft" },
|
|
27
|
+
{ label: "Published", value: "published" },
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: "collection.id",
|
|
32
|
+
label: "Collection",
|
|
33
|
+
type: "multiselect",
|
|
34
|
+
options: [{ label: "Summer", value: "pcol_1" }],
|
|
35
|
+
},
|
|
36
|
+
{ id: "handle", label: "Handle", type: "string" },
|
|
37
|
+
],
|
|
38
|
+
isLoading: false,
|
|
39
|
+
}),
|
|
40
|
+
}))
|
|
41
|
+
|
|
42
|
+
vi.mock(
|
|
43
|
+
"../../product-list/components/product-list-table/product-table-adapter",
|
|
44
|
+
() => ({
|
|
45
|
+
useProductTableAdapter: () => ({ entity: "products", queryPrefix: "p" }),
|
|
46
|
+
})
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
describe("ConfigurableExportFilters", () => {
|
|
50
|
+
it("should display the applied product list filters", () => {
|
|
51
|
+
const params = new URLSearchParams({
|
|
52
|
+
p_status: JSON.stringify(["draft", "published"]),
|
|
53
|
+
"p_collection.id": JSON.stringify(["pcol_1"]),
|
|
54
|
+
p_handle: JSON.stringify(""),
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const html = renderToString(
|
|
58
|
+
<MemoryRouter initialEntries={[`/products/export?${params.toString()}`]}>
|
|
59
|
+
<ConfigurableExportFilters />
|
|
60
|
+
</MemoryRouter>
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
expect(html).toContain("Status")
|
|
64
|
+
expect(html).toContain("Draft, Published")
|
|
65
|
+
expect(html).toContain("Collection")
|
|
66
|
+
expect(html).toContain("Summer")
|
|
67
|
+
expect(html).not.toContain("Handle")
|
|
68
|
+
})
|
|
69
|
+
})
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { DataTableFilter, Text } from "@medusajs/ui"
|
|
2
|
+
import { useMemo } from "react"
|
|
3
|
+
import { useSearchParams } from "react-router-dom"
|
|
4
|
+
import { useEntityColumns } from "../../../../hooks/api/views"
|
|
5
|
+
import { parseFilterParam } from "../../../../hooks/table/query"
|
|
6
|
+
import { useColumnFilters } from "../../../../hooks/table/use-column-filters"
|
|
7
|
+
import { useDate } from "../../../../hooks/use-date"
|
|
8
|
+
import { useProductTableAdapter } from "../../product-list/components/product-list-table/product-table-adapter"
|
|
9
|
+
|
|
10
|
+
const OPERATOR_LABELS: Record<string, string> = {
|
|
11
|
+
$eq: "=",
|
|
12
|
+
$gt: ">",
|
|
13
|
+
$gte: "≥",
|
|
14
|
+
$lt: "<",
|
|
15
|
+
$lte: "≤",
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const ConfigurableExportFilters = () => {
|
|
19
|
+
const adapter = useProductTableAdapter()
|
|
20
|
+
const [searchParams] = useSearchParams()
|
|
21
|
+
const { getFullDate } = useDate()
|
|
22
|
+
|
|
23
|
+
const { columns } = useEntityColumns(adapter.entity)
|
|
24
|
+
const apiColumns = useMemo(() => {
|
|
25
|
+
return columns && adapter.transformColumns
|
|
26
|
+
? adapter.transformColumns(columns)
|
|
27
|
+
: columns
|
|
28
|
+
}, [adapter, columns])
|
|
29
|
+
const { filters } = useColumnFilters(apiColumns)
|
|
30
|
+
|
|
31
|
+
const activeFilters = filters.flatMap((filter) => {
|
|
32
|
+
const value = parseFilterParam(
|
|
33
|
+
searchParams.get(`${adapter.queryPrefix}_${filter.id}`)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
if (value === undefined) {
|
|
37
|
+
return []
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return [
|
|
41
|
+
{
|
|
42
|
+
id: filter.id,
|
|
43
|
+
label: filter.label,
|
|
44
|
+
value: formatFilterValue(filter, value, (date) =>
|
|
45
|
+
getFullDate({ date })
|
|
46
|
+
),
|
|
47
|
+
},
|
|
48
|
+
]
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
53
|
+
{activeFilters.map((filter) => (
|
|
54
|
+
<div
|
|
55
|
+
key={filter.id}
|
|
56
|
+
className="bg-ui-bg-field shadow-borders-base text-ui-fg-subtle flex items-stretch overflow-hidden rounded-md"
|
|
57
|
+
>
|
|
58
|
+
<Text
|
|
59
|
+
size="small"
|
|
60
|
+
weight="plus"
|
|
61
|
+
leading="compact"
|
|
62
|
+
className="whitespace-nowrap border-r px-2 py-1"
|
|
63
|
+
>
|
|
64
|
+
{filter.label}
|
|
65
|
+
</Text>
|
|
66
|
+
<Text
|
|
67
|
+
size="small"
|
|
68
|
+
weight="plus"
|
|
69
|
+
leading="compact"
|
|
70
|
+
className="truncate px-2 py-1"
|
|
71
|
+
>
|
|
72
|
+
{filter.value}
|
|
73
|
+
</Text>
|
|
74
|
+
</div>
|
|
75
|
+
))}
|
|
76
|
+
</div>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const formatFilterValue = (
|
|
81
|
+
filter: DataTableFilter,
|
|
82
|
+
value: unknown,
|
|
83
|
+
formatDate: (date: string) => string
|
|
84
|
+
): string => {
|
|
85
|
+
const options = "options" in filter ? filter.options : undefined
|
|
86
|
+
const getLabel = (v: unknown) =>
|
|
87
|
+
options?.find((option) => option.value === v)?.label ?? String(v)
|
|
88
|
+
|
|
89
|
+
if (Array.isArray(value)) {
|
|
90
|
+
return value.map(getLabel).join(", ")
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (value && typeof value === "object") {
|
|
94
|
+
return Object.entries(value)
|
|
95
|
+
.map(([operator, operand]) => {
|
|
96
|
+
const formatted =
|
|
97
|
+
filter.type === "date" ? formatDate(operand) : String(operand)
|
|
98
|
+
return `${OPERATOR_LABELS[operator] ?? operator} ${formatted}`
|
|
99
|
+
})
|
|
100
|
+
.join(", ")
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return getLabel(value)
|
|
104
|
+
}
|
|
@@ -2,10 +2,12 @@ import { Heading, Text } from "@medusajs/ui"
|
|
|
2
2
|
import { DataTableFilter } from "../../../../components/table/data-table/data-table-filter"
|
|
3
3
|
import { useTranslation } from "react-i18next"
|
|
4
4
|
import { useProductTableFilters } from "../../../../hooks/table/filters"
|
|
5
|
+
import { useFeatureFlag } from "../../../../providers/feature-flag-provider"
|
|
6
|
+
import { ConfigurableExportFilters } from "./configurable-export-filters"
|
|
5
7
|
|
|
6
8
|
export const ExportFilters = () => {
|
|
7
9
|
const { t } = useTranslation()
|
|
8
|
-
const
|
|
10
|
+
const isViewConfigEnabled = useFeatureFlag("view_configurations")
|
|
9
11
|
|
|
10
12
|
return (
|
|
11
13
|
<div>
|
|
@@ -15,8 +17,18 @@ export const ExportFilters = () => {
|
|
|
15
17
|
</Text>
|
|
16
18
|
|
|
17
19
|
<div className="mt-4">
|
|
18
|
-
|
|
20
|
+
{isViewConfigEnabled ? (
|
|
21
|
+
<ConfigurableExportFilters />
|
|
22
|
+
) : (
|
|
23
|
+
<LegacyExportFilters />
|
|
24
|
+
)}
|
|
19
25
|
</div>
|
|
20
26
|
</div>
|
|
21
27
|
)
|
|
22
28
|
}
|
|
29
|
+
|
|
30
|
+
const LegacyExportFilters = () => {
|
|
31
|
+
const filters = useProductTableFilters()
|
|
32
|
+
|
|
33
|
+
return <DataTableFilter filters={filters} readonly />
|
|
34
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { renderToString } from "react-dom/server"
|
|
3
|
+
import { MemoryRouter } from "react-router-dom"
|
|
4
|
+
import { afterEach, describe, expect, it, vi } from "vitest"
|
|
5
|
+
|
|
6
|
+
import { ProductExport } from "./product-export"
|
|
7
|
+
|
|
8
|
+
const mocks = vi.hoisted(() => ({
|
|
9
|
+
mutateAsync: vi.fn(),
|
|
10
|
+
isViewConfigEnabled: false,
|
|
11
|
+
buttonClicks: {} as Record<string, () => unknown>,
|
|
12
|
+
}))
|
|
13
|
+
|
|
14
|
+
vi.mock("react-i18next", () => ({
|
|
15
|
+
useTranslation: () => ({
|
|
16
|
+
t: (key: string) => key,
|
|
17
|
+
}),
|
|
18
|
+
}))
|
|
19
|
+
|
|
20
|
+
vi.mock("@medusajs/ui", () => ({
|
|
21
|
+
Button: ({ children, onClick }: React.ComponentProps<"button">) => {
|
|
22
|
+
if (typeof children === "string" && onClick) {
|
|
23
|
+
mocks.buttonClicks[children] = onClick as () => unknown
|
|
24
|
+
}
|
|
25
|
+
return <button>{children}</button>
|
|
26
|
+
},
|
|
27
|
+
Heading: ({ children }: { children: React.ReactNode }) => <h1>{children}</h1>,
|
|
28
|
+
toast: {
|
|
29
|
+
info: vi.fn(),
|
|
30
|
+
error: vi.fn(),
|
|
31
|
+
},
|
|
32
|
+
}))
|
|
33
|
+
|
|
34
|
+
vi.mock("../../../components/modals", () => {
|
|
35
|
+
const Passthrough = ({ children }: { children: React.ReactNode }) => (
|
|
36
|
+
<>{children}</>
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
RouteDrawer: Object.assign(Passthrough, {
|
|
41
|
+
Header: Passthrough,
|
|
42
|
+
Title: Passthrough,
|
|
43
|
+
Description: Passthrough,
|
|
44
|
+
Body: Passthrough,
|
|
45
|
+
Footer: Passthrough,
|
|
46
|
+
Close: () => null,
|
|
47
|
+
}),
|
|
48
|
+
useRouteModal: () => ({ handleSuccess: vi.fn() }),
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
vi.mock("./components/export-filters", () => ({
|
|
53
|
+
ExportFilters: () => null,
|
|
54
|
+
}))
|
|
55
|
+
|
|
56
|
+
vi.mock("../../../providers/feature-flag-provider", () => ({
|
|
57
|
+
useFeatureFlag: () => mocks.isViewConfigEnabled,
|
|
58
|
+
}))
|
|
59
|
+
|
|
60
|
+
vi.mock("../../../hooks/api", () => ({
|
|
61
|
+
useExportProducts: () => ({ mutateAsync: mocks.mutateAsync }),
|
|
62
|
+
}))
|
|
63
|
+
|
|
64
|
+
const exportAt = async (url: string) => {
|
|
65
|
+
renderToString(
|
|
66
|
+
<MemoryRouter initialEntries={[url]}>
|
|
67
|
+
<ProductExport />
|
|
68
|
+
</MemoryRouter>
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
await mocks.buttonClicks["actions.export"]()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
describe("ProductExport", () => {
|
|
75
|
+
afterEach(() => {
|
|
76
|
+
mocks.mutateAsync.mockReset()
|
|
77
|
+
mocks.buttonClicks = {}
|
|
78
|
+
mocks.isViewConfigEnabled = false
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it("should send the product list filters from the URL with the export request", async () => {
|
|
82
|
+
await exportAt(
|
|
83
|
+
"/products/export?status=draft&q=shirt&collection_id=pcol_1&tag_id=ptag_1&created_at=%7B%22%24gte%22%3A%222024-01-01%22%7D"
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
expect(mocks.mutateAsync).toHaveBeenCalledTimes(1)
|
|
87
|
+
expect(mocks.mutateAsync.mock.calls[0][0]).toEqual({
|
|
88
|
+
payload: {},
|
|
89
|
+
query: expect.objectContaining({
|
|
90
|
+
status: ["draft"],
|
|
91
|
+
q: "shirt",
|
|
92
|
+
collection_id: ["pcol_1"],
|
|
93
|
+
tag_id: ["ptag_1"],
|
|
94
|
+
created_at: { $gte: "2024-01-01" },
|
|
95
|
+
}),
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
it("should not send the list fields with the export request", async () => {
|
|
100
|
+
await exportAt("/products/export?status=draft")
|
|
101
|
+
|
|
102
|
+
expect(mocks.mutateAsync.mock.calls[0][0].query).not.toHaveProperty(
|
|
103
|
+
"fields"
|
|
104
|
+
)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it("should send the configurable product list filters from the URL with the export request", async () => {
|
|
108
|
+
mocks.isViewConfigEnabled = true
|
|
109
|
+
const params = new URLSearchParams({
|
|
110
|
+
p_status: JSON.stringify(["draft"]),
|
|
111
|
+
p_q: "shirt",
|
|
112
|
+
"p_collection.id": JSON.stringify(["pcol_1"]),
|
|
113
|
+
p_created_at: JSON.stringify({ $gte: "2024-01-01" }),
|
|
114
|
+
p_handle: JSON.stringify(""),
|
|
115
|
+
p_order: "-created_at",
|
|
116
|
+
p_offset: "20",
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
await exportAt(`/products/export?${params.toString()}`)
|
|
120
|
+
|
|
121
|
+
expect(mocks.mutateAsync.mock.calls[0][0]).toEqual({
|
|
122
|
+
payload: {},
|
|
123
|
+
query: {
|
|
124
|
+
status: ["draft"],
|
|
125
|
+
q: "shirt",
|
|
126
|
+
collection: { id: ["pcol_1"] },
|
|
127
|
+
created_at: { $gte: "2024-01-01" },
|
|
128
|
+
},
|
|
129
|
+
})
|
|
130
|
+
})
|
|
131
|
+
})
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
import { HttpTypes } from "@medusajs/types"
|
|
1
2
|
import { Button, Heading, toast } from "@medusajs/ui"
|
|
3
|
+
import { useSearchParams } from "react-router-dom"
|
|
2
4
|
import { RouteDrawer, useRouteModal } from "../../../components/modals"
|
|
3
5
|
import { useTranslation } from "react-i18next"
|
|
4
6
|
import { ExportFilters } from "./components/export-filters"
|
|
5
7
|
import { useExportProducts } from "../../../hooks/api"
|
|
6
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
parsePrefixedQueryParams,
|
|
10
|
+
useProductTableQuery,
|
|
11
|
+
} from "../../../hooks/table/query"
|
|
12
|
+
import { useFeatureFlag } from "../../../providers/feature-flag-provider"
|
|
7
13
|
|
|
8
14
|
export const ProductExport = () => {
|
|
9
15
|
const { t } = useTranslation()
|
|
@@ -25,8 +31,7 @@ export const ProductExport = () => {
|
|
|
25
31
|
|
|
26
32
|
const ProductExportContent = () => {
|
|
27
33
|
const { t } = useTranslation()
|
|
28
|
-
const
|
|
29
|
-
delete searchParams.fields
|
|
34
|
+
const exportQuery = useExportQuery()
|
|
30
35
|
|
|
31
36
|
const { mutateAsync } = useExportProducts()
|
|
32
37
|
const { handleSuccess } = useRouteModal()
|
|
@@ -35,7 +40,7 @@ const ProductExportContent = () => {
|
|
|
35
40
|
await mutateAsync(
|
|
36
41
|
{
|
|
37
42
|
payload: {},
|
|
38
|
-
query:
|
|
43
|
+
query: exportQuery,
|
|
39
44
|
},
|
|
40
45
|
{
|
|
41
46
|
onSuccess: () => {
|
|
@@ -72,3 +77,18 @@ const ProductExportContent = () => {
|
|
|
72
77
|
</>
|
|
73
78
|
)
|
|
74
79
|
}
|
|
80
|
+
|
|
81
|
+
const PRODUCT_TABLE_QUERY_PREFIX = "p"
|
|
82
|
+
|
|
83
|
+
const useExportQuery = (): HttpTypes.AdminProductListParams => {
|
|
84
|
+
const isViewConfigEnabled = useFeatureFlag("view_configurations")
|
|
85
|
+
const [urlSearchParams] = useSearchParams()
|
|
86
|
+
const { searchParams } = useProductTableQuery({})
|
|
87
|
+
|
|
88
|
+
if (isViewConfigEnabled) {
|
|
89
|
+
return parsePrefixedQueryParams(urlSearchParams, PRODUCT_TABLE_QUERY_PREFIX)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const { fields: _fields, ...query } = searchParams
|
|
93
|
+
return query
|
|
94
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { HttpTypes } from "@medusajs/types"
|
|
2
|
+
import { ReactElement } from "react"
|
|
3
|
+
import { beforeEach, describe, expect, it, vi } from "vitest"
|
|
4
|
+
|
|
5
|
+
import { EditProductMediaForm } from "./edit-product-media-form"
|
|
6
|
+
|
|
7
|
+
const mocks = vi.hoisted(() => ({
|
|
8
|
+
uploadCreate: vi.fn(),
|
|
9
|
+
mutateAsync: vi.fn(),
|
|
10
|
+
setError: vi.fn(),
|
|
11
|
+
}))
|
|
12
|
+
|
|
13
|
+
vi.mock("react", async (importOriginal) => ({
|
|
14
|
+
...(await importOriginal<typeof import("react")>()),
|
|
15
|
+
useState: (initial: unknown) => [initial, vi.fn()],
|
|
16
|
+
useCallback: (fn: unknown) => fn,
|
|
17
|
+
}))
|
|
18
|
+
|
|
19
|
+
vi.mock("react-hook-form", () => ({
|
|
20
|
+
useForm: () => ({
|
|
21
|
+
control: {},
|
|
22
|
+
handleSubmit: (fn: unknown) => fn,
|
|
23
|
+
setError: mocks.setError,
|
|
24
|
+
}),
|
|
25
|
+
useFieldArray: () => ({
|
|
26
|
+
fields: [],
|
|
27
|
+
append: vi.fn(),
|
|
28
|
+
remove: vi.fn(),
|
|
29
|
+
update: vi.fn(),
|
|
30
|
+
}),
|
|
31
|
+
}))
|
|
32
|
+
|
|
33
|
+
vi.mock("@dnd-kit/core", async (importOriginal) => ({
|
|
34
|
+
...(await importOriginal<typeof import("@dnd-kit/core")>()),
|
|
35
|
+
useSensor: vi.fn(),
|
|
36
|
+
useSensors: vi.fn(),
|
|
37
|
+
}))
|
|
38
|
+
|
|
39
|
+
vi.mock("react-i18next", () => ({
|
|
40
|
+
useTranslation: () => ({
|
|
41
|
+
t: (key: string) => key,
|
|
42
|
+
}),
|
|
43
|
+
}))
|
|
44
|
+
|
|
45
|
+
vi.mock("@medusajs/ui", () => ({
|
|
46
|
+
Button: vi.fn(),
|
|
47
|
+
Checkbox: vi.fn(),
|
|
48
|
+
clx: vi.fn(),
|
|
49
|
+
CommandBar: Object.assign(vi.fn(), {
|
|
50
|
+
Bar: vi.fn(),
|
|
51
|
+
Value: vi.fn(),
|
|
52
|
+
Seperator: vi.fn(),
|
|
53
|
+
Command: vi.fn(),
|
|
54
|
+
}),
|
|
55
|
+
Tooltip: vi.fn(),
|
|
56
|
+
toast: {
|
|
57
|
+
success: vi.fn(),
|
|
58
|
+
error: vi.fn(),
|
|
59
|
+
},
|
|
60
|
+
}))
|
|
61
|
+
|
|
62
|
+
vi.mock("../../../../../components/modals", () => ({
|
|
63
|
+
RouteFocusModal: {
|
|
64
|
+
Form: vi.fn(),
|
|
65
|
+
Header: vi.fn(),
|
|
66
|
+
Body: vi.fn(),
|
|
67
|
+
Footer: vi.fn(),
|
|
68
|
+
Close: vi.fn(),
|
|
69
|
+
},
|
|
70
|
+
useRouteModal: () => ({ handleSuccess: vi.fn() }),
|
|
71
|
+
}))
|
|
72
|
+
|
|
73
|
+
vi.mock("../../../../../components/utilities/keybound-form", () => ({
|
|
74
|
+
KeyboundForm: vi.fn(),
|
|
75
|
+
}))
|
|
76
|
+
|
|
77
|
+
vi.mock("../../../../../hooks/api/products", () => ({
|
|
78
|
+
useUpdateProduct: () => ({
|
|
79
|
+
mutateAsync: mocks.mutateAsync,
|
|
80
|
+
isPending: false,
|
|
81
|
+
}),
|
|
82
|
+
}))
|
|
83
|
+
|
|
84
|
+
vi.mock("../../../../../lib/client", () => ({
|
|
85
|
+
sdk: {
|
|
86
|
+
admin: {
|
|
87
|
+
upload: { create: mocks.uploadCreate },
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
}))
|
|
91
|
+
|
|
92
|
+
vi.mock("../../../common/components/upload-media-form-item", () => ({
|
|
93
|
+
UploadMediaFormItem: vi.fn(),
|
|
94
|
+
}))
|
|
95
|
+
|
|
96
|
+
const product = {
|
|
97
|
+
id: "prod_1",
|
|
98
|
+
thumbnail: "https://example.com/existing.png",
|
|
99
|
+
images: [{ id: "img_1", url: "https://example.com/existing.png" }],
|
|
100
|
+
} as unknown as HttpTypes.AdminProduct
|
|
101
|
+
|
|
102
|
+
const media = [
|
|
103
|
+
{
|
|
104
|
+
id: "img_1",
|
|
105
|
+
url: "https://example.com/existing.png",
|
|
106
|
+
isThumbnail: true,
|
|
107
|
+
file: null,
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
id: "new_media",
|
|
111
|
+
url: "blob:new-media",
|
|
112
|
+
isThumbnail: false,
|
|
113
|
+
file: new Blob(["<svg />"], { type: "image/svg+xml" }),
|
|
114
|
+
},
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
const submit = async () => {
|
|
118
|
+
const element = EditProductMediaForm({ product }) as ReactElement<{
|
|
119
|
+
children: ReactElement<{
|
|
120
|
+
onSubmit: (values: { media: typeof media }) => Promise<void>
|
|
121
|
+
}>
|
|
122
|
+
}>
|
|
123
|
+
|
|
124
|
+
await element.props.children.props.onSubmit({ media })
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
describe("EditProductMediaForm", () => {
|
|
128
|
+
beforeEach(() => {
|
|
129
|
+
vi.clearAllMocks()
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
it("should not update the product and should show the server's error when the upload fails", async () => {
|
|
133
|
+
mocks.uploadCreate.mockRejectedValue(
|
|
134
|
+
new Error("SVG files are not allowed.")
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
await submit()
|
|
138
|
+
|
|
139
|
+
expect(mocks.uploadCreate).toHaveBeenCalledTimes(1)
|
|
140
|
+
expect(mocks.setError).toHaveBeenCalledWith("media", {
|
|
141
|
+
type: "invalid_file",
|
|
142
|
+
message: "SVG files are not allowed.",
|
|
143
|
+
})
|
|
144
|
+
expect(mocks.mutateAsync).not.toHaveBeenCalled()
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it("should update the product with the uploaded file's url when the upload succeeds", async () => {
|
|
148
|
+
mocks.uploadCreate.mockResolvedValue({
|
|
149
|
+
files: [{ id: "file_1", url: "https://example.com/uploaded.png" }],
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
await submit()
|
|
153
|
+
|
|
154
|
+
expect(mocks.setError).not.toHaveBeenCalled()
|
|
155
|
+
expect(mocks.mutateAsync).toHaveBeenCalledTimes(1)
|
|
156
|
+
expect(mocks.mutateAsync.mock.calls[0][0]).toEqual({
|
|
157
|
+
images: [
|
|
158
|
+
{ id: "img_1", url: "https://example.com/existing.png" },
|
|
159
|
+
{ id: "new_media", url: "https://example.com/uploaded.png" },
|
|
160
|
+
],
|
|
161
|
+
thumbnail: "https://example.com/existing.png",
|
|
162
|
+
})
|
|
163
|
+
})
|
|
164
|
+
})
|
|
@@ -109,16 +109,20 @@ export const EditProductMediaForm = ({ product }: ProductMediaViewProps) => {
|
|
|
109
109
|
let uploaded: HttpTypes.AdminFile[] = []
|
|
110
110
|
|
|
111
111
|
if (filesToUpload.length) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
form.setError("media", {
|
|
116
|
-
type: "invalid_file",
|
|
117
|
-
message: t("products.media.failedToUpload"),
|
|
118
|
-
})
|
|
119
|
-
return { files: [] }
|
|
112
|
+
try {
|
|
113
|
+
const { files: uploads } = await sdk.admin.upload.create({
|
|
114
|
+
files: filesToUpload.map((m) => m.file),
|
|
120
115
|
})
|
|
121
|
-
|
|
116
|
+
uploaded = uploads
|
|
117
|
+
} catch (error) {
|
|
118
|
+
form.setError("media", {
|
|
119
|
+
type: "invalid_file",
|
|
120
|
+
message:
|
|
121
|
+
(error instanceof Error && error.message) ||
|
|
122
|
+
t("products.media.failedToUpload"),
|
|
123
|
+
})
|
|
124
|
+
return
|
|
125
|
+
}
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
const withUpdatedUrls = media.map((entry, i) => {
|