diff options
author | Christian Blättler <blatc2@bfh.ch> | 2024-05-22 20:24:27 +0200 |
---|---|---|
committer | Christian Blättler <blatc2@bfh.ch> | 2024-05-22 20:24:27 +0200 |
commit | 631027a807138ed9125befc7a2a7c0d8219e17c6 (patch) | |
tree | f088a606d4852b524e1f62fe549f68df367ff2ca /packages/merchant-backoffice-ui/src | |
parent | 349cd9a1f46a2ea8e8d9e502577196c7ed1847eb (diff) | |
parent | 027b26d1ac9d88a4cfc901cc2465e45bfe13e812 (diff) | |
download | wallet-core-631027a807138ed9125befc7a2a7c0d8219e17c6.tar.xz |
Merge branch 'master' into feature/tokens
Diffstat (limited to 'packages/merchant-backoffice-ui/src')
11 files changed, 114 insertions, 89 deletions
diff --git a/packages/merchant-backoffice-ui/src/Application.tsx b/packages/merchant-backoffice-ui/src/Application.tsx index 097e98567..5be21ff8f 100644 --- a/packages/merchant-backoffice-ui/src/Application.tsx +++ b/packages/merchant-backoffice-ui/src/Application.tsx @@ -279,7 +279,10 @@ const swrCacheEvictor = new (class return; } case TalerMerchantInstanceCacheEviction.UPDATE_PRODUCT: { - await Promise.all([revalidateProductDetails()]); + await Promise.all([ + revalidateProductDetails(), + revalidateInstanceProducts(), + ]); return; } case TalerMerchantInstanceCacheEviction.DELETE_PRODUCT: { diff --git a/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx b/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx index c6d687b85..dede0008f 100644 --- a/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx +++ b/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx @@ -147,13 +147,13 @@ export function ProductForm({ onSubscribe, initial, alreadyExist }: Props) { name="minimum_age" label={i18n.str`Age restriction`} tooltip={i18n.str`is this product restricted for customer below certain age?`} - help={i18n.str`minimum age of the buyer`} + help={i18n.str`minimum age of the customer`} /> <Input<Entity> name="unit" label={i18n.str`Unit name`} tooltip={i18n.str`unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 items, 5 meters) for customers`} - help={i18n.str`exajmple: kg, items or liters`} + help={i18n.str`example: kg, items or liters`} /> <InputCurrency<Entity> name="price" diff --git a/packages/merchant-backoffice-ui/src/hooks/templates.ts b/packages/merchant-backoffice-ui/src/hooks/templates.ts index 12d99f3fc..500a94a48 100644 --- a/packages/merchant-backoffice-ui/src/hooks/templates.ts +++ b/packages/merchant-backoffice-ui/src/hooks/templates.ts @@ -57,7 +57,8 @@ export function useInstanceTemplates() { if (data === undefined) return undefined; if (data.type !== "ok") return data; - return buildPaginatedResult(data.body.templates, offset, setOffset, (d) => d.template_id) + // return buildPaginatedResult(data.body.templates, offset, setOffset, (d) => d.template_id) + return data; } diff --git a/packages/merchant-backoffice-ui/src/i18n/de.po b/packages/merchant-backoffice-ui/src/i18n/de.po index f34d5dd20..66d654f64 100644 --- a/packages/merchant-backoffice-ui/src/i18n/de.po +++ b/packages/merchant-backoffice-ui/src/i18n/de.po @@ -17,7 +17,7 @@ msgstr "" "Project-Id-Version: Taler Wallet\n" "Report-Msgid-Bugs-To: taler@gnu.org\n" "POT-Creation-Date: 2016-11-23 00:00+0100\n" -"PO-Revision-Date: 2024-03-21 21:39+0000\n" +"PO-Revision-Date: 2024-05-07 14:32+0000\n" "Last-Translator: Stefan Kügel <skuegel@web.de>\n" "Language-Team: German <https://weblate.taler.net/projects/gnu-taler/" "merchant-backoffice/de/>\n" @@ -26,27 +26,27 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.2.1\n" +"X-Generator: Weblate 5.4.3\n" #: src/components/modal/index.tsx:71 #, c-format msgid "Cancel" -msgstr "" +msgstr "Zurück" #: src/components/modal/index.tsx:79 #, c-format msgid "%1$s" -msgstr "" +msgstr "%1$s" #: src/components/modal/index.tsx:84 #, c-format msgid "Close" -msgstr "" +msgstr "Schließen" #: src/components/modal/index.tsx:124 #, c-format msgid "Continue" -msgstr "" +msgstr "Weiter" #: src/components/modal/index.tsx:178 #, c-format @@ -66,12 +66,12 @@ msgstr "" #: src/components/modal/index.tsx:299 #, c-format msgid "cannot be empty" -msgstr "" +msgstr "darf nicht leer sein" #: src/components/modal/index.tsx:301 #, c-format msgid "cannot be the same as the old token" -msgstr "" +msgstr "muss sich vom alten Token unterscheiden" #: src/components/modal/index.tsx:305 #, c-format @@ -563,57 +563,59 @@ msgstr "" #: src/paths/instance/orders/create/CreatePage.tsx:164 #, c-format msgid "not a valid json" -msgstr "" +msgstr "kein gültiges JSON-Format" #: src/paths/instance/orders/create/CreatePage.tsx:170 #, c-format msgid "should be in the future" -msgstr "" +msgstr "sollte in der Zukunft liegen" #: src/paths/instance/orders/create/CreatePage.tsx:173 #, c-format msgid "refund deadline cannot be before pay deadline" -msgstr "" +msgstr "Die Rückerstattungsfrist kann nicht vor der Zahlungsfrist liegen" #: src/paths/instance/orders/create/CreatePage.tsx:179 #, c-format msgid "wire transfer deadline cannot be before refund deadline" -msgstr "" +msgstr "Die Überweisungsfrist kann nicht vor der Rückerstattungsfrist liegen" #: src/paths/instance/orders/create/CreatePage.tsx:190 #, c-format msgid "wire transfer deadline cannot be before pay deadline" -msgstr "" +msgstr "Die Überweisungsfrist kann nicht vor der Zahlungsfrist liegen" #: src/paths/instance/orders/create/CreatePage.tsx:197 #, c-format msgid "should have a refund deadline" -msgstr "" +msgstr "sollte eine Rückerstattungsfrist haben" #: src/paths/instance/orders/create/CreatePage.tsx:202 #, c-format msgid "auto refund cannot be after refund deadline" msgstr "" +"Die automatische Rückerstattung kann nicht nach der Rückerstattungsfrist " +"erfolgen" #: src/paths/instance/orders/create/CreatePage.tsx:360 #, c-format msgid "Manage products in order" -msgstr "" +msgstr "Artikel in der Bestellung verwalten" #: src/paths/instance/orders/create/CreatePage.tsx:369 #, c-format msgid "Manage list of products in the order." -msgstr "" +msgstr "Liste der Artikel in der Bestellung verwalten." #: src/paths/instance/orders/create/CreatePage.tsx:391 #, c-format msgid "Remove this product from the order." -msgstr "" +msgstr "Diesen Artikel aus der Bestellung entfernen." #: src/paths/instance/orders/create/CreatePage.tsx:415 #, c-format msgid "Total price" -msgstr "" +msgstr "Gesamtpreis" #: src/paths/instance/orders/create/CreatePage.tsx:417 #, c-format @@ -623,12 +625,12 @@ msgstr "" #: src/paths/instance/orders/create/CreatePage.tsx:430 #, c-format msgid "Amount to be paid by the customer" -msgstr "" +msgstr "Zu zahlender Betrag" #: src/paths/instance/orders/create/CreatePage.tsx:436 #, c-format msgid "Order price" -msgstr "" +msgstr "Bestellsumme" #: src/paths/instance/orders/create/CreatePage.tsx:437 #, c-format @@ -638,12 +640,12 @@ msgstr "" #: src/paths/instance/orders/create/CreatePage.tsx:444 #, c-format msgid "Summary" -msgstr "" +msgstr "Zusammenfassung" #: src/paths/instance/orders/create/CreatePage.tsx:445 #, c-format msgid "Title of the order to be shown to the customer" -msgstr "" +msgstr "Bezeichnung der Bestellung, die den Kunden angezeigt wird" #: src/paths/instance/orders/create/CreatePage.tsx:450 #, c-format @@ -653,12 +655,12 @@ msgstr "" #: src/paths/instance/orders/create/CreatePage.tsx:455 #, c-format msgid "Delivery date" -msgstr "" +msgstr "Lieferdatum" #: src/paths/instance/orders/create/CreatePage.tsx:456 #, c-format msgid "Deadline for physical delivery assured by the merchant." -msgstr "" +msgstr "Vom Händler zugesicherte Zustellfrist." #: src/paths/instance/orders/create/CreatePage.tsx:461 #, c-format @@ -668,22 +670,22 @@ msgstr "" #: src/paths/instance/orders/create/CreatePage.tsx:462 #, c-format msgid "address where the products will be delivered" -msgstr "" +msgstr "Zustelladresse der Artikel" #: src/paths/instance/orders/create/CreatePage.tsx:469 #, c-format msgid "Fulfillment URL" -msgstr "" +msgstr "Adresse digitaler Dienstleistung (Fulfillment-URL)" #: src/paths/instance/orders/create/CreatePage.tsx:470 #, c-format msgid "URL to which the user will be redirected after successful payment." -msgstr "" +msgstr "URL der von Kunden zu besuchenden Adresse nach erfolgter Bezahlung." #: src/paths/instance/orders/create/CreatePage.tsx:476 #, c-format msgid "Taler payment options" -msgstr "" +msgstr "Taler-Zahlungsoptionen" #: src/paths/instance/orders/create/CreatePage.tsx:477 #, c-format @@ -693,7 +695,7 @@ msgstr "" #: src/paths/instance/orders/create/CreatePage.tsx:481 #, c-format msgid "Payment deadline" -msgstr "" +msgstr "Zahlungsfrist" #: src/paths/instance/orders/create/CreatePage.tsx:482 #, c-format diff --git a/packages/merchant-backoffice-ui/src/index.html b/packages/merchant-backoffice-ui/src/index.html index b005f967d..6b738d2b7 100644 --- a/packages/merchant-backoffice-ui/src/index.html +++ b/packages/merchant-backoffice-ui/src/index.html @@ -26,6 +26,7 @@ <meta name="viewport" content="width=device-width,initial-scale=1" /> <meta name="mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-capable" content="yes" /> + <meta name="taler-support" content="uri,api" /> <link rel="icon" diff --git a/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx index 9d5701fa7..39e2fd0c7 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx @@ -506,6 +506,7 @@ function difference(price: string, tax: number) { ps[1] = `${p - tax}`; return ps.join(":"); } -function sum(taxes: TalerMerchantApi.Tax[]) { +function sum(taxes: TalerMerchantApi.Tax[] | undefined) { + if (taxes === undefined) return 0; return taxes.reduce((p, c) => p + parseInt(c.tax.split(":")[1], 10), 0); } diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx index 78d7c83ac..50262be17 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx @@ -70,7 +70,7 @@ interface Props { export function CreatePage({ onCreate, onBack }: Props): VNode { const { i18n } = useTranslationContext(); const { config } = useSessionContext(); - const {state:session} = useSessionContext(); + const { state: session } = useSessionContext(); const devices = useInstanceOtpDevices(); const [state, setState] = useState<Partial<Entity>>({ @@ -100,11 +100,11 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { : undefined, description: !state.description ? i18n.str`should not be empty` : undefined, amount: !state.amount - ? undefined + ? state.amount_editable ? undefined : i18n.str`required` : !parsedPrice ? i18n.str`not valid` : Amounts.isZero(parsedPrice) - ? i18n.str`must be greater than 0` + ? state.amount_editable ? undefined : i18n.str`must be greater than 0` : undefined, minimum_age: state.minimum_age && state.minimum_age < 0 @@ -125,24 +125,30 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { (k) => (errors as Record<string, unknown>)[k] !== undefined, ); + const zero = Amounts.stringify(Amounts.zeroOfCurrency(config.currency)) + const submitForm = () => { if (hasErrors) return Promise.reject(); + const contract_amount = state.amount_editable ? undefined : state.amount as AmountString + const contract_summary = state.summary_editable ? undefined : state.summary + const template_contract: TalerMerchantApi.TemplateContractDetails = { + minimum_age: state.minimum_age!, + pay_duration: Duration.toTalerProtocolDuration(state.pay_duration!), + amount: contract_amount, + summary: contract_summary, + currency: + cList.length > 1 && state.currency_editable + ? undefined + : config.currency, + } return onCreate({ template_id: state.id!, template_description: state.description!, - template_contract: { - minimum_age: state.minimum_age!, - pay_duration: Duration.toTalerProtocolDuration(state.pay_duration!), - amount: state.amount_editable ? undefined : state.amount, - summary: state.summary_editable ? undefined : state.summary, - currency: - cList.length > 1 && state.currency_editable - ? undefined - : config.currency, - }, + template_contract, + required_currency: contract_amount !== undefined ? undefined : config.currency, editable_defaults: { - amount: !state.amount_editable ? undefined : state.amount, - summary: !state.summary_editable ? undefined : state.summary, + amount: !state.amount_editable ? undefined : (state.amount ?? zero), + summary: !state.summary_editable ? undefined : (state.summary ?? ""), currency: cList.length === 1 || !state.currency_editable ? undefined diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx index 9e59609c7..fce14dcc3 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx @@ -93,11 +93,16 @@ export default function ListTemplates({ /> <ListPage - templates={result.body} - onLoadMoreBefore={ - result.isFirstPage ? undefined: result.loadFirst - } - onLoadMoreAfter={result.isLastPage ? undefined : result.loadNext} + // templates={result.body} + // onLoadMoreBefore={ + // result.isFirstPage ? undefined: result.loadFirst + // } + // onLoadMoreAfter={result.isLastPage ? undefined : result.loadNext} + + templates={result.body.templates} + onLoadMoreBefore={undefined} + onLoadMoreAfter={undefined} + onCreate={onCreate} onSelect={(e) => { onSelect(e.template_id); diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx index 7322ca169..547996ea1 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx @@ -70,7 +70,8 @@ export function QrPage({ id: templateId, onBack }: Props): VNode { const payTemplateUri = stringifyPayTemplateUri({ merchantBaseUrl, templateId, - templateParams: {}, + // FIXME! + //templateParams: {}, }); return ( @@ -78,7 +79,7 @@ export function QrPage({ id: templateId, onBack }: Props): VNode { <section id="printThis"> <QR text={payTemplateUri} /> <pre style={{ textAlign: "center" }}> - <a href={payTemplateUri}>{payTemplateUri}</a> + <a target="_blank" rel="noreferrer" href={payTemplateUri}>{payTemplateUri}</a> </pre> </section> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx index eedb77f28..32c5637aa 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx @@ -51,7 +51,7 @@ type Entity = { description?: string; otpId?: string | null; summary?: string; - amount?: AmountString; + amount?: string; minimum_age?: number; pay_duration?: Duration; summary_editable?: boolean; @@ -68,7 +68,7 @@ interface Props { export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { const { i18n } = useTranslationContext(); const { config } = useSessionContext(); - const {state:session} = useSessionContext(); + const { state: session } = useSessionContext(); const [state, setState] = useState<Partial<Entity>>({ description: template.template_description, @@ -76,8 +76,8 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { otpId: template.otp_id, pay_duration: template.template_contract.pay_duration ? Duration.fromTalerProtocolDuration( - template.template_contract.pay_duration, - ) + template.template_contract.pay_duration, + ) : undefined, summary: template.editable_defaults?.summary ?? template.template_contract.summary, @@ -85,8 +85,8 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { template.editable_defaults?.amount ?? (template.template_contract.amount as AmountString | undefined), currency_editable: !!template.editable_defaults?.currency, - summary_editable: !!template.editable_defaults?.summary, - amount_editable: !!template.editable_defaults?.amount, + summary_editable: template.editable_defaults?.summary !== undefined, + amount_editable: template.editable_defaults?.amount !== undefined, }); function updateState(up: (s: Partial<Entity>) => Partial<Entity>) { @@ -117,11 +117,11 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { const errors: FormErrors<Entity> = { description: !state.description ? i18n.str`should not be empty` : undefined, amount: !state.amount - ? undefined + ? state.amount_editable ? undefined : i18n.str`required` : !parsedPrice ? i18n.str`not valid` : Amounts.isZero(parsedPrice) - ? i18n.str`must be greater than 0` + ? state.amount_editable ? undefined : i18n.str`must be greater than 0` : undefined, minimum_age: state.minimum_age && state.minimum_age < 0 @@ -142,23 +142,29 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { (k) => (errors as Record<string, unknown>)[k] !== undefined, ); + const zero = Amounts.stringify(Amounts.zeroOfCurrency(config.currency)) + const submitForm = () => { if (hasErrors) return Promise.reject(); + const contract_amount = state.amount_editable ? undefined : state.amount as AmountString + const contract_summary = state.summary_editable ? undefined : state.summary + const template_contract: TalerMerchantApi.TemplateContractDetails = { + minimum_age: state.minimum_age!, + pay_duration: Duration.toTalerProtocolDuration(state.pay_duration!), + amount: contract_amount, + summary: contract_summary, + currency: + cList.length > 1 && state.currency_editable + ? undefined + : config.currency, + } return onUpdate({ template_description: state.description!, - template_contract: { - minimum_age: state.minimum_age!, - pay_duration: Duration.toTalerProtocolDuration(state.pay_duration!), - amount: state.amount_editable ? undefined : state.amount, - summary: state.summary_editable ? undefined : state.summary, - currency: - cList.length > 1 && state.currency_editable - ? undefined - : config.currency, - }, + template_contract, + required_currency: contract_amount !== undefined ? undefined : config.currency, editable_defaults: { - amount: !state.amount_editable ? undefined : state.amount, - summary: !state.summary_editable ? undefined : state.summary, + amount: !state.amount_editable ? undefined : (state.amount ?? zero), + summary: !state.summary_editable ? undefined : (state.summary ?? ""), currency: cList.length === 1 || !state.currency_editable ? undefined diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx index 360c9d373..5b1404b55 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx @@ -19,9 +19,9 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { TalerMerchantApi } from "@gnu-taler/taler-util"; +import { AmountString, TalerMerchantApi } from "@gnu-taler/taler-util"; import { useTranslationContext } from "@gnu-taler/web-util/browser"; -import { h, VNode } from "preact"; +import { VNode, h } from "preact"; import { useState } from "preact/hooks"; import { AsyncButton } from "../../../../components/exception/AsyncButton.js"; import { @@ -44,20 +44,19 @@ export function UsePage({ id, template, onCreateOrder, onBack }: Props): VNode { const { i18n } = useTranslationContext(); const [state, setState] = useState<Partial<Entity>>({ - currency: template.editable_defaults?.currency ?? template.template_contract.currency, - amount: template.editable_defaults?.amount ?? template.template_contract.amount, - summary: template.editable_defaults?.summary ?? template.template_contract.summary, + currency: + template.editable_defaults?.currency ?? + template.template_contract.currency, + // FIXME: Add additional check here, editable default might be a plain string! + amount: (template.editable_defaults?.amount ?? + template.template_contract.amount) as AmountString, + summary: + template.editable_defaults?.summary ?? template.template_contract.summary, }); const errors: FormErrors<Entity> = { - amount: - !state.amount - ? i18n.str`Amount is required` - : undefined, - summary: - !state.summary - ? i18n.str`Order summary is required` - : undefined, + amount: !state.amount ? i18n.str`Amount is required` : undefined, + summary: !state.summary ? i18n.str`Order summary is required` : undefined, }; const hasErrors = Object.keys(errors).some( |