@spree/dashboard-core 1.0.0-rc.5 → 1.0.0-rc.6
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/package.json +9 -7
- package/src/api-client.ts +65 -1
- package/src/components/currency-amounts-field.tsx +93 -0
- package/src/index.ts +4 -0
- package/src/lib/currency-amounts.test.ts +147 -0
- package/src/lib/currency-amounts.ts +172 -0
- package/src/locales/ar.json +47 -0
- package/src/locales/de.json +47 -0
- package/src/locales/en.json +47 -0
- package/src/locales/es.json +47 -0
- package/src/locales/fr.json +47 -0
- package/src/locales/pl.json +47 -0
- package/src/locales/zh-CN.json +47 -0
- package/src/products/assignable-variants.ts +35 -0
- package/src/products/digital-asset-edit-sheet.tsx +192 -0
- package/src/products/digital-asset-provider-sheet.tsx +88 -0
- package/src/products/digital-assets-card.tsx +451 -0
- package/src/products/media-edit-sheet.tsx +1 -12
- package/src/products/provider-settings-fields.tsx +110 -0
- package/src/products/use-digital-assets.ts +66 -0
package/src/locales/de.json
CHANGED
|
@@ -117,6 +117,7 @@
|
|
|
117
117
|
"title": "Passwort zurücksetzen"
|
|
118
118
|
},
|
|
119
119
|
"login": {
|
|
120
|
+
"account_deactivated": "Dieses Konto wurde deaktiviert. Wenden Sie sich an einen Administrator, um den Zugang wiederherzustellen.",
|
|
120
121
|
"account_not_provisioned": "Dieses Konto ist für diesen Shop nicht freigegeben. Bitten Sie einen Administrator um eine Einladung.",
|
|
121
122
|
"divider": "oder",
|
|
122
123
|
"invalid_oauth_state": "Die Anmeldesitzung ist abgelaufen oder ungültig. Bitte melden Sie sich erneut an.",
|
|
@@ -487,6 +488,12 @@
|
|
|
487
488
|
"discard_title": "Entwurf verwerfen?"
|
|
488
489
|
}
|
|
489
490
|
},
|
|
491
|
+
"currency_amounts": {
|
|
492
|
+
"amount_in_currency": "Betrag in {{currency}}",
|
|
493
|
+
"help": "Währungen ohne Betrag wird diese Versandart nicht angeboten.",
|
|
494
|
+
"label": "Betrag",
|
|
495
|
+
"required": "Gib einen Betrag in mindestens einer Währung ein."
|
|
496
|
+
},
|
|
490
497
|
"custom_field_definitions": {
|
|
491
498
|
"errors": {
|
|
492
499
|
"failed_to_create": "Benutzerdefiniertes Feld konnte nicht erstellt werden",
|
|
@@ -941,6 +948,14 @@
|
|
|
941
948
|
"order_multiple": {
|
|
942
949
|
"label": "Bestellvielfaches",
|
|
943
950
|
"help": "Jeder Schritt über der Mindestmenge. Leer lassen für beliebige Mengen."
|
|
951
|
+
},
|
|
952
|
+
"store": {
|
|
953
|
+
"digital_asset_authorized_clicks": {
|
|
954
|
+
"label": "Erlaubte Downloads"
|
|
955
|
+
},
|
|
956
|
+
"digital_asset_authorized_days": {
|
|
957
|
+
"label": "Verfügbare Tage"
|
|
958
|
+
}
|
|
944
959
|
}
|
|
945
960
|
},
|
|
946
961
|
"image_upload": {
|
|
@@ -2038,6 +2053,38 @@
|
|
|
2038
2053
|
"description": "Der Verkäufer muss eine Rücksendeadresse angeben"
|
|
2039
2054
|
}
|
|
2040
2055
|
}
|
|
2056
|
+
},
|
|
2057
|
+
"digital_assets": {
|
|
2058
|
+
"add": "Hinzufügen",
|
|
2059
|
+
"all_variants": "Alle Varianten",
|
|
2060
|
+
"columns": {
|
|
2061
|
+
"file": "Datei",
|
|
2062
|
+
"variant": "Variante",
|
|
2063
|
+
"size": "Größe",
|
|
2064
|
+
"downloads": "Downloads",
|
|
2065
|
+
"days": "Tage"
|
|
2066
|
+
},
|
|
2067
|
+
"delete_description": "„{{name}}“ kann von niemandem mehr heruntergeladen werden, der sie gekauft hat. Dies wirkt sofort.",
|
|
2068
|
+
"delete_title": "Diese Datei löschen?",
|
|
2069
|
+
"description": "Dateien, die Käufer nach dem Kauf herunterladen können. Fügen Sie sie einem digitalen Produkt hinzu oder einem physischen Produkt, um eine Anleitung oder Garantie mitzuliefern.",
|
|
2070
|
+
"download": "Herunterladen",
|
|
2071
|
+
"drop_hint": "Dateien hierher ziehen und ablegen oder zum Durchsuchen klicken",
|
|
2072
|
+
"empty": "Noch keine Dateien",
|
|
2073
|
+
"limit_invalid": "Limits müssen ganze Zahlen ab 1 sein oder leer bleiben.",
|
|
2074
|
+
"limits_help": "Lassen Sie die Download- und Tageslimits leer, um die Einstellungen des Shops zu verwenden.",
|
|
2075
|
+
"source": {
|
|
2076
|
+
"upload": "Datei hochladen"
|
|
2077
|
+
},
|
|
2078
|
+
"store_default": "{{count}} (Shop-Standard)",
|
|
2079
|
+
"title": "Digitale Dateien",
|
|
2080
|
+
"untitled": "Unbenannte Datei",
|
|
2081
|
+
"upload": "Datei hinzufügen",
|
|
2082
|
+
"upload_failed": "Hochladen von {{name}} fehlgeschlagen: {{message}}",
|
|
2083
|
+
"uploading": "{{name}} wird hochgeladen…",
|
|
2084
|
+
"uploading_short": "Wird hochgeladen…",
|
|
2085
|
+
"replace": "Datei ersetzen",
|
|
2086
|
+
"replace_description": "„{{name}}“ wird entfernt, und alle Käufer laden über ihre bestehenden Links die neue Datei herunter. Dies gilt sofort.",
|
|
2087
|
+
"replace_title": "Diese Datei ersetzen?"
|
|
2041
2088
|
}
|
|
2042
2089
|
}
|
|
2043
2090
|
}
|
package/src/locales/en.json
CHANGED
|
@@ -117,6 +117,7 @@
|
|
|
117
117
|
"title": "Reset your password"
|
|
118
118
|
},
|
|
119
119
|
"login": {
|
|
120
|
+
"account_deactivated": "This account has been deactivated. Contact an administrator to restore access.",
|
|
120
121
|
"account_not_provisioned": "This account is not authorized for this store. Ask an administrator for an invitation.",
|
|
121
122
|
"divider": "or",
|
|
122
123
|
"invalid_oauth_state": "That sign-in session expired or was invalid. Please start signing in again.",
|
|
@@ -489,6 +490,12 @@
|
|
|
489
490
|
"discard_title": "Discard this draft?"
|
|
490
491
|
}
|
|
491
492
|
},
|
|
493
|
+
"currency_amounts": {
|
|
494
|
+
"amount_in_currency": "Amount in {{currency}}",
|
|
495
|
+
"help": "Currencies left blank are not offered this delivery method.",
|
|
496
|
+
"label": "Amount",
|
|
497
|
+
"required": "Enter an amount in at least one currency."
|
|
498
|
+
},
|
|
492
499
|
"custom_field_definitions": {
|
|
493
500
|
"errors": {
|
|
494
501
|
"failed_to_create": "Failed to create custom field definition",
|
|
@@ -943,6 +950,14 @@
|
|
|
943
950
|
"order_multiple": {
|
|
944
951
|
"label": "Order multiple",
|
|
945
952
|
"help": "Each step up from the minimum. Leave blank for any quantity."
|
|
953
|
+
},
|
|
954
|
+
"store": {
|
|
955
|
+
"digital_asset_authorized_clicks": {
|
|
956
|
+
"label": "Downloads allowed"
|
|
957
|
+
},
|
|
958
|
+
"digital_asset_authorized_days": {
|
|
959
|
+
"label": "Days available"
|
|
960
|
+
}
|
|
946
961
|
}
|
|
947
962
|
},
|
|
948
963
|
"image_upload": {
|
|
@@ -2040,6 +2055,38 @@
|
|
|
2040
2055
|
"description": "The seller must provide an address for returns"
|
|
2041
2056
|
}
|
|
2042
2057
|
}
|
|
2058
|
+
},
|
|
2059
|
+
"digital_assets": {
|
|
2060
|
+
"add": "Add",
|
|
2061
|
+
"all_variants": "All variants",
|
|
2062
|
+
"columns": {
|
|
2063
|
+
"file": "File",
|
|
2064
|
+
"variant": "Variant",
|
|
2065
|
+
"size": "Size",
|
|
2066
|
+
"downloads": "Downloads",
|
|
2067
|
+
"days": "Days"
|
|
2068
|
+
},
|
|
2069
|
+
"delete_description": "\"{{name}}\" will no longer be downloadable by anyone who bought it. This takes effect immediately.",
|
|
2070
|
+
"delete_title": "Delete this file?",
|
|
2071
|
+
"description": "Files buyers can download after purchase. Attach them to a digital product, or to a physical one to deliver a manual or warranty alongside the goods.",
|
|
2072
|
+
"download": "Download",
|
|
2073
|
+
"drop_hint": "Drag & drop files here, or click to browse",
|
|
2074
|
+
"empty": "No files yet",
|
|
2075
|
+
"limit_invalid": "Limits must be whole numbers of 1 or more, or blank.",
|
|
2076
|
+
"limits_help": "Leave the download and day limits blank to use the store's settings.",
|
|
2077
|
+
"source": {
|
|
2078
|
+
"upload": "Upload a file"
|
|
2079
|
+
},
|
|
2080
|
+
"store_default": "{{count}} (store default)",
|
|
2081
|
+
"title": "Digital files",
|
|
2082
|
+
"untitled": "Untitled file",
|
|
2083
|
+
"upload": "Add file",
|
|
2084
|
+
"upload_failed": "Failed to upload {{name}}: {{message}}",
|
|
2085
|
+
"uploading": "Uploading {{name}}…",
|
|
2086
|
+
"uploading_short": "Uploading…",
|
|
2087
|
+
"replace": "Replace file",
|
|
2088
|
+
"replace_description": "\"{{name}}\" is removed and everyone who bought it downloads the new file from their existing links. This takes effect immediately.",
|
|
2089
|
+
"replace_title": "Replace this file?"
|
|
2043
2090
|
}
|
|
2044
2091
|
}
|
|
2045
2092
|
}
|
package/src/locales/es.json
CHANGED
|
@@ -301,6 +301,12 @@
|
|
|
301
301
|
"discard_title": "¿Descartar este borrador?"
|
|
302
302
|
}
|
|
303
303
|
},
|
|
304
|
+
"currency_amounts": {
|
|
305
|
+
"amount_in_currency": "Monto en {{currency}}",
|
|
306
|
+
"help": "A las monedas dejadas en blanco no se les ofrece este método de entrega.",
|
|
307
|
+
"label": "Monto",
|
|
308
|
+
"required": "Introduce un monto en al menos una moneda."
|
|
309
|
+
},
|
|
304
310
|
"pages": {
|
|
305
311
|
"settings": {
|
|
306
312
|
"stock_locations": {
|
|
@@ -970,6 +976,14 @@
|
|
|
970
976
|
"order_multiple": {
|
|
971
977
|
"label": "Múltiplo de pedido",
|
|
972
978
|
"help": "Cada escalón por encima del mínimo. Dejalo en blanco para cualquier cantidad."
|
|
979
|
+
},
|
|
980
|
+
"store": {
|
|
981
|
+
"digital_asset_authorized_clicks": {
|
|
982
|
+
"label": "Descargas permitidas"
|
|
983
|
+
},
|
|
984
|
+
"digital_asset_authorized_days": {
|
|
985
|
+
"label": "Días disponibles"
|
|
986
|
+
}
|
|
973
987
|
}
|
|
974
988
|
},
|
|
975
989
|
"products": {
|
|
@@ -1723,6 +1737,7 @@
|
|
|
1723
1737
|
"title": "Restablecer tu contraseña"
|
|
1724
1738
|
},
|
|
1725
1739
|
"login": {
|
|
1740
|
+
"account_deactivated": "Esta cuenta fue desactivada. Contactá a un administrador para recuperar el acceso.",
|
|
1726
1741
|
"account_not_provisioned": "Esta cuenta no está autorizada para esta tienda. Pedile una invitación a un administrador.",
|
|
1727
1742
|
"divider": "o",
|
|
1728
1743
|
"invalid_oauth_state": "Esa sesión de inicio caducó o fue inválida. Empezá a iniciar sesión de nuevo.",
|
|
@@ -2040,6 +2055,38 @@
|
|
|
2040
2055
|
},
|
|
2041
2056
|
"media_library": {
|
|
2042
2057
|
"download": "Descargar"
|
|
2058
|
+
},
|
|
2059
|
+
"digital_assets": {
|
|
2060
|
+
"add": "Agregar",
|
|
2061
|
+
"all_variants": "Todas las variantes",
|
|
2062
|
+
"columns": {
|
|
2063
|
+
"file": "Archivo",
|
|
2064
|
+
"variant": "Variante",
|
|
2065
|
+
"size": "Tamaño",
|
|
2066
|
+
"downloads": "Descargas",
|
|
2067
|
+
"days": "Días"
|
|
2068
|
+
},
|
|
2069
|
+
"delete_description": "«{{name}}» ya no será descargable por nadie que lo haya comprado. Se aplica de inmediato.",
|
|
2070
|
+
"delete_title": "¿Eliminar este archivo?",
|
|
2071
|
+
"description": "Archivos que los compradores pueden descargar después de comprar. Adjuntalos a un producto digital, o a uno físico para entregar un manual o una garantía junto con la mercadería.",
|
|
2072
|
+
"download": "Descargar",
|
|
2073
|
+
"drop_hint": "Arrastrá y soltá los archivos acá, o hacé clic para explorar",
|
|
2074
|
+
"empty": "Todavía no hay archivos",
|
|
2075
|
+
"limit_invalid": "Los límites deben ser números enteros de 1 o más, o estar en blanco.",
|
|
2076
|
+
"limits_help": "Dejá los límites de descarga y de días en blanco para usar la config de la tienda.",
|
|
2077
|
+
"source": {
|
|
2078
|
+
"upload": "Subir un archivo"
|
|
2079
|
+
},
|
|
2080
|
+
"store_default": "{{count}} (predeterminado de la tienda)",
|
|
2081
|
+
"title": "Archivos digitales",
|
|
2082
|
+
"untitled": "Archivo sin título",
|
|
2083
|
+
"upload": "Agregar archivo",
|
|
2084
|
+
"upload_failed": "No se pudo subir {{name}}: {{message}}",
|
|
2085
|
+
"uploading": "Subiendo {{name}}…",
|
|
2086
|
+
"uploading_short": "Subiendo…",
|
|
2087
|
+
"replace": "Reemplazar archivo",
|
|
2088
|
+
"replace_description": "\"{{name}}\" se elimina y todos los compradores descargan el archivo nuevo desde sus enlaces existentes. Tiene efecto inmediato.",
|
|
2089
|
+
"replace_title": "¿Reemplazar este archivo?"
|
|
2043
2090
|
}
|
|
2044
2091
|
}
|
|
2045
2092
|
}
|
package/src/locales/fr.json
CHANGED
|
@@ -117,6 +117,7 @@
|
|
|
117
117
|
"title": "Réinitialiser votre mot de passe"
|
|
118
118
|
},
|
|
119
119
|
"login": {
|
|
120
|
+
"account_deactivated": "Ce compte a été désactivé. Contactez un administrateur pour rétablir l'accès.",
|
|
120
121
|
"account_not_provisioned": "Ce compte n'est pas autorisé pour cette boutique. Demandez une invitation à un administrateur.",
|
|
121
122
|
"divider": "ou",
|
|
122
123
|
"invalid_oauth_state": "Cette session de connexion a expiré ou n'était pas valide. Veuillez recommencer.",
|
|
@@ -487,6 +488,12 @@
|
|
|
487
488
|
"discard_title": "Abandonner ce brouillon ?"
|
|
488
489
|
}
|
|
489
490
|
},
|
|
491
|
+
"currency_amounts": {
|
|
492
|
+
"amount_in_currency": "Montant en {{currency}}",
|
|
493
|
+
"help": "Les devises laissées vides ne se voient pas proposer cette méthode de livraison.",
|
|
494
|
+
"label": "Montant",
|
|
495
|
+
"required": "Saisissez un montant dans au moins une devise."
|
|
496
|
+
},
|
|
490
497
|
"custom_field_definitions": {
|
|
491
498
|
"errors": {
|
|
492
499
|
"failed_to_create": "Impossible de créer le champ personnalisé",
|
|
@@ -941,6 +948,14 @@
|
|
|
941
948
|
"order_multiple": {
|
|
942
949
|
"label": "Multiple de commande",
|
|
943
950
|
"help": "Chaque palier au-dessus du minimum. Laisser vide pour toute quantité."
|
|
951
|
+
},
|
|
952
|
+
"store": {
|
|
953
|
+
"digital_asset_authorized_clicks": {
|
|
954
|
+
"label": "Téléchargements autorisés"
|
|
955
|
+
},
|
|
956
|
+
"digital_asset_authorized_days": {
|
|
957
|
+
"label": "Jours de disponibilité"
|
|
958
|
+
}
|
|
944
959
|
}
|
|
945
960
|
},
|
|
946
961
|
"image_upload": {
|
|
@@ -2038,6 +2053,38 @@
|
|
|
2038
2053
|
"description": "Le vendeur doit fournir une adresse pour les retours"
|
|
2039
2054
|
}
|
|
2040
2055
|
}
|
|
2056
|
+
},
|
|
2057
|
+
"digital_assets": {
|
|
2058
|
+
"add": "Ajouter",
|
|
2059
|
+
"all_variants": "Toutes les variantes",
|
|
2060
|
+
"columns": {
|
|
2061
|
+
"file": "Fichier",
|
|
2062
|
+
"variant": "Variante",
|
|
2063
|
+
"size": "Taille",
|
|
2064
|
+
"downloads": "Téléchargements",
|
|
2065
|
+
"days": "Jours"
|
|
2066
|
+
},
|
|
2067
|
+
"delete_description": "« {{name}} » ne sera plus téléchargeable par les personnes qui l'ont acheté. Effet immédiat.",
|
|
2068
|
+
"delete_title": "Supprimer ce fichier ?",
|
|
2069
|
+
"description": "Fichiers que les acheteurs peuvent télécharger après l'achat. Associez-les à un produit numérique, ou à un produit physique pour livrer un manuel ou une garantie.",
|
|
2070
|
+
"download": "Télécharger",
|
|
2071
|
+
"drop_hint": "Glissez-déposez des fichiers ici, ou cliquez pour parcourir",
|
|
2072
|
+
"empty": "Aucun fichier pour le moment",
|
|
2073
|
+
"limit_invalid": "Les limites doivent être des entiers supérieurs ou égaux à 1, ou vides.",
|
|
2074
|
+
"limits_help": "Laissez les limites de téléchargements et de jours vides pour utiliser les paramètres de la boutique.",
|
|
2075
|
+
"source": {
|
|
2076
|
+
"upload": "Téléverser un fichier"
|
|
2077
|
+
},
|
|
2078
|
+
"store_default": "{{count}} (par défaut)",
|
|
2079
|
+
"title": "Fichiers numériques",
|
|
2080
|
+
"untitled": "Fichier sans nom",
|
|
2081
|
+
"upload": "Ajouter un fichier",
|
|
2082
|
+
"upload_failed": "Échec du téléversement de {{name}} : {{message}}",
|
|
2083
|
+
"uploading": "Téléversement de {{name}}…",
|
|
2084
|
+
"uploading_short": "Téléversement…",
|
|
2085
|
+
"replace": "Remplacer le fichier",
|
|
2086
|
+
"replace_description": "« {{name}} » est supprimé et tous les acheteurs téléchargent le nouveau fichier depuis leurs liens existants. Effet immédiat.",
|
|
2087
|
+
"replace_title": "Remplacer ce fichier ?"
|
|
2041
2088
|
}
|
|
2042
2089
|
}
|
|
2043
2090
|
}
|
package/src/locales/pl.json
CHANGED
|
@@ -117,6 +117,7 @@
|
|
|
117
117
|
"title": "Zresetuj hasło"
|
|
118
118
|
},
|
|
119
119
|
"login": {
|
|
120
|
+
"account_deactivated": "To konto zostało dezaktywowane. Skontaktuj się z administratorem, aby przywrócić dostęp.",
|
|
120
121
|
"account_not_provisioned": "To konto nie ma dostępu do tego sklepu. Poproś administratora o zaproszenie.",
|
|
121
122
|
"divider": "lub",
|
|
122
123
|
"invalid_oauth_state": "Ta sesja logowania wygasła lub była nieprawidłowa. Zaloguj się ponownie.",
|
|
@@ -488,6 +489,12 @@
|
|
|
488
489
|
"discard_title": "Odrzucić szkic?"
|
|
489
490
|
}
|
|
490
491
|
},
|
|
492
|
+
"currency_amounts": {
|
|
493
|
+
"amount_in_currency": "Kwota w {{currency}}",
|
|
494
|
+
"help": "Waluty bez kwoty nie mają oferowanej tej metody dostawy.",
|
|
495
|
+
"label": "Kwota",
|
|
496
|
+
"required": "Podaj kwotę w co najmniej jednej walucie."
|
|
497
|
+
},
|
|
491
498
|
"custom_field_definitions": {
|
|
492
499
|
"errors": {
|
|
493
500
|
"failed_to_create": "Nie udało się utworzyć definicji pola niestandardowego",
|
|
@@ -942,6 +949,14 @@
|
|
|
942
949
|
"order_multiple": {
|
|
943
950
|
"label": "Wielokrotność zamówienia",
|
|
944
951
|
"help": "Każdy kolejny krok powyżej minimum. Pozostaw puste, aby dopuścić dowolną ilość."
|
|
952
|
+
},
|
|
953
|
+
"store": {
|
|
954
|
+
"digital_asset_authorized_clicks": {
|
|
955
|
+
"label": "Dozwolone pobrania"
|
|
956
|
+
},
|
|
957
|
+
"digital_asset_authorized_days": {
|
|
958
|
+
"label": "Dostępne dni"
|
|
959
|
+
}
|
|
945
960
|
}
|
|
946
961
|
},
|
|
947
962
|
"image_upload": {
|
|
@@ -2067,6 +2082,38 @@
|
|
|
2067
2082
|
"description": "Sprzedawca musi podać adres do zwrotów"
|
|
2068
2083
|
}
|
|
2069
2084
|
}
|
|
2085
|
+
},
|
|
2086
|
+
"digital_assets": {
|
|
2087
|
+
"add": "Dodaj",
|
|
2088
|
+
"all_variants": "Wszystkie warianty",
|
|
2089
|
+
"columns": {
|
|
2090
|
+
"file": "Plik",
|
|
2091
|
+
"variant": "Wariant",
|
|
2092
|
+
"size": "Rozmiar",
|
|
2093
|
+
"downloads": "Pobrania",
|
|
2094
|
+
"days": "Dni"
|
|
2095
|
+
},
|
|
2096
|
+
"delete_description": "„{{name}}” nie będzie już dostępny do pobrania dla osób, które go kupiły. Zmiana działa natychmiast.",
|
|
2097
|
+
"delete_title": "Usunąć ten plik?",
|
|
2098
|
+
"description": "Pliki, które kupujący mogą pobrać po zakupie. Dołącz je do produktu cyfrowego lub do fizycznego, aby dostarczyć instrukcję albo gwarancję.",
|
|
2099
|
+
"download": "Pobierz",
|
|
2100
|
+
"drop_hint": "Przeciągnij i upuść pliki tutaj lub kliknij, aby wybrać",
|
|
2101
|
+
"empty": "Brak plików",
|
|
2102
|
+
"limit_invalid": "Limity muszą być liczbami całkowitymi od 1 lub puste.",
|
|
2103
|
+
"limits_help": "Pozostaw limity pobrań i dni puste, aby użyć ustawień sklepu.",
|
|
2104
|
+
"source": {
|
|
2105
|
+
"upload": "Prześlij plik"
|
|
2106
|
+
},
|
|
2107
|
+
"store_default": "{{count}} (domyślne sklepu)",
|
|
2108
|
+
"title": "Pliki cyfrowe",
|
|
2109
|
+
"untitled": "Plik bez nazwy",
|
|
2110
|
+
"upload": "Dodaj plik",
|
|
2111
|
+
"upload_failed": "Nie udało się przesłać {{name}}: {{message}}",
|
|
2112
|
+
"uploading": "Przesyłanie {{name}}…",
|
|
2113
|
+
"uploading_short": "Przesyłanie…",
|
|
2114
|
+
"replace": "Zastąp plik",
|
|
2115
|
+
"replace_description": "„{{name}}” zostanie usunięty, a wszyscy kupujący pobiorą nowy plik ze swoich dotychczasowych linków. Obowiązuje natychmiast.",
|
|
2116
|
+
"replace_title": "Zastąpić ten plik?"
|
|
2070
2117
|
}
|
|
2071
2118
|
}
|
|
2072
2119
|
}
|
package/src/locales/zh-CN.json
CHANGED
|
@@ -117,6 +117,7 @@
|
|
|
117
117
|
"title": "重置密码"
|
|
118
118
|
},
|
|
119
119
|
"login": {
|
|
120
|
+
"account_deactivated": "此账户已被停用。请联系管理员恢复访问权限。",
|
|
120
121
|
"account_not_provisioned": "此账户无权访问该店铺。请向管理员申请邀请。",
|
|
121
122
|
"divider": "或",
|
|
122
123
|
"invalid_oauth_state": "登录会话已过期或无效。请重新登录。",
|
|
@@ -487,6 +488,12 @@
|
|
|
487
488
|
"discard_title": "放弃此草稿?"
|
|
488
489
|
}
|
|
489
490
|
},
|
|
491
|
+
"currency_amounts": {
|
|
492
|
+
"amount_in_currency": "{{currency}} 金额",
|
|
493
|
+
"help": "未填写金额的币种将不会提供该配送方式。",
|
|
494
|
+
"label": "金额",
|
|
495
|
+
"required": "请至少为一种货币输入金额。"
|
|
496
|
+
},
|
|
490
497
|
"custom_field_definitions": {
|
|
491
498
|
"errors": {
|
|
492
499
|
"failed_to_create": "创建自定义字段定义失败",
|
|
@@ -941,6 +948,14 @@
|
|
|
941
948
|
"order_multiple": {
|
|
942
949
|
"label": "订购倍数",
|
|
943
950
|
"help": "在最小起订量之上的每一档增量。留空表示不限数量。"
|
|
951
|
+
},
|
|
952
|
+
"store": {
|
|
953
|
+
"digital_asset_authorized_clicks": {
|
|
954
|
+
"label": "允许的下载次数"
|
|
955
|
+
},
|
|
956
|
+
"digital_asset_authorized_days": {
|
|
957
|
+
"label": "可用天数"
|
|
958
|
+
}
|
|
944
959
|
}
|
|
945
960
|
},
|
|
946
961
|
"image_upload": {
|
|
@@ -2037,6 +2052,38 @@
|
|
|
2037
2052
|
"description": "卖家必须提供退货地址"
|
|
2038
2053
|
}
|
|
2039
2054
|
}
|
|
2055
|
+
},
|
|
2056
|
+
"digital_assets": {
|
|
2057
|
+
"add": "添加",
|
|
2058
|
+
"all_variants": "所有变体",
|
|
2059
|
+
"columns": {
|
|
2060
|
+
"file": "文件",
|
|
2061
|
+
"variant": "变体",
|
|
2062
|
+
"size": "大小",
|
|
2063
|
+
"downloads": "下载次数",
|
|
2064
|
+
"days": "天数"
|
|
2065
|
+
},
|
|
2066
|
+
"delete_description": "购买过“{{name}}”的人将无法再下载它。此操作立即生效。",
|
|
2067
|
+
"delete_title": "删除此文件?",
|
|
2068
|
+
"description": "买家购买后可下载的文件。可附加到数字商品,也可附加到实体商品以随货提供说明书或保修卡。",
|
|
2069
|
+
"download": "下载",
|
|
2070
|
+
"drop_hint": "将文件拖放到此处,或点击浏览",
|
|
2071
|
+
"empty": "暂无文件",
|
|
2072
|
+
"limit_invalid": "限制必须是不小于 1 的整数,或留空。",
|
|
2073
|
+
"limits_help": "将下载次数和天数限制留空即可使用商店设置。",
|
|
2074
|
+
"source": {
|
|
2075
|
+
"upload": "上传文件"
|
|
2076
|
+
},
|
|
2077
|
+
"store_default": "{{count}}(商店默认)",
|
|
2078
|
+
"title": "数字文件",
|
|
2079
|
+
"untitled": "未命名文件",
|
|
2080
|
+
"upload": "添加文件",
|
|
2081
|
+
"upload_failed": "上传 {{name}} 失败:{{message}}",
|
|
2082
|
+
"uploading": "正在上传 {{name}}…",
|
|
2083
|
+
"uploading_short": "上传中…",
|
|
2084
|
+
"replace": "替换文件",
|
|
2085
|
+
"replace_description": "“{{name}}”将被移除,所有买家将通过现有链接下载新文件。立即生效。",
|
|
2086
|
+
"replace_title": "替换此文件?"
|
|
2040
2087
|
}
|
|
2041
2088
|
}
|
|
2042
2089
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { i18n, type ProductFormValues } from '@spree/dashboard-core'
|
|
2
|
+
import { type Control, useWatch } from 'react-hook-form'
|
|
3
|
+
|
|
4
|
+
interface LabelledVariant {
|
|
5
|
+
id: string
|
|
6
|
+
options_text?: string | null
|
|
7
|
+
sku?: string | null
|
|
8
|
+
name?: string | null
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** The name a variant goes by in a picker. */
|
|
12
|
+
export function variantLabel(variant: LabelledVariant): string {
|
|
13
|
+
return (
|
|
14
|
+
variant.options_text ||
|
|
15
|
+
variant.name ||
|
|
16
|
+
variant.sku ||
|
|
17
|
+
variant.id ||
|
|
18
|
+
i18n.t('admin.products.variants.variant_label')
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The saved variants a file can be linked to. A card that links files saves
|
|
24
|
+
* at once, so it must not offer a variant the merchant removed in the form but
|
|
25
|
+
* has not saved yet: saving would delete that variant and its files with it.
|
|
26
|
+
* Variants added but not saved have no id to link to.
|
|
27
|
+
*/
|
|
28
|
+
export function useAssignableVariants<V extends { id: string }>(
|
|
29
|
+
control: Control<ProductFormValues>,
|
|
30
|
+
variants: V[] | undefined,
|
|
31
|
+
): V[] {
|
|
32
|
+
const liveVariants = useWatch({ control, name: 'variants' })
|
|
33
|
+
const liveVariantIds = new Set((liveVariants ?? []).map((variant) => variant.id).filter(Boolean))
|
|
34
|
+
return (variants ?? []).filter((variant) => liveVariantIds.has(variant.id))
|
|
35
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import type { DigitalAssetProviderSettingField } from '@spree/admin-sdk'
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
Field,
|
|
5
|
+
FieldLabel,
|
|
6
|
+
Input,
|
|
7
|
+
Select,
|
|
8
|
+
SelectContent,
|
|
9
|
+
SelectItem,
|
|
10
|
+
SelectTrigger,
|
|
11
|
+
SelectValue,
|
|
12
|
+
Sheet,
|
|
13
|
+
SheetContent,
|
|
14
|
+
SheetFooter,
|
|
15
|
+
SheetHeader,
|
|
16
|
+
SheetTitle,
|
|
17
|
+
} from '@spree/dashboard-ui'
|
|
18
|
+
import { useEffect, useState } from 'react'
|
|
19
|
+
import { useTranslation } from 'react-i18next'
|
|
20
|
+
import type { PanelDigitalAsset } from '../api-client'
|
|
21
|
+
import { variantLabel } from './assignable-variants'
|
|
22
|
+
import type { PanelVariant } from './product-types'
|
|
23
|
+
import { ProviderSettingsFields } from './provider-settings-fields'
|
|
24
|
+
import { useUpdateDigitalAsset } from './use-digital-assets'
|
|
25
|
+
|
|
26
|
+
interface Props {
|
|
27
|
+
productId: string
|
|
28
|
+
asset: PanelDigitalAsset | null
|
|
29
|
+
variants?: PanelVariant[]
|
|
30
|
+
/** Fields for a provider-backed asset; empty for an uploaded file. */
|
|
31
|
+
settingsSchema?: DigitalAssetProviderSettingField[]
|
|
32
|
+
open: boolean
|
|
33
|
+
onOpenChange: (open: boolean) => void
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Blank means "use the store's setting", so an empty box is a real value. */
|
|
37
|
+
function toInput(value: number | null | undefined): string {
|
|
38
|
+
return value == null ? '' : String(value)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function parseLimit(raw: string): number | null | undefined {
|
|
42
|
+
if (raw.trim() === '') return null
|
|
43
|
+
const parsed = Number(raw)
|
|
44
|
+
return Number.isInteger(parsed) && parsed >= 1 ? parsed : undefined
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function DigitalAssetEditSheet({
|
|
48
|
+
productId,
|
|
49
|
+
asset,
|
|
50
|
+
variants,
|
|
51
|
+
settingsSchema = [],
|
|
52
|
+
open,
|
|
53
|
+
onOpenChange,
|
|
54
|
+
}: Props) {
|
|
55
|
+
const { t } = useTranslation()
|
|
56
|
+
const updateAsset = useUpdateDigitalAsset(productId)
|
|
57
|
+
|
|
58
|
+
const [clicks, setClicks] = useState('')
|
|
59
|
+
const [days, setDays] = useState('')
|
|
60
|
+
const [variantId, setVariantId] = useState('')
|
|
61
|
+
const [settings, setSettings] = useState<Record<string, unknown>>({})
|
|
62
|
+
const [error, setError] = useState<string | null>(null)
|
|
63
|
+
|
|
64
|
+
// Re-seed whenever a different file is opened, so the sheet never shows the
|
|
65
|
+
// previous row's values.
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (!asset) return
|
|
68
|
+
setClicks(toInput(asset.authorized_clicks))
|
|
69
|
+
setDays(toInput(asset.authorized_days))
|
|
70
|
+
setVariantId(asset.variant_id ?? '')
|
|
71
|
+
setSettings(asset.provider_settings ?? {})
|
|
72
|
+
setError(null)
|
|
73
|
+
}, [asset])
|
|
74
|
+
|
|
75
|
+
if (!asset) return null
|
|
76
|
+
|
|
77
|
+
const hasVariants = (variants?.length ?? 0) > 1
|
|
78
|
+
|
|
79
|
+
async function handleSave() {
|
|
80
|
+
const parsedClicks = parseLimit(clicks)
|
|
81
|
+
const parsedDays = parseLimit(days)
|
|
82
|
+
|
|
83
|
+
if (parsedClicks === undefined || parsedDays === undefined) {
|
|
84
|
+
setError(t('admin.digital_assets.limit_invalid'))
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
setError(null)
|
|
89
|
+
try {
|
|
90
|
+
await updateAsset.mutateAsync({
|
|
91
|
+
id: asset!.id,
|
|
92
|
+
authorized_clicks: parsedClicks,
|
|
93
|
+
authorized_days: parsedDays,
|
|
94
|
+
...(hasVariants && variantId ? { variant_id: variantId } : {}),
|
|
95
|
+
...(settingsSchema.length > 0 ? { provider_settings: settings } : {}),
|
|
96
|
+
})
|
|
97
|
+
onOpenChange(false)
|
|
98
|
+
} catch (err) {
|
|
99
|
+
// useResourceMutation suppresses the toast for a 422, so surface the
|
|
100
|
+
// reason inline and keep the sheet open with the entered values.
|
|
101
|
+
setError(err instanceof Error ? err.message : t('admin.errors.unexpected'))
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<Sheet open={open} onOpenChange={onOpenChange}>
|
|
107
|
+
<SheetContent side="right" className="flex flex-col">
|
|
108
|
+
<SheetHeader>
|
|
109
|
+
<SheetTitle>
|
|
110
|
+
{asset.filename ?? asset.provider_name ?? t('admin.digital_assets.untitled')}
|
|
111
|
+
</SheetTitle>
|
|
112
|
+
</SheetHeader>
|
|
113
|
+
|
|
114
|
+
<div className="flex flex-1 flex-col gap-6 overflow-y-auto p-4">
|
|
115
|
+
<ProviderSettingsFields
|
|
116
|
+
schema={settingsSchema}
|
|
117
|
+
values={settings}
|
|
118
|
+
onChange={setSettings}
|
|
119
|
+
/>
|
|
120
|
+
|
|
121
|
+
{hasVariants && (
|
|
122
|
+
<Field>
|
|
123
|
+
<FieldLabel htmlFor="digital-asset-variant">
|
|
124
|
+
{t('admin.digital_assets.columns.variant')}
|
|
125
|
+
</FieldLabel>
|
|
126
|
+
<Select value={variantId} onValueChange={setVariantId}>
|
|
127
|
+
<SelectTrigger id="digital-asset-variant">
|
|
128
|
+
<SelectValue>
|
|
129
|
+
{(value) => {
|
|
130
|
+
const variant = variants?.find((v) => v.id === value)
|
|
131
|
+
return variant
|
|
132
|
+
? variantLabel(variant)
|
|
133
|
+
: t('admin.digital_assets.all_variants')
|
|
134
|
+
}}
|
|
135
|
+
</SelectValue>
|
|
136
|
+
</SelectTrigger>
|
|
137
|
+
<SelectContent>
|
|
138
|
+
{variants?.map((variant) => (
|
|
139
|
+
<SelectItem key={variant.id} value={variant.id}>
|
|
140
|
+
{variantLabel(variant)}
|
|
141
|
+
</SelectItem>
|
|
142
|
+
))}
|
|
143
|
+
</SelectContent>
|
|
144
|
+
</Select>
|
|
145
|
+
</Field>
|
|
146
|
+
)}
|
|
147
|
+
|
|
148
|
+
<Field>
|
|
149
|
+
<FieldLabel htmlFor="digital-asset-clicks">
|
|
150
|
+
{t('admin.fields.store.digital_asset_authorized_clicks.label')}
|
|
151
|
+
</FieldLabel>
|
|
152
|
+
<Input
|
|
153
|
+
id="digital-asset-clicks"
|
|
154
|
+
type="number"
|
|
155
|
+
min={1}
|
|
156
|
+
value={clicks}
|
|
157
|
+
placeholder={String(asset.effective_authorized_clicks)}
|
|
158
|
+
onChange={(e) => setClicks(e.target.value)}
|
|
159
|
+
/>
|
|
160
|
+
</Field>
|
|
161
|
+
|
|
162
|
+
<Field>
|
|
163
|
+
<FieldLabel htmlFor="digital-asset-days">
|
|
164
|
+
{t('admin.fields.store.digital_asset_authorized_days.label')}
|
|
165
|
+
</FieldLabel>
|
|
166
|
+
<Input
|
|
167
|
+
id="digital-asset-days"
|
|
168
|
+
type="number"
|
|
169
|
+
min={1}
|
|
170
|
+
value={days}
|
|
171
|
+
placeholder={String(asset.effective_authorized_days)}
|
|
172
|
+
onChange={(e) => setDays(e.target.value)}
|
|
173
|
+
/>
|
|
174
|
+
</Field>
|
|
175
|
+
|
|
176
|
+
<p className="text-muted-foreground text-xs">{t('admin.digital_assets.limits_help')}</p>
|
|
177
|
+
|
|
178
|
+
{error && <p className="text-destructive text-sm">{error}</p>}
|
|
179
|
+
</div>
|
|
180
|
+
|
|
181
|
+
<SheetFooter>
|
|
182
|
+
<Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
|
|
183
|
+
{t('admin.actions.cancel')}
|
|
184
|
+
</Button>
|
|
185
|
+
<Button type="button" onClick={handleSave} disabled={updateAsset.isPending}>
|
|
186
|
+
{updateAsset.isPending ? t('admin.actions.saving') : t('admin.actions.save')}
|
|
187
|
+
</Button>
|
|
188
|
+
</SheetFooter>
|
|
189
|
+
</SheetContent>
|
|
190
|
+
</Sheet>
|
|
191
|
+
)
|
|
192
|
+
}
|