@medusajs/dashboard 3.0.0-snapshot-20251214110905 → 3.0.0-snapshot-20251215162333
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/{adjust-inventory-I5VYMAI4.mjs → adjust-inventory-26YXAXQL.mjs} +2 -1
- package/dist/{api-key-management-create-CVRFY4PL.mjs → api-key-management-create-EMP32G2D.mjs} +4 -3
- package/dist/{api-key-management-detail-HRVP6HRC.mjs → api-key-management-detail-NRGL7HHX.mjs} +11 -10
- package/dist/{api-key-management-edit-JMU3WEPX.mjs → api-key-management-edit-IBM3ZXHK.mjs} +4 -3
- package/dist/{api-key-management-list-RGLZMUCB.mjs → api-key-management-list-LJSWRAGE.mjs} +4 -3
- package/dist/{api-key-management-sales-channels-4OU5VGIG.mjs → api-key-management-sales-channels-3GRNDBZ4.mjs} +4 -3
- package/dist/app.css +3 -0
- package/dist/app.js +1085 -835
- package/dist/app.mjs +12 -11
- package/dist/{campaign-detail-BDI3P2SF.mjs → campaign-detail-22Q6XWGL.mjs} +11 -10
- package/dist/{categories-metadata-BARTITD5.mjs → categories-metadata-J7M3XWI7.mjs} +11 -10
- package/dist/{category-create-L2KJCHPO.mjs → category-create-KHJZSC7G.mjs} +3 -2
- package/dist/{category-detail-CUMEBNXU.mjs → category-detail-RRKJPMEG.mjs} +13 -12
- package/dist/{category-edit-U6SLZSAX.mjs → category-edit-CTA2EPDG.mjs} +3 -2
- package/dist/{category-list-W7JW4PWA.mjs → category-list-4HZP4FRE.mjs} +4 -3
- package/dist/{category-organize-LLSVAO3U.mjs → category-organize-SXP33XET.mjs} +3 -2
- package/dist/{category-products-GYXTDDBQ.mjs → category-products-EFZRTCSF.mjs} +12 -11
- package/dist/{chunk-XIVBRONM.mjs → chunk-23GTCEOV.mjs} +1 -1
- package/dist/{chunk-N3FCYZV6.mjs → chunk-2XTBDCGE.mjs} +1 -1
- package/dist/{chunk-DS5IRNJY.mjs → chunk-32FPYJ3S.mjs} +1 -1
- package/dist/{chunk-FPBKWWSI.mjs → chunk-43X7ZR3P.mjs} +1 -1
- package/dist/{chunk-RU4ZS47V.mjs → chunk-4JQR6QNW.mjs} +2 -2
- package/dist/{chunk-Z6NHG5LQ.mjs → chunk-6P4Q4AAP.mjs} +3 -3
- package/dist/{chunk-F5NZDW7L.mjs → chunk-A2WBKOXJ.mjs} +2 -2
- package/dist/{chunk-F63F3FIT.mjs → chunk-A4XYK3MY.mjs} +2 -2
- package/dist/{chunk-NT6C7CHT.mjs → chunk-AWRCV3ME.mjs} +1 -1
- package/dist/{chunk-5X6SKB2P.mjs → chunk-BMS2QLJY.mjs} +1 -1
- package/dist/{chunk-67KHYLIQ.mjs → chunk-DK7IWUMK.mjs} +3 -3
- package/dist/{chunk-FEB3ZGTL.mjs → chunk-DNUVCBN7.mjs} +159 -5
- package/dist/{chunk-N4O5FAUC.mjs → chunk-FYWHE3W5.mjs} +1 -1
- package/dist/{chunk-HKKZJTRO.mjs → chunk-GRZSG4EP.mjs} +89 -34
- package/dist/chunk-HGRIOEAR.mjs +32 -0
- package/dist/{chunk-Y5UO73CH.mjs → chunk-HTCYX4VD.mjs} +1 -1
- package/dist/{chunk-34KFHPN6.mjs → chunk-IAV7IKJ6.mjs} +1 -1
- package/dist/{chunk-3BJLNORD.mjs → chunk-KQ4LC2YV.mjs} +1 -1
- package/dist/{chunk-GC3QXC6D.mjs → chunk-OHY2N2Q4.mjs} +4 -4
- package/dist/{chunk-7AX6R6G6.mjs → chunk-OSHH5GAS.mjs} +13 -1
- package/dist/{chunk-PXZEQZ6Q.mjs → chunk-PHLCT2HA.mjs} +1 -1
- package/dist/{chunk-35LSPN2U.mjs → chunk-QKALAT7P.mjs} +1 -1
- package/dist/{chunk-BBTE6VKD.mjs → chunk-RL5EYTP6.mjs} +1 -1
- package/dist/{chunk-B3AOQW2B.mjs → chunk-U6G4M5LP.mjs} +1 -1
- package/dist/{chunk-HKIF5HVL.mjs → chunk-UJ2TMPV4.mjs} +12 -0
- package/dist/{chunk-NHDFPGQ3.mjs → chunk-UWY5ZV66.mjs} +13 -1
- package/dist/{chunk-AH4DORIW.mjs → chunk-XY7A7GZJ.mjs} +1 -1
- package/dist/{chunk-FQDPOKEK.mjs → chunk-Y2YVTIJI.mjs} +1 -1
- package/dist/{chunk-Q4AXBDFH.mjs → chunk-YTYDWNYA.mjs} +155 -153
- package/dist/{chunk-2HDKZN4Q.mjs → chunk-YYOPBKME.mjs} +3 -3
- package/dist/{chunk-LEJUZW3P.mjs → chunk-Z6BFNHEO.mjs} +12 -0
- package/dist/{chunk-AIZ6W4QI.mjs → chunk-ZMG5B4FG.mjs} +1 -1
- package/dist/{collection-add-products-4WBPS6PY.mjs → collection-add-products-XUMV6XR7.mjs} +12 -11
- package/dist/{collection-create-4JX4YE47.mjs → collection-create-GWKWVT7B.mjs} +3 -2
- package/dist/{collection-detail-HT4SSV32.mjs → collection-detail-ONRBKJLN.mjs} +12 -11
- package/dist/{collection-edit-MXL35GQQ.mjs → collection-edit-EZIO2BR5.mjs} +3 -2
- package/dist/{collection-list-FYONEBDN.mjs → collection-list-XCC4SIPJ.mjs} +13 -12
- package/dist/{collection-metadata-YEZ2TBRX.mjs → collection-metadata-QK7MI3D2.mjs} +11 -10
- package/dist/{customer-detail-MB7CS7OG.mjs → customer-detail-FR6J37ZC.mjs} +12 -11
- package/dist/{customer-group-detail-U5UAP7QS.mjs → customer-group-detail-YSKSNETG.mjs} +11 -10
- package/dist/{customer-group-list-KAS6JSCQ.mjs → customer-group-list-XBCD4FZH.mjs} +11 -10
- package/dist/{customers-add-customer-group-UKLSPYEU.mjs → customers-add-customer-group-Q7FMR2Y5.mjs} +11 -10
- package/dist/{edit-inventory-item-RATTNP2Y.mjs → edit-inventory-item-H7DAZWIT.mjs} +2 -1
- package/dist/{edit-inventory-item-attributes-JHH5GSNL.mjs → edit-inventory-item-attributes-7HTXXPGZ.mjs} +2 -1
- package/dist/{edit-reservation-UZCSNLHY.mjs → edit-reservation-OVTRZHJR.mjs} +3 -2
- package/dist/{edit-rules-VMEHCXYQ.mjs → edit-rules-SMVRTCUP.mjs} +11 -10
- package/dist/en.json +1 -0
- package/dist/{inventory-create-KN72V2KK.mjs → inventory-create-3XONKYMZ.mjs} +12 -11
- package/dist/{inventory-detail-7OHCFAJO.mjs → inventory-detail-6A6GOLB6.mjs} +11 -10
- package/dist/{inventory-list-BQPHK3FV.mjs → inventory-list-2CJLAK3X.mjs} +2 -1
- package/dist/{inventory-metadata-I3IRRMLH.mjs → inventory-metadata-FNEJ3RAT.mjs} +11 -10
- package/dist/{inventory-stock-5IUICNEH.mjs → inventory-stock-S3ZYYCMZ.mjs} +13 -12
- package/dist/{location-detail-3MSUGB4W.mjs → location-detail-N3GUZSY7.mjs} +11 -10
- package/dist/{location-fulfillment-providers-ZVZMLCIC.mjs → location-fulfillment-providers-WM6DT252.mjs} +13 -12
- package/dist/{location-sales-channels-NKNM5TQK.mjs → location-sales-channels-WLVTMU4Z.mjs} +3 -2
- package/dist/{location-service-zone-shipping-option-create-CZWEHKVJ.mjs → location-service-zone-shipping-option-create-MJPH3WKX.mjs} +13 -12
- package/dist/{location-service-zone-shipping-option-pricing-Z5IFOLFJ.mjs → location-service-zone-shipping-option-pricing-6IRNPWJY.mjs} +2 -2
- package/dist/{login-OCYZM7SI.mjs → login-VNOLI5YG.mjs} +11 -10
- package/dist/{manage-locations-MLNMPQ5I.mjs → manage-locations-7HH6R4UP.mjs} +2 -1
- package/dist/{order-allocate-items-VRPPVPP3.mjs → order-allocate-items-HZGGYJ42.mjs} +4 -3
- package/dist/{order-create-claim-O3ZYTAIC.mjs → order-create-claim-GUYTLVPB.mjs} +13 -12
- package/dist/{order-create-edit-HUS7IRS3.mjs → order-create-edit-ODIN6GRW.mjs} +12 -11
- package/dist/{order-create-exchange-TUP4NHHX.mjs → order-create-exchange-ZT5RBRKL.mjs} +13 -12
- package/dist/{order-create-fulfillment-4BGDYHBB.mjs → order-create-fulfillment-OWUVTZXW.mjs} +11 -10
- package/dist/{order-create-refund-FA5ERI7M.mjs → order-create-refund-Q6HQY42R.mjs} +11 -10
- package/dist/{order-create-return-7GPHJ2WU.mjs → order-create-return-E2KILJX2.mjs} +5 -4
- package/dist/{order-create-shipment-27UBYPKT.mjs → order-create-shipment-WAGGEPRW.mjs} +11 -10
- package/dist/{order-detail-2J7KDTKG.mjs → order-detail-HFJONELJ.mjs} +15 -14
- package/dist/{order-edit-billing-address-E7CD5FBQ.mjs → order-edit-billing-address-UM76J4KX.mjs} +11 -10
- package/dist/{order-edit-email-ELRIQYVN.mjs → order-edit-email-CL3KNOCM.mjs} +11 -10
- package/dist/{order-edit-shipping-address-HVNAJUZI.mjs → order-edit-shipping-address-PIESTGVL.mjs} +11 -10
- package/dist/{order-export-TRMFVBFO.mjs → order-export-4MZUPMGD.mjs} +12 -11
- package/dist/{order-list-Y4FET3XV.mjs → order-list-ACSFGIPD.mjs} +6 -5
- package/dist/{order-metadata-THARHEJC.mjs → order-metadata-FHBB7MTG.mjs} +11 -10
- package/dist/{order-receive-return-X5ASB7DL.mjs → order-receive-return-PRVKP6J2.mjs} +12 -11
- package/dist/{order-request-transfer-PKF4ULJY.mjs → order-request-transfer-XSAGRUMT.mjs} +11 -10
- package/dist/{price-list-configuration-SZRY7CXO.mjs → price-list-configuration-IHPSUNZJ.mjs} +3 -2
- package/dist/{price-list-create-TYNSJDDM.mjs → price-list-create-YHXRQSC3.mjs} +14 -13
- package/dist/{price-list-detail-ORYFRNB6.mjs → price-list-detail-FR3FQR3H.mjs} +13 -12
- package/dist/{price-list-edit-I5QNCWJP.mjs → price-list-edit-53UW35L3.mjs} +3 -2
- package/dist/{price-list-list-AZOGEZAS.mjs → price-list-list-YSEM6IAI.mjs} +4 -3
- package/dist/{price-list-prices-add-MWAUNUBF.mjs → price-list-prices-add-GJVI47OY.mjs} +14 -13
- package/dist/{price-list-prices-edit-Z4YJ4YBY.mjs → price-list-prices-edit-E4Q5TQPM.mjs} +5 -4
- package/dist/{product-attributes-5QW6ZEYB.mjs → product-attributes-TKCE2M63.mjs} +12 -11
- package/dist/{product-create-YQ76CEF3.mjs → product-create-OLDZPMLW.mjs} +14 -13
- package/dist/{product-create-option-UMZKRNTC.mjs → product-create-option-7AOXAA4S.mjs} +2 -1
- package/dist/{product-create-variant-IASRY2JX.mjs → product-create-variant-KEBN5OR7.mjs} +12 -11
- package/dist/{product-detail-NVLJQGGK.mjs → product-detail-O6QWJIKR.mjs} +12 -11
- package/dist/{product-edit-DP42G3EU.mjs → product-edit-56XDGDUN.mjs} +12 -11
- package/dist/{product-edit-option-ZMTSLRG5.mjs → product-edit-option-LWJT3CYJ.mjs} +2 -1
- package/dist/{product-export-OK5FCD42.mjs → product-export-WUZYHPS5.mjs} +13 -12
- package/dist/{product-image-variants-edit-VEWNL52X.mjs → product-image-variants-edit-Y363J5NG.mjs} +11 -10
- package/dist/{product-import-LX625CIX.mjs → product-import-V3KQN4TV.mjs} +11 -10
- package/dist/{product-list-TXEPE6NL.mjs → product-list-DNTS7WUN.mjs} +12 -11
- package/dist/{product-media-ULNJ7JJY.mjs → product-media-3VJ7KENL.mjs} +2 -1
- package/dist/{product-metadata-ZKKBE6GG.mjs → product-metadata-GL2MVPDI.mjs} +11 -10
- package/dist/{product-organization-NMA2WJNT.mjs → product-organization-PNKWRNHC.mjs} +13 -12
- package/dist/{product-prices-5WCCQDS6.mjs → product-prices-JOG6IIQ7.mjs} +3 -2
- package/dist/{product-sales-channels-2PN4L7II.mjs → product-sales-channels-ANCFZZ5S.mjs} +3 -2
- package/dist/{product-shipping-profile-45XXB7FM.mjs → product-shipping-profile-ETQFZ7DC.mjs} +2 -1
- package/dist/{product-stock-KUHH6MFA.mjs → product-stock-NYUFMEVG.mjs} +13 -12
- package/dist/{product-tag-create-7EVRE5BL.mjs → product-tag-create-PQMDDKWH.mjs} +11 -10
- package/dist/{product-tag-detail-WULO55NT.mjs → product-tag-detail-EHBB3WUB.mjs} +14 -13
- package/dist/{product-tag-edit-J4ODRLXN.mjs → product-tag-edit-K3BBQLJR.mjs} +11 -10
- package/dist/{product-tag-list-V4CCQTL6.mjs → product-tag-list-LSW5FFVN.mjs} +14 -13
- package/dist/{product-tag-metadata-KHDYQMSG.mjs → product-tag-metadata-MJH5LH7E.mjs} +11 -10
- package/dist/{product-type-create-KHSNCQCV.mjs → product-type-create-DRFXTL5O.mjs} +2 -1
- package/dist/{product-type-detail-F35MUSLD.mjs → product-type-detail-3VB6AWUW.mjs} +13 -12
- package/dist/{product-type-edit-3LRBWZ3S.mjs → product-type-edit-SRHCZDK7.mjs} +2 -1
- package/dist/{product-type-list-K2GULUPF.mjs → product-type-list-FD3TGPNP.mjs} +3 -2
- package/dist/{product-type-metadata-CGXFFEJO.mjs → product-type-metadata-CDJDFFGQ.mjs} +11 -10
- package/dist/{product-variant-detail-NT2MB3Z4.mjs → product-variant-detail-43T33AQP.mjs} +11 -10
- package/dist/{product-variant-edit-KZ6D5CSA.mjs → product-variant-edit-DEZEY2H2.mjs} +11 -10
- package/dist/{product-variant-manage-inventory-items-OGM64KYP.mjs → product-variant-manage-inventory-items-Y2VEOHP7.mjs} +2 -1
- package/dist/{product-variant-media-C3KCFODU.mjs → product-variant-media-2WLVNGI4.mjs} +2 -1
- package/dist/{product-variant-metadata-I2PN64TH.mjs → product-variant-metadata-VTZDNWUT.mjs} +11 -10
- package/dist/{promotion-create-4KVSXYAI.mjs → promotion-create-HWFNUQXG.mjs} +11 -10
- package/dist/{promotion-detail-NGNVELME.mjs → promotion-detail-VJB55PJK.mjs} +11 -10
- package/dist/{refund-reason-create-CTAPBK3X.mjs → refund-reason-create-YHCDEHGQ.mjs} +11 -10
- package/dist/{refund-reason-edit-B6HRNXGE.mjs → refund-reason-edit-CZ5QZ2SZ.mjs} +11 -10
- package/dist/{refund-reason-list-7OUHUORB.mjs → refund-reason-list-URYYYEK6.mjs} +11 -10
- package/dist/{region-metadata-GRG3QSJY.mjs → region-metadata-H6XXUQ4S.mjs} +11 -10
- package/dist/{reservation-create-C6HTEF3R.mjs → reservation-create-ZCIYM6JI.mjs} +3 -2
- package/dist/{reservation-detail-KAI7N5UP.mjs → reservation-detail-LZAQL4XA.mjs} +11 -10
- package/dist/{reservation-list-SOJRN5RI.mjs → reservation-list-2DN3YHIJ.mjs} +3 -2
- package/dist/{reservation-metadata-TWV7KLOB.mjs → reservation-metadata-5HZSDDOK.mjs} +11 -10
- package/dist/{sales-channel-add-products-CBECZU46.mjs → sales-channel-add-products-VH5T3GDA.mjs} +12 -11
- package/dist/{sales-channel-create-4XLJDVJO.mjs → sales-channel-create-MI7HHZYE.mjs} +3 -2
- package/dist/{sales-channel-detail-NQSBPPIE.mjs → sales-channel-detail-I2ZHVXMG.mjs} +12 -11
- package/dist/{sales-channel-edit-UZGSXD5X.mjs → sales-channel-edit-VSHOIR37.mjs} +3 -2
- package/dist/{sales-channel-list-UYN2OCBR.mjs → sales-channel-list-3FV4S2NN.mjs} +11 -10
- package/dist/{sales-channel-metadata-4XWXYN2E.mjs → sales-channel-metadata-M364R4RJ.mjs} +11 -10
- package/dist/{shipping-option-type-create-U7PIKVMV.mjs → shipping-option-type-create-C5WUWON7.mjs} +11 -10
- package/dist/{shipping-option-type-detail-QNZLQGI6.mjs → shipping-option-type-detail-PENS2K73.mjs} +12 -11
- package/dist/{shipping-option-type-edit-BP6HLZ7B.mjs → shipping-option-type-edit-CIU5EHRP.mjs} +11 -10
- package/dist/{shipping-option-type-list-L274RM6A.mjs → shipping-option-type-list-ZMZMXFME.mjs} +12 -11
- package/dist/{shipping-profile-metadata-BZKPLXHO.mjs → shipping-profile-metadata-75G2NNMA.mjs} +11 -10
- package/dist/{store-add-locales-EXR3NLOM.mjs → store-add-locales-IZOZP5C6.mjs} +12 -18
- package/dist/{store-detail-T4YY5NHG.mjs → store-detail-4IBAEVSD.mjs} +16 -28
- package/dist/{store-edit-AB5CDUTK.mjs → store-edit-5ZS562ZO.mjs} +1 -42
- package/dist/{store-metadata-FN3WZLXA.mjs → store-metadata-CYXTVJUE.mjs} +11 -10
- package/dist/{tax-region-create-PWXTFE3Q.mjs → tax-region-create-DWGL4EUT.mjs} +11 -10
- package/dist/{tax-region-detail-GJW63AMV.mjs → tax-region-detail-O2T7BI3V.mjs} +16 -15
- package/dist/{tax-region-edit-WOUO7TPQ.mjs → tax-region-edit-EEVEEU2Q.mjs} +11 -10
- package/dist/{tax-region-province-detail-FCHPIRXW.mjs → tax-region-province-detail-2W7RXAM5.mjs} +16 -15
- package/dist/{tax-region-tax-override-create-ZLWXRNLN.mjs → tax-region-tax-override-create-7IM4ZVPH.mjs} +14 -13
- package/dist/{tax-region-tax-override-edit-ZM2JUFNJ.mjs → tax-region-tax-override-edit-3ZT5IZYR.mjs} +15 -14
- package/dist/{translation-list-Y2GWTRGW.mjs → translation-list-AFK5MGSH.mjs} +68 -79
- package/dist/{translations-edit-PM4PSMRF.mjs → translations-edit-EN47PWTO.mjs} +146 -81
- package/dist/{user-detail-KEDJ7N3Q.mjs → user-detail-BJUXLZZQ.mjs} +2 -1
- package/dist/{user-metadata-LNADHFTW.mjs → user-metadata-2WPJOEJA.mjs} +11 -10
- package/dist/{workflow-execution-detail-POTSURJX.mjs → workflow-execution-detail-H2AKEZJX.mjs} +11 -10
- package/package.json +9 -9
- package/src/components/data-grid/components/data-grid-root.tsx +184 -5
- package/src/components/data-grid/data-grid.tsx +12 -1
- package/src/components/data-grid/helpers/create-data-grid-column-helper.ts +18 -0
- package/src/components/data-grid/hooks/use-data-grid-cell.tsx +1 -1
- package/src/hooks/api/categories.tsx +32 -0
- package/src/hooks/api/collections.tsx +31 -0
- package/src/hooks/api/product-types.tsx +32 -0
- package/src/hooks/api/product-variants.tsx +40 -2
- package/src/hooks/api/products.tsx +29 -0
- package/src/hooks/api/tags.tsx +32 -0
- package/src/hooks/api/translations.tsx +114 -62
- package/src/hooks/use-infinite-list.tsx +92 -0
- package/src/i18n/translations/$schema.json +4 -0
- package/src/i18n/translations/en.json +1 -0
- package/src/i18n/translations/es.json +1 -0
- package/src/routes/store/store-add-locales/components/add-locales-form/add-locales-form.tsx +0 -9
- package/src/routes/store/store-detail/components/store-general-section/store-general-section.tsx +0 -24
- package/src/routes/store/store-detail/components/store-locale-section/store-locale-section.tsx +1 -9
- package/src/routes/store/store-edit/components/edit-store-form/edit-store-form.tsx +1 -45
- package/src/routes/translations/translation-list/components/active-locales-section/active-locales-section.tsx +2 -2
- package/src/routes/translations/translation-list/components/translation-list-section/translation-list-section.tsx +1 -8
- package/src/routes/translations/translation-list/components/translations-completion-section/translations-completion-section.tsx +10 -4
- package/src/routes/translations/translation-list/translation-list.tsx +66 -68
- package/src/routes/translations/translations-edit/components/translations-edit-form/translations-edit-form.tsx +131 -65
- package/src/routes/translations/translations-edit/translations-edit.tsx +36 -12
- package/src/routes/translations/translations-edit/utils/index.ts +0 -1
- package/src/routes/translations/translations-edit/utils/reference-label-map.ts +0 -10
|
@@ -1,16 +1,22 @@
|
|
|
1
|
+
import { AdminTranslationEntityStatistics } from "@medusajs/types"
|
|
1
2
|
import { Container, Heading, Text } from "@medusajs/ui"
|
|
2
3
|
import { useTranslation } from "react-i18next"
|
|
3
4
|
|
|
4
5
|
type TranslationsCompletionSectionProps = {
|
|
5
|
-
|
|
6
|
-
totalCount?: number
|
|
6
|
+
statistics: Record<string, AdminTranslationEntityStatistics>
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export const TranslationsCompletionSection = ({
|
|
10
|
-
|
|
11
|
-
totalCount = 0,
|
|
10
|
+
statistics,
|
|
12
11
|
}: TranslationsCompletionSectionProps) => {
|
|
13
12
|
const { t } = useTranslation()
|
|
13
|
+
const { translatedCount, totalCount } = Object.values(statistics).reduce(
|
|
14
|
+
(acc, curr) => ({
|
|
15
|
+
translatedCount: acc.translatedCount + curr.translated,
|
|
16
|
+
totalCount: acc.totalCount + curr.expected,
|
|
17
|
+
}),
|
|
18
|
+
{ totalCount: 0, translatedCount: 0 }
|
|
19
|
+
)
|
|
14
20
|
|
|
15
21
|
const percentage = totalCount > 0 ? (translatedCount / totalCount) * 100 : 0
|
|
16
22
|
const remaining = Math.max(0, totalCount - translatedCount)
|
|
@@ -2,96 +2,92 @@ import { Container, Heading, Text } from "@medusajs/ui"
|
|
|
2
2
|
import { TwoColumnPage } from "../../../components/layout/pages"
|
|
3
3
|
import { useTranslation } from "react-i18next"
|
|
4
4
|
import { Buildings } from "@medusajs/icons"
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
useStore,
|
|
7
|
+
useTranslationSettings,
|
|
8
|
+
useTranslationStatistics,
|
|
9
|
+
} from "../../../hooks/api"
|
|
6
10
|
import { ActiveLocalesSection } from "./components/active-locales-section/active-locales-section"
|
|
7
11
|
import { TranslationListSection } from "./components/translation-list-section/translation-list-section"
|
|
8
12
|
import { TranslationsCompletionSection } from "./components/translations-completion-section/translations-completion-section"
|
|
9
13
|
import { TwoColumnPageSkeleton } from "../../../components/common/skeleton"
|
|
14
|
+
import { useMemo } from "react"
|
|
10
15
|
|
|
11
16
|
export type TranslatableEntity = {
|
|
12
|
-
icon: React.ReactNode
|
|
13
17
|
label: string
|
|
14
18
|
reference: string
|
|
19
|
+
translatableFields: string[]
|
|
15
20
|
translatedCount?: number
|
|
16
21
|
totalCount?: number
|
|
17
22
|
}
|
|
18
23
|
|
|
19
|
-
const TRANSLATABLE_ENTITIES: TranslatableEntity[] = [
|
|
20
|
-
{
|
|
21
|
-
icon: <Buildings />,
|
|
22
|
-
label: "Product",
|
|
23
|
-
reference: "product",
|
|
24
|
-
translatedCount: 4,
|
|
25
|
-
totalCount: 96,
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
icon: <Buildings />,
|
|
29
|
-
label: "Product Variants",
|
|
30
|
-
reference: "product_variant",
|
|
31
|
-
translatedCount: 4,
|
|
32
|
-
totalCount: 200000,
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
icon: <Buildings />,
|
|
36
|
-
label: "Product Categories",
|
|
37
|
-
reference: "product_category",
|
|
38
|
-
translatedCount: 96,
|
|
39
|
-
totalCount: 96,
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
icon: <Buildings />,
|
|
43
|
-
label: "Product Collections",
|
|
44
|
-
reference: "product_collection",
|
|
45
|
-
translatedCount: 4,
|
|
46
|
-
totalCount: 96,
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
icon: <Buildings />,
|
|
50
|
-
label: "Product Types",
|
|
51
|
-
reference: "product_type",
|
|
52
|
-
translatedCount: 4,
|
|
53
|
-
totalCount: 96,
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
icon: <Buildings />,
|
|
57
|
-
label: "Product Tags",
|
|
58
|
-
reference: "product_tag",
|
|
59
|
-
translatedCount: 96,
|
|
60
|
-
totalCount: 96,
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
icon: <Buildings />,
|
|
64
|
-
label: "Product Options",
|
|
65
|
-
reference: "product_option",
|
|
66
|
-
translatedCount: 96,
|
|
67
|
-
totalCount: 96,
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
icon: <Buildings />,
|
|
71
|
-
label: "Product Option Values",
|
|
72
|
-
reference: "product_option_value",
|
|
73
|
-
translatedCount: 96,
|
|
74
|
-
totalCount: 96,
|
|
75
|
-
},
|
|
76
|
-
]
|
|
77
|
-
|
|
78
24
|
export const TranslationList = () => {
|
|
79
25
|
const { t } = useTranslation()
|
|
80
26
|
|
|
81
27
|
const { store, isPending, isError, error } = useStore()
|
|
28
|
+
const {
|
|
29
|
+
translatable_fields,
|
|
30
|
+
isPending: isTranslationSettingsPending,
|
|
31
|
+
isError: isTranslationSettingsError,
|
|
32
|
+
error: translationSettingsError,
|
|
33
|
+
} = useTranslationSettings()
|
|
34
|
+
const {
|
|
35
|
+
statistics,
|
|
36
|
+
isPending: isTranslationStatisticsPending,
|
|
37
|
+
isError: isTranslationStatisticsError,
|
|
38
|
+
error: translationStatisticsError,
|
|
39
|
+
} = useTranslationStatistics(
|
|
40
|
+
{
|
|
41
|
+
locales:
|
|
42
|
+
store?.supported_locales?.map(
|
|
43
|
+
(suportedLocale) => suportedLocale.locale_code
|
|
44
|
+
) ?? [],
|
|
45
|
+
entity_types: Object.keys(translatable_fields ?? {}),
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
enabled: !!translatable_fields && !!store,
|
|
49
|
+
}
|
|
50
|
+
)
|
|
82
51
|
|
|
83
|
-
if (isError) {
|
|
84
|
-
throw error
|
|
52
|
+
if (isError || isTranslationSettingsError || isTranslationStatisticsError) {
|
|
53
|
+
throw error || translationSettingsError || translationStatisticsError
|
|
85
54
|
}
|
|
86
55
|
|
|
87
|
-
const
|
|
56
|
+
const hasLocales = (store?.supported_locales ?? []).length > 0
|
|
57
|
+
|
|
58
|
+
const translatableEntities: TranslatableEntity[] = useMemo(() => {
|
|
59
|
+
if (!translatable_fields || !statistics) {
|
|
60
|
+
return []
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return Object.entries(translatable_fields).map(([entity, fields]) => {
|
|
64
|
+
const entityStatistics = statistics[entity]
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
label: entity
|
|
68
|
+
.split("_")
|
|
69
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
70
|
+
.join(" "),
|
|
71
|
+
reference: entity,
|
|
72
|
+
translatableFields: fields,
|
|
73
|
+
translatedCount: entityStatistics.translated,
|
|
74
|
+
totalCount: entityStatistics.expected,
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
}, [translatable_fields, statistics])
|
|
78
|
+
|
|
79
|
+
const isReady =
|
|
80
|
+
!!store &&
|
|
81
|
+
!isPending &&
|
|
82
|
+
!isTranslationSettingsPending &&
|
|
83
|
+
!isTranslationStatisticsPending &&
|
|
84
|
+
!!translatable_fields &&
|
|
85
|
+
!!statistics
|
|
88
86
|
|
|
89
87
|
if (!isReady) {
|
|
90
88
|
return <TwoColumnPageSkeleton sidebarSections={2} />
|
|
91
89
|
}
|
|
92
90
|
|
|
93
|
-
const hasLocales = (store?.supported_locales ?? []).length > 0
|
|
94
|
-
|
|
95
91
|
return (
|
|
96
92
|
<TwoColumnPage
|
|
97
93
|
widgets={{
|
|
@@ -109,7 +105,7 @@ export const TranslationList = () => {
|
|
|
109
105
|
</Text>
|
|
110
106
|
</Container>
|
|
111
107
|
<TranslationListSection
|
|
112
|
-
entities={
|
|
108
|
+
entities={translatableEntities}
|
|
113
109
|
hasLocales={hasLocales}
|
|
114
110
|
/>
|
|
115
111
|
</TwoColumnPage.Main>
|
|
@@ -121,7 +117,9 @@ export const TranslationList = () => {
|
|
|
121
117
|
) ?? []
|
|
122
118
|
}
|
|
123
119
|
></ActiveLocalesSection>
|
|
124
|
-
|
|
120
|
+
{statistics && (
|
|
121
|
+
<TranslationsCompletionSection statistics={statistics} />
|
|
122
|
+
)}
|
|
125
123
|
</TwoColumnPage.Sidebar>
|
|
126
124
|
</TwoColumnPage>
|
|
127
125
|
)
|
|
@@ -18,10 +18,9 @@ import {
|
|
|
18
18
|
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
|
19
19
|
import { useBatchTranslations } from "../../../../../hooks/api/translations"
|
|
20
20
|
import { useDocumentDirection } from "../../../../../hooks/use-document-direction"
|
|
21
|
-
import { REFERENCE_LABEL_MAP } from "../../utils"
|
|
22
21
|
|
|
23
22
|
/**
|
|
24
|
-
* Schema for a single locale translation
|
|
23
|
+
* Schema for a single locale translation.
|
|
25
24
|
*/
|
|
26
25
|
const LocaleTranslationSchema = z.object({
|
|
27
26
|
id: z.string().nullish(),
|
|
@@ -50,30 +49,28 @@ export type TranslationsFormSchema = z.infer<typeof TranslationsFormSchema>
|
|
|
50
49
|
|
|
51
50
|
/**
|
|
52
51
|
* Row types for the DataGrid.
|
|
53
|
-
* Parent rows are entities, subrows are
|
|
52
|
+
* Parent rows are entities, subrows are translatable fields.
|
|
54
53
|
*/
|
|
55
|
-
export type TranslationRow = EntityRow |
|
|
54
|
+
export type TranslationRow = EntityRow | FieldRow
|
|
56
55
|
|
|
57
56
|
export type EntityRow = {
|
|
58
57
|
_type: "entity"
|
|
59
58
|
reference_id: string
|
|
60
|
-
subRows:
|
|
59
|
+
subRows: FieldRow[]
|
|
61
60
|
}
|
|
62
61
|
|
|
63
|
-
export type
|
|
64
|
-
_type: "
|
|
62
|
+
export type FieldRow = {
|
|
63
|
+
_type: "field"
|
|
65
64
|
reference_id: string
|
|
66
|
-
|
|
67
|
-
locale_name: string
|
|
68
|
-
id?: string
|
|
65
|
+
field_name: string
|
|
69
66
|
}
|
|
70
67
|
|
|
71
68
|
export function isEntityRow(row: TranslationRow): row is EntityRow {
|
|
72
69
|
return row._type === "entity"
|
|
73
70
|
}
|
|
74
71
|
|
|
75
|
-
export function
|
|
76
|
-
return row._type === "
|
|
72
|
+
export function isFieldRow(row: TranslationRow): row is FieldRow {
|
|
73
|
+
return row._type === "field"
|
|
77
74
|
}
|
|
78
75
|
|
|
79
76
|
function initTranslationsFormState(
|
|
@@ -95,14 +92,10 @@ function initTranslationsFormState(
|
|
|
95
92
|
for (const locale of availableLocales) {
|
|
96
93
|
const key = `${reference.id}:${locale.locale_code}`
|
|
97
94
|
const existing = existingMap.get(key)
|
|
98
|
-
const isDefaultLocale = locale.is_default
|
|
99
95
|
|
|
100
96
|
const fields: Record<string, string> = {}
|
|
101
97
|
for (const fieldName of translatableFields) {
|
|
102
|
-
const fieldValue =
|
|
103
|
-
? (existing?.translations?.[fieldName] as string) ??
|
|
104
|
-
reference[fieldName]
|
|
105
|
-
: (existing?.translations?.[fieldName] as string) ?? ""
|
|
98
|
+
const fieldValue = (existing?.translations?.[fieldName] as string) ?? ""
|
|
106
99
|
fields[fieldName] = fieldValue
|
|
107
100
|
}
|
|
108
101
|
|
|
@@ -123,29 +116,16 @@ function initTranslationsFormState(
|
|
|
123
116
|
|
|
124
117
|
function buildTranslationRows(
|
|
125
118
|
references: { id: string; [key: string]: string }[],
|
|
126
|
-
|
|
127
|
-
translations: HttpTypes.AdminTranslation[]
|
|
119
|
+
translatableFields: string[]
|
|
128
120
|
): TranslationRow[] {
|
|
129
|
-
// Index existing translations by reference_id:locale_code
|
|
130
|
-
const existingMap = new Map<string, HttpTypes.AdminTranslation>()
|
|
131
|
-
for (const t of translations) {
|
|
132
|
-
existingMap.set(`${t.reference_id}:${t.locale_code}`, t)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
121
|
return references.map((reference) => ({
|
|
136
122
|
_type: "entity" as const,
|
|
137
123
|
reference_id: reference.id,
|
|
138
|
-
subRows:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
reference_id: reference.id,
|
|
144
|
-
locale_code: locale.locale_code,
|
|
145
|
-
locale_name: locale.locale.name,
|
|
146
|
-
id: existing?.id,
|
|
147
|
-
}
|
|
148
|
-
}),
|
|
124
|
+
subRows: translatableFields.map((fieldName) => ({
|
|
125
|
+
_type: "field" as const,
|
|
126
|
+
reference_id: reference.id,
|
|
127
|
+
field_name: fieldName,
|
|
128
|
+
})),
|
|
149
129
|
}))
|
|
150
130
|
}
|
|
151
131
|
|
|
@@ -209,10 +189,14 @@ const columnHelper = createDataGridHelper<
|
|
|
209
189
|
>()
|
|
210
190
|
|
|
211
191
|
function useTranslationsGridColumns({
|
|
192
|
+
entities,
|
|
212
193
|
translatableFields,
|
|
194
|
+
availableLocales,
|
|
213
195
|
modalFields = [],
|
|
214
196
|
}: {
|
|
197
|
+
entities: { id: string; [key: string]: string }[]
|
|
215
198
|
translatableFields: string[]
|
|
199
|
+
availableLocales: AdminStoreLocale[]
|
|
216
200
|
modalFields?: string[]
|
|
217
201
|
}) {
|
|
218
202
|
const { t } = useTranslation()
|
|
@@ -220,8 +204,9 @@ function useTranslationsGridColumns({
|
|
|
220
204
|
const columns: ColumnDef<TranslationRow>[] = useMemo(() => {
|
|
221
205
|
return [
|
|
222
206
|
columnHelper.column({
|
|
223
|
-
id: "
|
|
224
|
-
|
|
207
|
+
id: "field",
|
|
208
|
+
name: "field",
|
|
209
|
+
header: undefined,
|
|
225
210
|
cell: (context) => {
|
|
226
211
|
const row = context.row.original
|
|
227
212
|
|
|
@@ -234,35 +219,67 @@ function useTranslationsGridColumns({
|
|
|
234
219
|
return (
|
|
235
220
|
<DataGrid.ReadonlyCell context={context} color="normal">
|
|
236
221
|
<div className="flex h-full w-full items-center gap-x-2 overflow-hidden">
|
|
237
|
-
<span className="truncate">
|
|
222
|
+
<span className="truncate">
|
|
223
|
+
{t(`fields.${row.field_name}`, {
|
|
224
|
+
defaultValue: row.field_name,
|
|
225
|
+
})}
|
|
226
|
+
</span>
|
|
238
227
|
</div>
|
|
239
228
|
</DataGrid.ReadonlyCell>
|
|
240
229
|
)
|
|
241
230
|
},
|
|
242
231
|
disableHiding: true,
|
|
243
232
|
}),
|
|
244
|
-
|
|
245
|
-
|
|
233
|
+
columnHelper.column({
|
|
234
|
+
id: "original",
|
|
235
|
+
name: "original",
|
|
236
|
+
header: t("general.original"),
|
|
237
|
+
cell: (context) => {
|
|
238
|
+
const row = context.row.original
|
|
239
|
+
|
|
240
|
+
if (isEntityRow(row)) {
|
|
241
|
+
return (
|
|
242
|
+
<DataGrid.ReadonlyCell context={context}></DataGrid.ReadonlyCell>
|
|
243
|
+
)
|
|
244
|
+
}
|
|
246
245
|
|
|
246
|
+
const entity = entities.find(
|
|
247
|
+
(entity) => entity.id === row.reference_id
|
|
248
|
+
)
|
|
249
|
+
if (!entity) {
|
|
250
|
+
return null
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return (
|
|
254
|
+
<DataGrid.ReadonlyCell context={context}>
|
|
255
|
+
{entity[row.field_name]}
|
|
256
|
+
</DataGrid.ReadonlyCell>
|
|
257
|
+
)
|
|
258
|
+
},
|
|
259
|
+
}),
|
|
260
|
+
...availableLocales.map((locale) => {
|
|
247
261
|
return columnHelper.column({
|
|
248
|
-
id:
|
|
249
|
-
|
|
262
|
+
id: locale.locale_code,
|
|
263
|
+
name: locale.locale.name,
|
|
264
|
+
header: () => locale.locale.name,
|
|
250
265
|
cell: (context) => {
|
|
251
266
|
const row = context.row.original
|
|
252
267
|
|
|
253
268
|
if (isEntityRow(row)) {
|
|
254
269
|
return (
|
|
255
|
-
<DataGrid.ReadonlyCell
|
|
256
|
-
|
|
257
|
-
|
|
270
|
+
<DataGrid.ReadonlyCell
|
|
271
|
+
context={context}
|
|
272
|
+
></DataGrid.ReadonlyCell>
|
|
258
273
|
)
|
|
259
274
|
}
|
|
260
275
|
|
|
276
|
+
const useModal = modalFields.includes(row.field_name)
|
|
277
|
+
|
|
261
278
|
if (useModal) {
|
|
262
279
|
return (
|
|
263
280
|
<DataGrid.ExpandableTextCell
|
|
264
281
|
context={context}
|
|
265
|
-
fieldLabel={
|
|
282
|
+
fieldLabel={row.field_name}
|
|
266
283
|
/>
|
|
267
284
|
)
|
|
268
285
|
}
|
|
@@ -276,13 +293,13 @@ function useTranslationsGridColumns({
|
|
|
276
293
|
return null
|
|
277
294
|
}
|
|
278
295
|
|
|
279
|
-
return `entities.${row.reference_id}.locales.${
|
|
296
|
+
return `entities.${row.reference_id}.locales.${locale.locale_code}.fields.${row.field_name}`
|
|
280
297
|
},
|
|
281
298
|
type: "text",
|
|
282
299
|
})
|
|
283
300
|
}),
|
|
284
301
|
]
|
|
285
|
-
}, [t, translatableFields, modalFields])
|
|
302
|
+
}, [t, translatableFields, availableLocales, modalFields])
|
|
286
303
|
|
|
287
304
|
return columns
|
|
288
305
|
}
|
|
@@ -294,6 +311,10 @@ type TranslationsEditFormProps = {
|
|
|
294
311
|
availableLocales: AdminStoreLocale[]
|
|
295
312
|
translatableFields: string[]
|
|
296
313
|
modalFields?: string[]
|
|
314
|
+
fetchNextPage: () => void
|
|
315
|
+
hasNextPage: boolean
|
|
316
|
+
isFetchingNextPage: boolean
|
|
317
|
+
referenceCount: number
|
|
297
318
|
}
|
|
298
319
|
|
|
299
320
|
export const TranslationsEditForm = ({
|
|
@@ -303,12 +324,20 @@ export const TranslationsEditForm = ({
|
|
|
303
324
|
availableLocales,
|
|
304
325
|
translatableFields,
|
|
305
326
|
modalFields = [],
|
|
327
|
+
fetchNextPage,
|
|
328
|
+
hasNextPage,
|
|
329
|
+
isFetchingNextPage,
|
|
330
|
+
referenceCount,
|
|
306
331
|
}: TranslationsEditFormProps) => {
|
|
307
332
|
const { t } = useTranslation()
|
|
308
333
|
const { handleSuccess, setCloseOnEscape } = useRouteModal()
|
|
309
334
|
const direction = useDocumentDirection()
|
|
310
335
|
|
|
311
336
|
const entities = useMemo(() => references, [references])
|
|
337
|
+
const totalCount = useMemo(
|
|
338
|
+
() => referenceCount * (translatableFields.length + 1),
|
|
339
|
+
[referenceCount, translatableFields]
|
|
340
|
+
)
|
|
312
341
|
|
|
313
342
|
const initialState = useRef(
|
|
314
343
|
initTranslationsFormState(
|
|
@@ -325,8 +354,8 @@ export const TranslationsEditForm = ({
|
|
|
325
354
|
})
|
|
326
355
|
|
|
327
356
|
const rows = useMemo(
|
|
328
|
-
() => buildTranslationRows(entities,
|
|
329
|
-
[entities,
|
|
357
|
+
() => buildTranslationRows(entities, translatableFields),
|
|
358
|
+
[entities, translatableFields]
|
|
330
359
|
)
|
|
331
360
|
|
|
332
361
|
const { mutateAsync, isPending } = useBatchTranslations(entityType)
|
|
@@ -349,23 +378,53 @@ export const TranslationsEditForm = ({
|
|
|
349
378
|
return
|
|
350
379
|
}
|
|
351
380
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
364
|
-
|
|
381
|
+
const BATCH_SIZE = 150
|
|
382
|
+
const totalItems =
|
|
383
|
+
payload.create.length + payload.update.length + payload.delete.length
|
|
384
|
+
const batchCount = Math.ceil(totalItems / BATCH_SIZE)
|
|
385
|
+
|
|
386
|
+
for (let i = 0; i < batchCount; i++) {
|
|
387
|
+
let currentBatchAvailable = BATCH_SIZE
|
|
388
|
+
const currentBatch: HttpTypes.AdminBatchTranslations = {
|
|
389
|
+
create: [],
|
|
390
|
+
update: [],
|
|
391
|
+
delete: [],
|
|
392
|
+
}
|
|
393
|
+
if (payload.create.length > 0) {
|
|
394
|
+
currentBatch.create = payload.create.splice(0, currentBatchAvailable)
|
|
395
|
+
currentBatchAvailable -= currentBatch.create.length
|
|
396
|
+
}
|
|
397
|
+
if (payload.update.length > 0) {
|
|
398
|
+
currentBatch.update = payload.update.splice(0, currentBatchAvailable)
|
|
399
|
+
currentBatchAvailable -= currentBatch.update.length
|
|
400
|
+
}
|
|
401
|
+
if (payload.delete.length > 0) {
|
|
402
|
+
currentBatch.delete = payload.delete.splice(0, currentBatchAvailable)
|
|
403
|
+
currentBatchAvailable -= currentBatch.delete.length
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
await mutateAsync(currentBatch, {
|
|
407
|
+
onSuccess: () => {
|
|
408
|
+
if (i === batchCount - 1) {
|
|
409
|
+
toast.success(
|
|
410
|
+
t("translations.edit.successToast", {
|
|
411
|
+
defaultValue: "Translations updated successfully",
|
|
412
|
+
})
|
|
413
|
+
)
|
|
414
|
+
handleSuccess()
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
onError: (error) => {
|
|
418
|
+
toast.error(error.message)
|
|
419
|
+
},
|
|
420
|
+
})
|
|
421
|
+
}
|
|
365
422
|
})
|
|
366
423
|
|
|
367
424
|
const columns = useTranslationsGridColumns({
|
|
425
|
+
entities,
|
|
368
426
|
translatableFields,
|
|
427
|
+
availableLocales,
|
|
369
428
|
modalFields,
|
|
370
429
|
})
|
|
371
430
|
|
|
@@ -381,7 +440,10 @@ export const TranslationsEditForm = ({
|
|
|
381
440
|
<div className="-my-2 w-full border-l">
|
|
382
441
|
<ProgressTabs.List className="justify-start-start flex w-full items-center">
|
|
383
442
|
<ProgressTabs.Trigger value={entityType}>
|
|
384
|
-
{
|
|
443
|
+
{entityType
|
|
444
|
+
.split("_")
|
|
445
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
446
|
+
.join(" ")}
|
|
385
447
|
</ProgressTabs.Trigger>
|
|
386
448
|
</ProgressTabs.List>
|
|
387
449
|
</div>
|
|
@@ -401,6 +463,10 @@ export const TranslationsEditForm = ({
|
|
|
401
463
|
}}
|
|
402
464
|
state={form}
|
|
403
465
|
onEditingChange={(editing) => setCloseOnEscape(!editing)}
|
|
466
|
+
totalRowCount={totalCount}
|
|
467
|
+
onFetchMore={fetchNextPage}
|
|
468
|
+
isFetchingMore={isFetchingNextPage}
|
|
469
|
+
hasNextPage={hasNextPage}
|
|
404
470
|
/>
|
|
405
471
|
</ProgressTabs.Content>
|
|
406
472
|
</RouteFocusModal.Body>
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { useNavigate, useSearchParams } from "react-router-dom"
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
useReferenceTranslations,
|
|
4
|
+
useStore,
|
|
5
|
+
useTranslationSettings,
|
|
6
|
+
} from "../../../hooks/api"
|
|
3
7
|
import { TranslationsEditForm } from "./components/translations-edit-form"
|
|
4
8
|
import { useEffect } from "react"
|
|
5
9
|
import { RouteFocusModal } from "../../../components/modals"
|
|
6
10
|
import { useFeatureFlag } from "../../../providers/feature-flag-provider"
|
|
11
|
+
import { keepPreviousData } from "@tanstack/react-query"
|
|
7
12
|
|
|
8
13
|
export const TranslationsEdit = () => {
|
|
9
14
|
const isTranslationsEnabled = useFeatureFlag("translation")
|
|
@@ -19,17 +24,32 @@ export const TranslationsEdit = () => {
|
|
|
19
24
|
}
|
|
20
25
|
}, [reference, navigate, isTranslationsEnabled])
|
|
21
26
|
|
|
27
|
+
const {
|
|
28
|
+
translatable_fields,
|
|
29
|
+
isPending: isTranslationSettingsPending,
|
|
30
|
+
isError: isTranslationSettingsError,
|
|
31
|
+
error: translationSettingsError,
|
|
32
|
+
} = useTranslationSettings({ entity_type: reference! })
|
|
33
|
+
|
|
22
34
|
const {
|
|
23
35
|
translations,
|
|
24
36
|
references,
|
|
25
|
-
|
|
37
|
+
fetchNextPage,
|
|
38
|
+
count,
|
|
39
|
+
isFetchingNextPage,
|
|
40
|
+
hasNextPage,
|
|
26
41
|
isPending,
|
|
27
42
|
isError,
|
|
28
43
|
error,
|
|
29
|
-
} = useReferenceTranslations(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
44
|
+
} = useReferenceTranslations(
|
|
45
|
+
reference!,
|
|
46
|
+
translatable_fields?.[reference!] ?? [],
|
|
47
|
+
referenceIdParam,
|
|
48
|
+
{
|
|
49
|
+
enabled: !!translatable_fields && !!reference,
|
|
50
|
+
placeholderData: keepPreviousData,
|
|
51
|
+
}
|
|
52
|
+
)
|
|
33
53
|
const {
|
|
34
54
|
store,
|
|
35
55
|
isPending: isStorePending,
|
|
@@ -40,13 +60,14 @@ export const TranslationsEdit = () => {
|
|
|
40
60
|
const ready =
|
|
41
61
|
!isPending &&
|
|
42
62
|
!!translations &&
|
|
43
|
-
!!
|
|
63
|
+
!!translatable_fields &&
|
|
64
|
+
!isTranslationSettingsPending &&
|
|
44
65
|
!!references &&
|
|
45
66
|
!isStorePending &&
|
|
46
67
|
!!store
|
|
47
68
|
|
|
48
|
-
if (isError || isStoreError) {
|
|
49
|
-
throw error || storeError
|
|
69
|
+
if (isError || isStoreError || isTranslationSettingsError) {
|
|
70
|
+
throw error || storeError || translationSettingsError
|
|
50
71
|
}
|
|
51
72
|
|
|
52
73
|
return (
|
|
@@ -57,9 +78,12 @@ export const TranslationsEdit = () => {
|
|
|
57
78
|
references={references}
|
|
58
79
|
entityType={reference!}
|
|
59
80
|
availableLocales={store?.supported_locales ?? []}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
81
|
+
translatableFields={translatable_fields[reference!]}
|
|
82
|
+
modalFields={translatable_fields[reference!]}
|
|
83
|
+
fetchNextPage={fetchNextPage}
|
|
84
|
+
hasNextPage={hasNextPage}
|
|
85
|
+
isFetchingNextPage={isFetchingNextPage}
|
|
86
|
+
referenceCount={count}
|
|
63
87
|
/>
|
|
64
88
|
)}
|
|
65
89
|
</RouteFocusModal>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./reference-label-map"
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export const REFERENCE_LABEL_MAP: Record<string, string> = {
|
|
2
|
-
product: "Products",
|
|
3
|
-
product_variant: "Product Variants",
|
|
4
|
-
product_category: "Product Categories",
|
|
5
|
-
product_collection: "Product Collections",
|
|
6
|
-
product_type: "Product Types",
|
|
7
|
-
product_tag: "Product Tags",
|
|
8
|
-
product_option: "Product Options",
|
|
9
|
-
product_option_value: "Product Option Values",
|
|
10
|
-
}
|