diff options
author | Sebastian <sebasjm@gmail.com> | 2024-02-05 16:23:09 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2024-02-05 16:23:09 -0300 |
commit | 46aa042f9acb940660f7a53b4824b1d6fb2ad8b3 (patch) | |
tree | e8b03acb195a2161aa0a0e68435b07de352a4477 | |
parent | f68585db5f9ba0f760e22dada474fd7ec2847796 (diff) | |
download | wallet-core-46aa042f9acb940660f7a53b4824b1d6fb2ad8b3.tar.gz wallet-core-46aa042f9acb940660f7a53b4824b1d6fb2ad8b3.tar.bz2 wallet-core-46aa042f9acb940660f7a53b4824b1d6fb2ad8b3.zip |
fixes #8294
25 files changed, 327 insertions, 179 deletions
diff --git a/packages/demobank-ui/src/Routing.tsx b/packages/demobank-ui/src/Routing.tsx index 409d4ec2d..9f9475210 100644 --- a/packages/demobank-ui/src/Routing.tsx +++ b/packages/demobank-ui/src/Routing.tsx @@ -164,6 +164,7 @@ function PublicRounting({ return ( <WithdrawalOperationPage operationId={wopid} + pupose="after-confirmation" onOperationAborted={() => navigateTo(publicPages.login.url({}))} routeClose={publicPages.login} onAuthorizationRequired={() => @@ -242,6 +243,10 @@ export const privatePages = { /\/profile\/(?<account>[a-zA-Z0-9]+)\/cashouts/, ({ account }) => `#/profile/${account}/cashouts`, ), + startOperation: urlPattern<{ wopid: string }>( + /\/start-operation\/(?<wopid>[a-zA-Z0-9-]+)/, + ({ wopid }) => `#/start-operation/${wopid}`, + ), operationDetails: urlPattern<{ wopid: string }>( /\/operation\/(?<wopid>[a-zA-Z0-9-]+)/, ({ wopid }) => `#/operation/${wopid}`, @@ -277,6 +282,25 @@ function PrivateRouting({ return ( <WithdrawalOperationPage operationId={wopid} + pupose="after-confirmation" + onOperationAborted={() => navigateTo(privatePages.home.url({}))} + routeClose={privatePages.home} + onAuthorizationRequired={() => + navigateTo(privatePages.solveSecondFactor.url({})) + } + /> + ); + } + case "startOperation": { + const { wopid } = location.values as RouteParamsType< + typeof location.parent, + typeof location.name + >; + + return ( + <WithdrawalOperationPage + operationId={wopid} + pupose="after-creation" onOperationAborted={() => navigateTo(privatePages.home.url({}))} routeClose={privatePages.home} onAuthorizationRequired={() => @@ -316,6 +340,10 @@ function PrivateRouting({ <ShowAccountDetails account={account} onUpdateSuccess={() => navigateTo(privatePages.home.url({}))} + routeMyAccountCashout={privatePages.myAccountCashouts} + routeMyAccountDelete={privatePages.myAccountDelete} + routeMyAccountDetails={privatePages.myAccountDetails} + routeMyAccountPassword={privatePages.myAccountPassword} onAuthorizationRequired={() => navigateTo(privatePages.solveSecondFactor.url({})) } @@ -333,6 +361,10 @@ function PrivateRouting({ focus account={account} onUpdateSuccess={() => navigateTo(privatePages.home.url({}))} + routeMyAccountCashout={privatePages.myAccountCashouts} + routeMyAccountDelete={privatePages.myAccountDelete} + routeMyAccountDetails={privatePages.myAccountDetails} + routeMyAccountPassword={privatePages.myAccountPassword} onAuthorizationRequired={() => navigateTo(privatePages.solveSecondFactor.url({})) } @@ -366,6 +398,10 @@ function PrivateRouting({ account={account} routeCashoutDetails={privatePages.cashoutDetails} routeClose={privatePages.home} + routeMyAccountCashout={privatePages.myAccountCashouts} + routeMyAccountDelete={privatePages.myAccountDelete} + routeMyAccountDetails={privatePages.myAccountDetails} + routeMyAccountPassword={privatePages.myAccountPassword} onAuthorizationRequired={() => navigateTo(privatePages.solveSecondFactor.url({})) } @@ -389,6 +425,10 @@ function PrivateRouting({ <ShowAccountDetails account={username} onUpdateSuccess={() => navigateTo(privatePages.home.url({}))} + routeMyAccountCashout={privatePages.myAccountCashouts} + routeMyAccountDelete={privatePages.myAccountDelete} + routeMyAccountDetails={privatePages.myAccountDetails} + routeMyAccountPassword={privatePages.myAccountPassword} onAuthorizationRequired={() => navigateTo(privatePages.solveSecondFactor.url({})) } @@ -402,6 +442,10 @@ function PrivateRouting({ focus account={username} onUpdateSuccess={() => navigateTo(privatePages.home.url({}))} + routeMyAccountCashout={privatePages.myAccountCashouts} + routeMyAccountDelete={privatePages.myAccountDelete} + routeMyAccountDetails={privatePages.myAccountDetails} + routeMyAccountPassword={privatePages.myAccountPassword} onAuthorizationRequired={() => navigateTo(privatePages.solveSecondFactor.url({})) } @@ -414,6 +458,10 @@ function PrivateRouting({ <CashoutListForAccount account={username} routeCashoutDetails={privatePages.cashoutDetails} + routeMyAccountCashout={privatePages.myAccountCashouts} + routeMyAccountDelete={privatePages.myAccountDelete} + routeMyAccountDetails={privatePages.myAccountDetails} + routeMyAccountPassword={privatePages.myAccountPassword} onAuthorizationRequired={() => navigateTo(privatePages.solveSecondFactor.url({})) } @@ -433,6 +481,8 @@ function PrivateRouting({ routeShowAccount={privatePages.accountDetails} routeShowCashoutsAccount={privatePages.accountCashouts} routeUpdatePasswordAccount={privatePages.accountChangePassword} + routeCreateWireTransfer={privatePages.wireTranserCreate} + routeDownloadStats={privatePages.statsDownload} /> ); } @@ -440,15 +490,19 @@ function PrivateRouting({ <AccountPage account={username} tab={undefined} + routeCreateWireTransfer={privatePages.wireTranserCreate} + routePublicAccounts={privatePages.publicAccountList} + routeOperationDetails={privatePages.startOperation} routeChargeWallet={privatePages.homeChargeWallet} routeWireTransfer={privatePages.homeWireTransfer} + routeSolveSecondFactor={privatePages.solveSecondFactor} routeClose={privatePages.home} onClose={() => navigateTo(privatePages.home.url({}))} onAuthorizationRequired={() => navigateTo(privatePages.solveSecondFactor.url({})) } onOperationCreated={(wopid) => - navigateTo(privatePages.operationDetails.url({ wopid })) + navigateTo(privatePages.startOperation.url({ wopid })) } /> ); @@ -499,13 +553,17 @@ function PrivateRouting({ tab="charge-wallet" routeChargeWallet={privatePages.homeChargeWallet} routeWireTransfer={privatePages.homeWireTransfer} + routeCreateWireTransfer={privatePages.wireTranserCreate} + routePublicAccounts={privatePages.publicAccountList} + routeOperationDetails={privatePages.startOperation} + routeSolveSecondFactor={privatePages.solveSecondFactor} routeClose={privatePages.home} onClose={() => navigateTo(privatePages.home.url({}))} onAuthorizationRequired={() => navigateTo(privatePages.solveSecondFactor.url({})) } onOperationCreated={(wopid) => - navigateTo(privatePages.operationDetails.url({ wopid })) + navigateTo(privatePages.startOperation.url({ wopid })) } /> ); @@ -517,13 +575,17 @@ function PrivateRouting({ tab="wire-transfer" routeChargeWallet={privatePages.homeChargeWallet} routeWireTransfer={privatePages.homeWireTransfer} + routeCreateWireTransfer={privatePages.wireTranserCreate} + routePublicAccounts={privatePages.publicAccountList} + routeOperationDetails={privatePages.startOperation} + routeSolveSecondFactor={privatePages.solveSecondFactor} routeClose={privatePages.home} onClose={() => navigateTo(privatePages.home.url({}))} onAuthorizationRequired={() => navigateTo(privatePages.solveSecondFactor.url({})) } onOperationCreated={(wopid) => - navigateTo(privatePages.operationDetails.url({ wopid })) + navigateTo(privatePages.startOperation.url({ wopid })) } /> ); diff --git a/packages/demobank-ui/src/components/Transactions/index.ts b/packages/demobank-ui/src/components/Transactions/index.ts index b0e67d4d9..f4e799839 100644 --- a/packages/demobank-ui/src/components/Transactions/index.ts +++ b/packages/demobank-ui/src/components/Transactions/index.ts @@ -19,9 +19,11 @@ import { Loading, utils } from "@gnu-taler/web-util/browser"; import { ErrorLoadingWithDebug } from "../ErrorLoadingWithDebug.js"; import { useComponentState } from "./state.js"; import { ReadyView } from "./views.js"; +import { RouteDefinition } from "../../route.js"; export interface Props { account: string; + routeCreateWireTransfer: RouteDefinition<{ destination: string }> | undefined; } export type State = State.Loading | State.LoadingUriError | State.Ready; @@ -43,6 +45,7 @@ export namespace State { export interface Ready extends BaseInfo { status: "ready"; error: undefined; + routeCreateWireTransfer: RouteDefinition<{ destination: string }> | undefined; transactions: Transaction[]; onPrev?: () => void; onNext?: () => void; diff --git a/packages/demobank-ui/src/components/Transactions/state.ts b/packages/demobank-ui/src/components/Transactions/state.ts index 74e6b0d36..5e99a8a76 100644 --- a/packages/demobank-ui/src/components/Transactions/state.ts +++ b/packages/demobank-ui/src/components/Transactions/state.ts @@ -23,7 +23,7 @@ import { import { useTransactions } from "../../hooks/access.js"; import { Props, State, Transaction } from "./index.js"; -export function useComponentState({ account }: Props): State { +export function useComponentState({ account, routeCreateWireTransfer }: Props): State { const result = useTransactions(account); if (!result) { return { @@ -42,38 +42,39 @@ export function useComponentState({ account }: Props): State { result.data.type === "fail" ? [] : result.data.body.transactions - .map((tx) => { - const negative = tx.direction === "debit"; - const cp = parsePaytoUri( - negative ? tx.creditor_payto_uri : tx.debtor_payto_uri, - ); - const counterpart = - (cp === undefined || !cp.isKnown - ? undefined - : cp.targetType === "iban" - ? cp.iban - : cp.targetType === "x-taler-bank" - ? cp.account - : cp.targetType === "bitcoin" - ? `${cp.targetPath.substring(0, 6)}...` - : undefined) ?? "unknown"; + .map((tx) => { + const negative = tx.direction === "debit"; + const cp = parsePaytoUri( + negative ? tx.creditor_payto_uri : tx.debtor_payto_uri, + ); + const counterpart = + (cp === undefined || !cp.isKnown + ? undefined + : cp.targetType === "iban" + ? cp.iban + : cp.targetType === "x-taler-bank" + ? cp.account + : cp.targetType === "bitcoin" + ? `${cp.targetPath.substring(0, 6)}...` + : undefined) ?? "unknown"; - const when = AbsoluteTime.fromProtocolTimestamp(tx.date); - const amount = Amounts.parse(tx.amount); - const subject = tx.subject; - return { - negative, - counterpart, - when, - amount, - subject, - }; - }) - .filter((x): x is Transaction => x !== undefined); + const when = AbsoluteTime.fromProtocolTimestamp(tx.date); + const amount = Amounts.parse(tx.amount); + const subject = tx.subject; + return { + negative, + counterpart, + when, + amount, + subject, + }; + }) + .filter((x): x is Transaction => x !== undefined); return { status: "ready", error: undefined, + routeCreateWireTransfer, transactions, onNext: result.isLastPage ? undefined : result.loadMore, onPrev: result.isFirstPage ? undefined : result.loadMorePrev, diff --git a/packages/demobank-ui/src/components/Transactions/test.ts b/packages/demobank-ui/src/components/Transactions/test.ts index cf33a0b1c..9ded218c1 100644 --- a/packages/demobank-ui/src/components/Transactions/test.ts +++ b/packages/demobank-ui/src/components/Transactions/test.ts @@ -33,6 +33,7 @@ describe("Transaction states", () => { const props: Props = { account: "myAccount", + routeCreateWireTransfer: undefined, }; env.addRequestExpectation(TRANSACTION_API_EXAMPLE.LIST_FIRST_PAGE, { @@ -161,6 +162,7 @@ describe("Transaction states", () => { const props: Props = { account: "myAccount", + routeCreateWireTransfer: undefined, }; env.addRequestExpectation(TRANSACTION_API_EXAMPLE.LIST_ERROR, { diff --git a/packages/demobank-ui/src/components/Transactions/views.tsx b/packages/demobank-ui/src/components/Transactions/views.tsx index 51fb90b61..53e437523 100644 --- a/packages/demobank-ui/src/components/Transactions/views.tsx +++ b/packages/demobank-ui/src/components/Transactions/views.tsx @@ -20,10 +20,10 @@ import { Fragment, h, VNode } from "preact"; import { useBankCoreApiContext } from "../../context/config.js"; import { RenderAmount } from "../../pages/PaytoWireTransferForm.js"; import { State } from "./index.js"; -import { privatePages } from "../../Routing.js"; export function ReadyView({ transactions, + routeCreateWireTransfer, onNext, onPrev, }: State.Ready): VNode { @@ -93,8 +93,8 @@ export function ReadyView({ item.when.t_ms === "never" ? "" : format(item.when.t_ms, "HH:mm:ss", { - locale: dateLocale, - }); + locale: dateLocale, + }); return ( <tr key={idx} @@ -134,14 +134,16 @@ export function ReadyView({ </dt> <dd class="mt-1 truncate text-gray-500 sm:hidden"> {item.negative ? i18n.str`to` : i18n.str`from`}{" "} - <a - href={privatePages.wireTranserCreate.url({ - destination: item.counterpart, - })} - class="text-indigo-600 hover:text-indigo-900" - > - {item.counterpart} - </a> + {!routeCreateWireTransfer ? item.counterpart : + <a + href={routeCreateWireTransfer.url({ + destination: item.counterpart, + })} + class="text-indigo-600 hover:text-indigo-900" + > + {item.counterpart} + </a> + } </dd> <dd class="mt-1 text-gray-500 sm:hidden"> <pre class="break-words w-56 whitespace-break-spaces p-2 rounded-md mx-auto my-2 bg-gray-100"> @@ -168,14 +170,16 @@ export function ReadyView({ )} </td> <td class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500"> - <a - href={privatePages.wireTranserCreate.url({ - destination: item.counterpart, - })} - class="text-indigo-600 hover:text-indigo-900" - > - {item.counterpart} - </a> + {!routeCreateWireTransfer ? item.counterpart : + <a + href={routeCreateWireTransfer.url({ + destination: item.counterpart, + })} + class="text-indigo-600 hover:text-indigo-900" + > + {item.counterpart} + </a> + } </td> <td class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500 break-all min-w-md"> {item.subject} diff --git a/packages/demobank-ui/src/i18n/en.po b/packages/demobank-ui/src/i18n/en.po index 636863b6f..a9657bd32 100644 --- a/packages/demobank-ui/src/i18n/en.po +++ b/packages/demobank-ui/src/i18n/en.po @@ -88,7 +88,7 @@ msgstr "" #: src/hooks/preferences.ts:55 #, fuzzy, c-format msgid "Max withdrawal amount" -msgstr "Start withdrawal" +msgstr "" #: src/hooks/preferences.ts:57 #, c-format @@ -108,7 +108,7 @@ msgstr "" #: src/hooks/preferences.ts:63 #, fuzzy, c-format msgid "Use fast withdrawal form" -msgstr "Start withdrawal" +msgstr "" #: src/hooks/preferences.ts:65 #, c-format @@ -244,7 +244,7 @@ msgstr "" #: src/pages/PaytoWireTransferForm.tsx:415 #, fuzzy, c-format msgid "amount to transfer" -msgstr "Amount to withdraw" +msgstr "" #: src/pages/PaytoWireTransferForm.tsx:425 #, c-format @@ -422,7 +422,7 @@ msgstr "" #: src/pages/WithdrawalConfirmationQuestion.tsx:186 #, fuzzy, c-format msgid "Confirm the withdrawal operation" -msgstr "Confirm withdrawal" +msgstr "" #: src/pages/WithdrawalConfirmationQuestion.tsx:203 #, c-format @@ -486,7 +486,7 @@ msgstr "" #: src/pages/OperationState/views.tsx:319 #, c-format msgid "Close" -msgstr "Close" +msgstr "" #: src/pages/OperationState/views.tsx:399 #, c-format @@ -524,7 +524,7 @@ msgstr "" #: src/pages/WalletWithdrawForm.tsx:75 #, fuzzy, c-format msgid "Complete or cancel the operation in" -msgstr "Confirm withdrawal" +msgstr "" #: src/pages/WalletWithdrawForm.tsx:84 #, c-format @@ -544,7 +544,7 @@ msgstr "" #: src/pages/WalletWithdrawForm.tsx:117 #, fuzzy, c-format msgid "Withdraw URI: %1$s" -msgstr "Confirm withdrawal" +msgstr "" #: src/pages/WalletWithdrawForm.tsx:132 #, c-format @@ -571,7 +571,7 @@ msgstr "" #: src/pages/WalletWithdrawForm.tsx:295 #, fuzzy, c-format msgid "You need a GNU Taler Wallet" -msgstr "Top up Taler wallet" +msgstr "" #: src/pages/WalletWithdrawForm.tsx:300 #, c-format @@ -611,7 +611,7 @@ msgstr "" #: src/pages/PaymentOptions.tsx:171 #, fuzzy, c-format msgid "Transfer details" -msgstr "Top up Taler wallet" +msgstr "" #: src/pages/AccountPage/views.tsx:41 #, c-format @@ -979,7 +979,7 @@ msgstr "" #: src/pages/QrCodeSection.tsx:143 #, fuzzy, c-format msgid "Withdraw" -msgstr "Confirm withdrawal" +msgstr "" #: src/pages/QrCodeSection.tsx:152 #, c-format @@ -989,7 +989,7 @@ msgstr "" #: src/pages/QrCodeSection.tsx:157 #, fuzzy, c-format msgid "Scan the QR below to start the withdrawal." -msgstr "Close Taler withdrawal" +msgstr "" #: src/pages/WithdrawalQRCode.tsx:79 #, c-format @@ -1123,12 +1123,12 @@ msgstr "" #: src/pages/SolveChallengePage.tsx:232 #, fuzzy, c-format msgid "Withdrawal" -msgstr "Confirm withdrawal" +msgstr "" #: src/pages/SolveChallengePage.tsx:248 #, fuzzy, c-format msgid "Confirm the operation" -msgstr "Confirm withdrawal" +msgstr "" #: src/pages/SolveChallengePage.tsx:271 #, c-format @@ -1306,12 +1306,12 @@ msgstr "" #: src/pages/business/CreateCashout.tsx:440 #, fuzzy, c-format msgid "Amount to send" -msgstr "Amount to withdraw" +msgstr "" #: src/pages/business/CreateCashout.tsx:441 #, fuzzy, c-format msgid "Amount to receive" -msgstr "Amount to withdraw" +msgstr "" #: src/pages/business/CreateCashout.tsx:490 #, c-format @@ -1749,36 +1749,36 @@ msgstr "" #, c-format #~ msgid "days" -#~ msgstr "days" +#~ msgstr "" #, c-format #~ msgid "hours" -#~ msgstr "hours" +#~ msgstr "" #, c-format #~ msgid "minutes" -#~ msgstr "minutes" +#~ msgstr "" #, c-format #~ msgid "seconds" -#~ msgstr "seconds" +#~ msgstr "" #~ msgid "Go back" -#~ msgstr "Go back" +#~ msgstr "" #, fuzzy #~ msgid "Withdraw Money into a Taler wallet" -#~ msgstr "Top up Taler wallet" +#~ msgstr "" #~ msgid "Page has a problem: logged in but backend state is lost." -#~ msgstr "Page has a problem: logged in but backend state is lost." +#~ msgstr "" #, fuzzy #~ msgid "Welcome to the euFin bank!" -#~ msgstr "Welcome to euFin bank: Taler+IBAN now possible!" +#~ msgstr "" #~ msgid "Page has a problem:" -#~ msgstr "Page has a problem:" +#~ msgstr "" #~ msgid "Sign in" -#~ msgstr "Sign in" +#~ msgstr "" diff --git a/packages/demobank-ui/src/i18n/strings.ts b/packages/demobank-ui/src/i18n/strings.ts index fbd1acb35..f55e5efbc 100644 --- a/packages/demobank-ui/src/i18n/strings.ts +++ b/packages/demobank-ui/src/i18n/strings.ts @@ -1505,11 +1505,11 @@ strings["en"] = { "IBAN numbers usually have less that 34 digits": [""], "IBAN country code not found": [""], "IBAN number is not valid, checksum is wrong": [""], - "Max withdrawal amount": ["Start withdrawal"], + "Max withdrawal amount": [""], "Show withdrawal confirmation": [""], "Show demo description": [""], "Show install wallet first": [""], - "Use fast withdrawal form": ["Start withdrawal"], + "Use fast withdrawal form": [""], "Show debug info": [""], "The reserve operation has been confirmed previously and can't be aborted": [""], @@ -1519,9 +1519,9 @@ strings["en"] = { "You will see the details of the operation in your wallet including the fees (if applies). If you still don't have one you can install it following instructions in": [""], "this page": [""], - Withdraw: ["Confirm withdrawal"], + Withdraw: [""], "Or if you have the wallet in another device": [""], - "Scan the QR below to start the withdrawal.": ["Close Taler withdrawal"], + "Scan the QR below to start the withdrawal.": [""], required: [""], "IBAN should have just uppercased letters and numbers": [""], "not valid": [""], @@ -1550,7 +1550,7 @@ strings["en"] = { subject: [""], "some text to identify the transfer": [""], Amount: [""], - "amount to transfer": ["Amount to withdraw"], + "amount to transfer": [""], "payto URI:": [""], "uniform resource identifier of the target account": [""], "payto://iban/[receiver-iban]?message=[subject]&amount=[%1$s:X.Y]": [""], @@ -1572,7 +1572,7 @@ strings["en"] = { "The withdrawal operation can't be confirmed before a wallet accepted the transaction.": [""], "Your balance is not enough for the operation.": [""], - "Confirm the withdrawal operation": ["Confirm withdrawal"], + "Confirm the withdrawal operation": [""], "Wire transfer details": [""], "Taler Exchange operator's account": [""], "Taler Exchange operator's name": [""], @@ -1681,8 +1681,8 @@ strings["en"] = { "To account": [""], "No cashout account": [""], "Before doing a cashout you need to complete your profile": [""], - "Amount to send": ["Amount to withdraw"], - "Amount to receive": ["Amount to withdraw"], + "Amount to send": [""], + "Amount to receive": [""], "Total cost": [""], "Balance left": [""], "Before fee": [""], @@ -1808,7 +1808,7 @@ strings["en"] = { [""], "The operation was rejected due to insufficient funds.": [""], "Do not show this again": [""], - Close: ["Close"], + Close: [""], "On this device": [""], 'If you are using a web browser on desktop you should access your wallet with the GNU Taler WebExtension now or click the link if your WebExtension have the "Inject Taler support" option enabled.': [""], @@ -1816,14 +1816,14 @@ strings["en"] = { "On a mobile phone": [""], "Scan the QR code with your mobile device.": [""], "There is an operation already": [""], - "Complete or cancel the operation in": ["Confirm withdrawal"], + "Complete or cancel the operation in": [""], "Server responded with an invalid withdraw URI": [""], - "Withdraw URI: %1$s": ["Confirm withdrawal"], + "Withdraw URI: %1$s": [""], "The operation was rejected due to insufficient funds": [""], "Prepare your wallet": [""], "After using your wallet you will need to confirm or cancel the operation on this site.": [""], - "You need a GNU Taler Wallet": ["Top up Taler wallet"], + "You need a GNU Taler Wallet": [""], "If you don't have one yet you can follow the instruction in": [""], "Send money": [""], "to a %1$s wallet": [""], @@ -1835,7 +1835,7 @@ strings["en"] = { "Make a wire transfer to an account with known bank account number.": [ "", ], - "Transfer details": ["Top up Taler wallet"], + "Transfer details": [""], "This is a demo bank": [""], "This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some %1$s.": [""], @@ -1871,8 +1871,8 @@ strings["en"] = { "Account update": [""], "Password update": [""], "Wire transfer": [""], - Withdrawal: ["Confirm withdrawal"], - "Confirm the operation": ["Confirm withdrawal"], + Withdrawal: [""], + "Confirm the operation": [""], "Send again": [""], "Send code": [""], "Operation details": [""], diff --git a/packages/demobank-ui/src/pages/AccountPage/index.ts b/packages/demobank-ui/src/pages/AccountPage/index.ts index 31a8a9e34..6c67f6d90 100644 --- a/packages/demobank-ui/src/pages/AccountPage/index.ts +++ b/packages/demobank-ui/src/pages/AccountPage/index.ts @@ -36,6 +36,10 @@ export interface Props { routeClose: RouteDefinition<Record<string, never>>; routeChargeWallet: RouteDefinition<Record<string, never>>; routeWireTransfer: RouteDefinition<Record<string, never>>; + routePublicAccounts: RouteDefinition<Record<string, never>>; + routeCreateWireTransfer: RouteDefinition<{ destination: string }>; + routeOperationDetails: RouteDefinition<{ wopid: string }>; + routeSolveSecondFactor: RouteDefinition<Record<string, never>>; } export type State = @@ -72,6 +76,10 @@ export namespace State { routeClose: RouteDefinition<Record<string, never>>; routeChargeWallet: RouteDefinition<Record<string, never>>; routeWireTransfer: RouteDefinition<Record<string, never>>; + routePublicAccounts: RouteDefinition<Record<string, never>>; + routeCreateWireTransfer: RouteDefinition<{ destination: string }>; + routeOperationDetails: RouteDefinition<{ wopid: string }>; + routeSolveSecondFactor: RouteDefinition<Record<string, never>>; } export interface InvalidIban { diff --git a/packages/demobank-ui/src/pages/AccountPage/state.ts b/packages/demobank-ui/src/pages/AccountPage/state.ts index a07ea37d3..58da82f80 100644 --- a/packages/demobank-ui/src/pages/AccountPage/state.ts +++ b/packages/demobank-ui/src/pages/AccountPage/state.ts @@ -28,6 +28,10 @@ export function useComponentState({ account, tab, routeChargeWallet, + routeCreateWireTransfer, + routePublicAccounts, + routeSolveSecondFactor, + routeOperationDetails, routeWireTransfer, onOperationCreated, onClose, @@ -96,6 +100,10 @@ export function useComponentState({ onOperationCreated, error: undefined, tab, + routeOperationDetails, + routeCreateWireTransfer, + routePublicAccounts, + routeSolveSecondFactor, onAuthorizationRequired, onClose, routeClose, diff --git a/packages/demobank-ui/src/pages/AccountPage/views.tsx b/packages/demobank-ui/src/pages/AccountPage/views.tsx index 9baefe96c..7694ca1d3 100644 --- a/packages/demobank-ui/src/pages/AccountPage/views.tsx +++ b/packages/demobank-ui/src/pages/AccountPage/views.tsx @@ -22,7 +22,7 @@ import { useBankState } from "../../hooks/bank-state.js"; import { usePreferences } from "../../hooks/preferences.js"; import { PaymentOptions } from "../PaymentOptions.js"; import { State } from "./index.js"; -import { privatePages } from "../../Routing.js"; +import { RouteDefinition } from "../../route.js"; export function InvalidIbanView({ error }: State.InvalidIban) { return ( @@ -32,7 +32,9 @@ export function InvalidIbanView({ error }: State.InvalidIban) { const IS_PUBLIC_ACCOUNT_ENABLED = false; -function ShowDemoInfo(): VNode { +function ShowDemoInfo({ routePublicAccounts }: { + routePublicAccounts: RouteDefinition<Record<string, never>>; +}): VNode { const { i18n } = useTranslationContext(); const [settings, updateSettings] = usePreferences(); if (!settings.showDemoDescription) return <Fragment />; @@ -48,7 +50,7 @@ function ShowDemoInfo(): VNode { This part of the demo shows how a bank that supports Taler directly would work. In addition to using your own bank account, you can also see the transaction history of some{" "} - <a href={privatePages.publicAccountList.url({})}>Public Accounts</a>. + <a href={routePublicAccounts.url({})}>Public Accounts</a>. </i18n.Translate> ) : ( <i18n.Translate> @@ -60,7 +62,9 @@ function ShowDemoInfo(): VNode { ); } -function ShowPedingOperation(): VNode { +function ShowPedingOperation({ routeSolveSecondFactor }: { + routeSolveSecondFactor: RouteDefinition<Record<string, never>>; +}): VNode { const { i18n } = useTranslationContext(); const [bankState, updateBankState] = useBankState(); if (!bankState.currentChallenge) return <Fragment />; @@ -93,7 +97,7 @@ function ShowPedingOperation(): VNode { </i18n.Translate>{" "} <a class="font-semibold text-yellow-700 hover:text-yellow-600" - href={`#/2fa`} + href={routeSolveSecondFactor.url({})} > <i18n.Translate>this page</i18n.Translate> </a> @@ -107,6 +111,10 @@ export function ReadyView({ routeChargeWallet, routeWireTransfer, limit, + routeCreateWireTransfer, + routePublicAccounts, + routeOperationDetails, + routeSolveSecondFactor, onClose, routeClose, onOperationCreated, @@ -114,10 +122,11 @@ export function ReadyView({ }: State.Ready): VNode { return ( <Fragment> - <ShowPedingOperation /> - <ShowDemoInfo /> + <ShowPedingOperation routeSolveSecondFactor={routeSolveSecondFactor} /> + <ShowDemoInfo routePublicAccounts={routePublicAccounts} /> <PaymentOptions tab={tab} + routeOperationDetails={routeOperationDetails} routeChargeWallet={routeChargeWallet} routeWireTransfer={routeWireTransfer} limit={limit} @@ -126,7 +135,7 @@ export function ReadyView({ onOperationCreated={onOperationCreated} onAuthorizationRequired={onAuthorizationRequired} /> - <Transactions account={account} /> + <Transactions account={account} routeCreateWireTransfer={routeCreateWireTransfer} /> </Fragment> ); } diff --git a/packages/demobank-ui/src/pages/BankFrame.tsx b/packages/demobank-ui/src/pages/BankFrame.tsx index d6ab882f1..f16e0e9bf 100644 --- a/packages/demobank-ui/src/pages/BankFrame.tsx +++ b/packages/demobank-ui/src/pages/BankFrame.tsx @@ -26,7 +26,6 @@ import { } from "@gnu-taler/web-util/browser"; import { ComponentChildren, VNode, h } from "preact"; import { useEffect, useErrorBoundary } from "preact/hooks"; -import { privatePages } from "../Routing.js"; import { useBankCoreApiContext } from "../context/config.js"; import { useSettingsContext } from "../context/settings.js"; import { useAccountDetails } from "../hooks/access.js"; @@ -38,6 +37,7 @@ import { usePreferences, } from "../hooks/preferences.js"; import { RenderAmount } from "./PaytoWireTransferForm.js"; +import { RouteDefinition } from "../route.js"; const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined; const VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : undefined; @@ -45,8 +45,10 @@ const VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : undefined; export function BankFrame({ children, account, + routeAccountDetails, }: { account?: string; + routeAccountDetails?: RouteDefinition<Record<string, never>>; children: ComponentChildren; }): VNode { const { i18n } = useTranslationContext(); @@ -86,9 +88,9 @@ export function BankFrame({ backend.state.status !== "loggedIn" ? undefined : () => { - backend.logOut(); - resetBankState(); - } + backend.logOut(); + resetBankState(); + } } sites={ !settings.topNavSites ? [] : Object.entries(settings.topNavSites) @@ -143,12 +145,12 @@ export function BankFrame({ <GlobalNotificationsBanner /> <main class="-mt-32 flex-1"> - {account && ( + {account && routeAccountDetails && ( <header class="py-5 bg-indigo-600 "> <div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8"> <h1 class=" flex flex-wrap items-center justify-between sm:flex-nowrap"> <span class="text-2xl font-bold tracking-tight text-white"> - <WelcomeAccount account={account} /> + <WelcomeAccount account={account} routeAccountDetails={routeAccountDetails} /> </span> <span class="text-2xl font-bold tracking-tight text-white"> <AccountBalance account={account} /> @@ -174,7 +176,10 @@ export function BankFrame({ ); } -function WelcomeAccount({ account }: { account: string }): VNode { +function WelcomeAccount({ account, routeAccountDetails }: { + account: string, + routeAccountDetails: RouteDefinition<Record<string, never>>; +}): VNode { const { i18n } = useTranslationContext(); const result = useAccountDetails(account); if (!result) { @@ -186,7 +191,7 @@ function WelcomeAccount({ account }: { account: string }): VNode { if (result.type === "fail") { return ( <a - href={privatePages.myAccountDetails.url({})} + href={routeAccountDetails.url({})} class="underline underline-offset-2" > <i18n.Translate>Welcome</i18n.Translate> @@ -195,7 +200,7 @@ function WelcomeAccount({ account }: { account: string }): VNode { } return ( <a - href={privatePages.myAccountDetails.url({})} + href={routeAccountDetails.url({})} class="underline underline-offset-2" > <i18n.Translate> diff --git a/packages/demobank-ui/src/pages/OperationState/views.tsx b/packages/demobank-ui/src/pages/OperationState/views.tsx index dbd8e9b77..40d974a17 100644 --- a/packages/demobank-ui/src/pages/OperationState/views.tsx +++ b/packages/demobank-ui/src/pages/OperationState/views.tsx @@ -392,10 +392,7 @@ export function ReadyView({ <div class="max-w-xl text-sm text-gray-500"> <p> <i18n.Translate> - If you are using a web browser on desktop you should access - your wallet with the GNU Taler WebExtension now or click the - link if your WebExtension have the "Inject Taler support" - option enabled. + If you are using a web browser on desktop you can also </i18n.Translate> </p> </div> diff --git a/packages/demobank-ui/src/pages/PaymentOptions.tsx b/packages/demobank-ui/src/pages/PaymentOptions.tsx index eb21f637a..39b31a094 100644 --- a/packages/demobank-ui/src/pages/PaymentOptions.tsx +++ b/packages/demobank-ui/src/pages/PaymentOptions.tsx @@ -74,6 +74,7 @@ export function PaymentOptions({ limit, onOperationCreated, onClose, + routeOperationDetails, onAuthorizationRequired, }: { limit: AmountJson; @@ -81,6 +82,8 @@ export function PaymentOptions({ onAuthorizationRequired: () => void; onOperationCreated: (wopid: string) => void; onClose: () => void; + + routeOperationDetails: RouteDefinition<{ wopid: string }>; routeClose: RouteDefinition<Record<string, never>>; routeChargeWallet: RouteDefinition<Record<string, never>>; routeWireTransfer: RouteDefinition<Record<string, never>>; @@ -111,7 +114,7 @@ export function PaymentOptions({ <div class="text-4xl mr-4 my-auto">💵</div> <span class="grow self-center text-lg text-gray-900 align-middle text-center"> <i18n.Translate> - to a <b>Taler</b> wallet + to a Taler wallet </i18n.Translate> </span> <svg @@ -196,6 +199,7 @@ export function PaymentOptions({ </div> {tab === "charge-wallet" && ( <WalletWithdrawForm + routeOperationDetails={routeOperationDetails} focus limit={limit} onAuthorizationRequired={onAuthorizationRequired} diff --git a/packages/demobank-ui/src/pages/ProfileNavigation.tsx b/packages/demobank-ui/src/pages/ProfileNavigation.tsx index 607487c9d..94669584a 100644 --- a/packages/demobank-ui/src/pages/ProfileNavigation.tsx +++ b/packages/demobank-ui/src/pages/ProfileNavigation.tsx @@ -15,16 +15,24 @@ */ import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { VNode, h } from "preact"; -import { privatePages } from "../Routing.js"; import { useBankCoreApiContext } from "../context/config.js"; import { useBackendState } from "../hooks/backend.js"; import { assertUnreachable } from "@gnu-taler/taler-util"; import { useNavigationContext } from "../context/navigation.js"; +import { RouteDefinition } from "../route.js"; export function ProfileNavigation({ current, + routeMyAccountCashout, + routeMyAccountDelete, + routeMyAccountDetails, + routeMyAccountPassword, }: { - current: "details" | "delete" | "credentials" | "cashouts"; + current: "details" | "delete" | "credentials" | "cashouts", + routeMyAccountDetails: RouteDefinition<Record<string, never>>; + routeMyAccountDelete: RouteDefinition<Record<string, never>>; + routeMyAccountPassword: RouteDefinition<Record<string, never>>; + routeMyAccountCashout: RouteDefinition<Record<string, never>>; }): VNode { const { i18n } = useTranslationContext(); const { config } = useBankCoreApiContext(); @@ -48,19 +56,19 @@ export function ProfileNavigation({ const op = e.currentTarget.value as typeof current; switch (op) { case "details": { - navigateTo(privatePages.myAccountDetails.url({})); + navigateTo(routeMyAccountDetails.url({})); return; } case "delete": { - navigateTo(privatePages.myAccountDelete.url({})); + navigateTo(routeMyAccountDelete.url({})); return; } case "credentials": { - navigateTo(privatePages.myAccountPassword.url({})); + navigateTo(routeMyAccountPassword.url({})); return; } case "cashouts": { - navigateTo(privatePages.myAccountCashouts.url({})); + navigateTo(routeMyAccountCashout.url({})); return; } default: @@ -92,7 +100,7 @@ export function ProfileNavigation({ aria-label="Tabs" > <a - href={privatePages.myAccountDetails.url({})} + href={routeMyAccountDetails.url({})} data-selected={current == "details"} class="rounded-l-lg text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10" > @@ -107,7 +115,7 @@ export function ProfileNavigation({ </a> {!config.allow_deletions ? undefined : ( <a - href={privatePages.myAccountDelete.url({})} + href={routeMyAccountDelete.url({})} data-selected={current == "delete"} aria-current="page" class=" text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10" @@ -123,7 +131,7 @@ export function ProfileNavigation({ </a> )} <a - href={privatePages.myAccountPassword.url({})} + href={routeMyAccountPassword.url({})} data-selected={current == "credentials"} aria-current="page" class=" text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10" @@ -139,7 +147,7 @@ export function ProfileNavigation({ </a> {config.allow_conversion && nonAdminUser ? ( <a - href={privatePages.myAccountCashouts.url({})} + href={routeMyAccountCashout.url({})} data-selected={current == "cashouts"} class="rounded-r-lg text-gray-500 hover:text-gray-700 data-[selected=true]:text-gray-900 group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-center text-sm font-medium hover:bg-gray-50 focus:z-10" > diff --git a/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx b/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx index 0f951b1a8..2864cac65 100644 --- a/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx +++ b/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx @@ -31,8 +31,8 @@ export function PublicHistoriesPage(): VNode { const result = usePublicAccounts(undefined); const firstAccount = result && - !(result instanceof TalerError) && - result.data.public_accounts.length > 0 + !(result instanceof TalerError) && + result.data.public_accounts.length > 0 ? result.data.public_accounts[0].username : undefined; @@ -70,7 +70,7 @@ export function PublicHistoriesPage(): VNode { </a> </li>, ); - txs[account.username] = <Transactions account={account.username} />; + txs[account.username] = <Transactions account={account.username} routeCreateWireTransfer={undefined} />; } return ( diff --git a/packages/demobank-ui/src/pages/QrCodeSection.tsx b/packages/demobank-ui/src/pages/QrCodeSection.tsx index bf0369855..b439003a0 100644 --- a/packages/demobank-ui/src/pages/QrCodeSection.tsx +++ b/packages/demobank-ui/src/pages/QrCodeSection.tsx @@ -141,7 +141,7 @@ export function QrCodeSection({ <div class="px-4 py-5 sm:p-6"> <h3 class="text-base font-semibold leading-6 text-gray-900"> <i18n.Translate> - Or if you have the wallet in another device + Or if you have the Taler wallet in another device </i18n.Translate> </h3> <div class="mt-4 max-w-xl text-sm text-gray-500"> diff --git a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx index 8ce4c6a09..be1528db8 100644 --- a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx +++ b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx @@ -20,8 +20,7 @@ import { HttpStatusCode, TranslatedString, assertUnreachable, - parseWithdrawUri, - stringifyWithdrawUri, + parseWithdrawUri } from "@gnu-taler/taler-util"; import { Attention, @@ -33,7 +32,6 @@ import { import { VNode, h } from "preact"; import { forwardRef } from "preact/compat"; import { useState } from "preact/hooks"; -import { privatePages } from "../Routing.js"; import { useBankCoreApiContext } from "../context/config.js"; import { useBackendState } from "../hooks/backend.js"; import { useBankState } from "../hooks/bank-state.js"; @@ -42,8 +40,6 @@ import { RouteDefinition } from "../route.js"; import { undefinedIfEmpty } from "../utils.js"; import { OperationState } from "./OperationState/index.js"; import { InputAmount, doAutoFocus } from "./PaytoWireTransferForm.js"; -import { useTalerWalletIntegrationAPI } from "../context/wallet-integration.js"; -import { useNavigationContext } from "../context/navigation.js"; const RefAmount = forwardRef(InputAmount); @@ -52,9 +48,11 @@ function OldWithdrawalForm({ limit, routeCancel, focus, + routeOperationDetails, }: { limit: AmountJson; focus?: boolean; + routeOperationDetails: RouteDefinition<{ wopid: string }>, onOperationCreated: (wopid: string) => void; routeCancel: RouteDefinition<Record<string, never>>; }): VNode { @@ -83,7 +81,7 @@ function OldWithdrawalForm({ // withdrawalOperationId: bankState.currentWithdrawalOperationId, // }); // const uri = parseWithdrawUri(suri)! - const url = privatePages.operationDetails.url({ + const url = routeOperationDetails.url({ wopid: bankState.currentWithdrawalOperationId, }); return ( @@ -95,12 +93,12 @@ function OldWithdrawalForm({ <a class="font-semibold text-yellow-700 hover:text-yellow-600" href={url} - // onClick={(e) => { - // e.preventDefault() - // walletInegrationApi.publishTalerAction(uri, () => { - // navigateTo(url) - // }) - // }} + // onClick={(e) => { + // e.preventDefault() + // walletInegrationApi.publishTalerAction(uri, () => { + // navigateTo(url) + // }) + // }} > <i18n.Translate>this page</i18n.Translate> </a> @@ -285,9 +283,11 @@ export function WalletWithdrawForm({ onAuthorizationRequired, onOperationCreated, onOperationAborted, + routeOperationDetails, }: { limit: AmountJson; focus?: boolean; + routeOperationDetails: RouteDefinition<{ wopid: string }>, onAuthorizationRequired: () => void; onOperationCreated: (wopid: string) => void; onOperationAborted: () => void; @@ -300,7 +300,7 @@ export function WalletWithdrawForm({ <div class="grid grid-cols-1 gap-x-8 gap-y-8 pt-10 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg"> <div class="px-4 sm:px-0"> <h2 class="text-base font-semibold leading-7 text-gray-900"> - <i18n.Translate>Prepare your wallet</i18n.Translate> + <i18n.Translate>Prepare your Taler wallet</i18n.Translate> </h2> <p class="mt-1 text-sm text-gray-500"> <i18n.Translate> @@ -313,7 +313,7 @@ export function WalletWithdrawForm({ <div class="col-span-2"> {settings.showInstallWallet && ( <Attention - title={i18n.str`You need a GNU Taler Wallet`} + title={i18n.str`You need a Taler wallet`} onClose={() => { updateSettings("showInstallWallet", false); }} @@ -335,6 +335,7 @@ export function WalletWithdrawForm({ {!settings.fastWithdrawal ? ( <OldWithdrawalForm focus={focus} + routeOperationDetails={routeOperationDetails} limit={limit} routeCancel={routeCancel} onOperationCreated={onOperationCreated} @@ -345,7 +346,7 @@ export function WalletWithdrawForm({ onAuthorizationRequired={onAuthorizationRequired} routeClose={routeCancel} onAbort={onOperationAborted} - // route={routeCancel} + // route={routeCancel} /> )} </div> diff --git a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx index 66c27ef4c..e8fff1901 100644 --- a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx +++ b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx @@ -214,9 +214,7 @@ export function WithdrawalConfirmationQuestion({ <Fragment> <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <dt class="text-sm font-medium leading-6 text-gray-900"> - <i18n.Translate> - Taler Exchange operator's account - </i18n.Translate> + <i18n.Translate>Payment provider's account number</i18n.Translate> </dt> <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"> {p.iban} @@ -225,12 +223,10 @@ export function WithdrawalConfirmationQuestion({ {name && ( <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <dt class="text-sm font-medium leading-6 text-gray-900"> - <i18n.Translate> - Taler Exchange operator's name - </i18n.Translate> + <i18n.Translate>Payment provider's name</i18n.Translate> </dt> <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"> - {p.params["receiver-name"]} + {name} </dd> </div> )} @@ -244,9 +240,7 @@ export function WithdrawalConfirmationQuestion({ <Fragment> <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <dt class="text-sm font-medium leading-6 text-gray-900"> - <i18n.Translate> - Taler Exchange operator's account - </i18n.Translate> + <i18n.Translate>Payment provider's account id</i18n.Translate> </dt> <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"> {p.account} @@ -255,12 +249,10 @@ export function WithdrawalConfirmationQuestion({ {name && ( <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <dt class="text-sm font-medium leading-6 text-gray-900"> - <i18n.Translate> - Taler Exchange operator's name - </i18n.Translate> + <i18n.Translate>Payment provider's name</i18n.Translate> </dt> <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"> - {p.params["receiver-name"]} + {name} </dd> </div> )} @@ -271,9 +263,7 @@ export function WithdrawalConfirmationQuestion({ return ( <div class="px-4 py-2 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0"> <dt class="text-sm font-medium leading-6 text-gray-900"> - <i18n.Translate> - Taler Exchange operator's account - </i18n.Translate> + <i18n.Translate>Payment provider's account</i18n.Translate> </dt> <dd class="mt-1 text-sm leading-6 text-gray-700 sm:col-span-2 sm:mt-0"> {details.account.targetPath} diff --git a/packages/demobank-ui/src/pages/WithdrawalOperationPage.tsx b/packages/demobank-ui/src/pages/WithdrawalOperationPage.tsx index e69a4dfb2..e03260dbb 100644 --- a/packages/demobank-ui/src/pages/WithdrawalOperationPage.tsx +++ b/packages/demobank-ui/src/pages/WithdrawalOperationPage.tsx @@ -30,6 +30,7 @@ export function WithdrawalOperationPage({ }: { onAuthorizationRequired: () => void; operationId: string; + pupose: "after-creation" | "after-confirmation", onOperationAborted: () => void; routeClose: RouteDefinition<Record<string, never>>; }): VNode { diff --git a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx index a23909338..8faa91d07 100644 --- a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx +++ b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx @@ -101,7 +101,7 @@ export function WithdrawalQRCode({ <div class="mt-2"> <p class="text-sm text-gray-500"> <i18n.Translate> - The wire transfer to the Taler Exchange operator's account was + The wire transfer to the payment provider's account was aborted from somewhere else, your balance was not affected. </i18n.Translate> </p> @@ -169,6 +169,7 @@ export function WithdrawalQRCode({ </div> ); } + if (data.status === "pending") { return ( <QrCodeSection diff --git a/packages/demobank-ui/src/pages/account/CashoutListForAccount.tsx b/packages/demobank-ui/src/pages/account/CashoutListForAccount.tsx index 670bbaea0..656c2a52a 100644 --- a/packages/demobank-ui/src/pages/account/CashoutListForAccount.tsx +++ b/packages/demobank-ui/src/pages/account/CashoutListForAccount.tsx @@ -26,12 +26,20 @@ interface Props { routeClose: RouteDefinition<Record<string, never>>; onAuthorizationRequired: () => void; routeCashoutDetails: RouteDefinition<{ cid: string }>; + routeMyAccountDetails: RouteDefinition<Record<string, never>>; + routeMyAccountDelete: RouteDefinition<Record<string, never>>; + routeMyAccountPassword: RouteDefinition<Record<string, never>>; + routeMyAccountCashout: RouteDefinition<Record<string, never>>; } export function CashoutListForAccount({ account, onAuthorizationRequired, routeCashoutDetails, + routeMyAccountCashout, + routeMyAccountDelete, + routeMyAccountDetails, + routeMyAccountPassword, routeClose, }: Props): VNode { const { i18n } = useTranslationContext(); @@ -46,7 +54,12 @@ export function CashoutListForAccount({ return ( <Fragment> {accountIsTheCurrentUser ? ( - <ProfileNavigation current="cashouts" /> + <ProfileNavigation current="cashouts" + routeMyAccountCashout={routeMyAccountCashout} + routeMyAccountDelete={routeMyAccountDelete} + routeMyAccountDetails={routeMyAccountDetails} + routeMyAccountPassword={routeMyAccountPassword} + /> ) : ( <h1 class="text-base font-semibold leading-6 text-gray-900"> <i18n.Translate>Cashout for account {account}</i18n.Translate> diff --git a/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx b/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx index 6d5a1c18d..70fd85ee8 100644 --- a/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx +++ b/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx @@ -46,8 +46,16 @@ export function ShowAccountDetails({ routeClose, onUpdateSuccess, onAuthorizationRequired, + routeMyAccountCashout, + routeMyAccountDelete, + routeMyAccountDetails, + routeMyAccountPassword, }: { routeClose: RouteDefinition<Record<string, never>>; + routeMyAccountDetails: RouteDefinition<Record<string, never>>; + routeMyAccountDelete: RouteDefinition<Record<string, never>>; + routeMyAccountPassword: RouteDefinition<Record<string, never>>; + routeMyAccountCashout: RouteDefinition<Record<string, never>>; onUpdateSuccess: () => void; onAuthorizationRequired: () => void; account: string; @@ -171,7 +179,12 @@ export function ShowAccountDetails({ <Fragment> <LocalNotificationBanner notification={notification} showDebug={true} /> {accountIsTheCurrentUser ? ( - <ProfileNavigation current="details" /> + <ProfileNavigation current="details" + routeMyAccountCashout={routeMyAccountCashout} + routeMyAccountDelete={routeMyAccountDelete} + routeMyAccountDetails={routeMyAccountDetails} + routeMyAccountPassword={routeMyAccountPassword} + /> ) : ( <h1 class="text-base font-semibold leading-6 text-gray-900"> <i18n.Translate>Account "{account}"</i18n.Translate> diff --git a/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx b/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx index 4dcce599d..3ce9b1094 100644 --- a/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx +++ b/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx @@ -41,9 +41,17 @@ export function UpdateAccountPassword({ routeClose, onUpdateSuccess, onAuthorizationRequired, + routeMyAccountCashout, + routeMyAccountDelete, + routeMyAccountDetails, + routeMyAccountPassword, focus, }: { routeClose: RouteDefinition<Record<string, never>>; + routeMyAccountDetails: RouteDefinition<Record<string, never>>; + routeMyAccountDelete: RouteDefinition<Record<string, never>>; + routeMyAccountPassword: RouteDefinition<Record<string, never>>; + routeMyAccountCashout: RouteDefinition<Record<string, never>>; focus?: boolean; onAuthorizationRequired: () => void; onUpdateSuccess: () => void; @@ -136,7 +144,12 @@ export function UpdateAccountPassword({ <Fragment> <LocalNotificationBanner notification={notification} /> {accountIsTheCurrentUser ? ( - <ProfileNavigation current="credentials" /> + <ProfileNavigation current="credentials" + routeMyAccountCashout={routeMyAccountCashout} + routeMyAccountDelete={routeMyAccountDelete} + routeMyAccountDetails={routeMyAccountDetails} + routeMyAccountPassword={routeMyAccountPassword} + /> ) : ( <h1 class="text-base font-semibold leading-6 text-gray-900"> <i18n.Translate>Account "{accountName}"</i18n.Translate> diff --git a/packages/demobank-ui/src/pages/admin/AccountForm.tsx b/packages/demobank-ui/src/pages/admin/AccountForm.tsx index fcad47b4a..5d4a5c5db 100644 --- a/packages/demobank-ui/src/pages/admin/AccountForm.tsx +++ b/packages/demobank-ui/src/pages/admin/AccountForm.tsx @@ -475,9 +475,9 @@ export function AccountForm<PurposeType extends keyof ChangeByPurposeType>({ !editableThreshold ? undefined : (e) => { - form.debit_threshold = e as AmountString; - updateForm(structuredClone(form)); - } + form.debit_threshold = e as AmountString; + updateForm(structuredClone(form)); + } } /> <ShowInputErrorLabel @@ -503,7 +503,7 @@ export function AccountForm<PurposeType extends keyof ChangeByPurposeType>({ class="text-sm text-black font-medium leading-6 " id="availability-label" > - <i18n.Translate>Is this a Taler Exchange?</i18n.Translate> + <i18n.Translate>Is this a payment provider?</i18n.Translate> </span> </span> <button @@ -538,7 +538,7 @@ export function AccountForm<PurposeType extends keyof ChangeByPurposeType>({ )} {/* channel, not shown if old cashout api */} {OLD_CASHOUT_API || - config.supported_tan_channels.length === 0 ? undefined : ( + config.supported_tan_channels.length === 0 ? undefined : ( <div class="sm:col-span-5"> <label class="block text-sm font-medium leading-6 text-gray-900" @@ -549,7 +549,7 @@ export function AccountForm<PurposeType extends keyof ChangeByPurposeType>({ <div class="mt-2 max-w-xl text-sm text-gray-500"> <div class="px-4 mt-4 grid grid-cols-1 gap-y-6"> {config.supported_tan_channels.indexOf(TanChannel.EMAIL) === - -1 ? undefined : ( + -1 ? undefined : ( <label onClick={(e) => { if (!hasEmail) return; @@ -607,7 +607,7 @@ export function AccountForm<PurposeType extends keyof ChangeByPurposeType>({ )} {config.supported_tan_channels.indexOf(TanChannel.SMS) === - -1 ? undefined : ( + -1 ? undefined : ( <label onClick={(e) => { if (!hasPhone) return; diff --git a/packages/demobank-ui/src/pages/admin/AdminHome.tsx b/packages/demobank-ui/src/pages/admin/AdminHome.tsx index f0f8f71be..1a7edd6b9 100644 --- a/packages/demobank-ui/src/pages/admin/AdminHome.tsx +++ b/packages/demobank-ui/src/pages/admin/AdminHome.tsx @@ -37,21 +37,22 @@ import { } from "date-fns"; import { Fragment, VNode, h } from "preact"; import { useState } from "preact/hooks"; -import { privatePages } from "../../Routing.js"; import { ErrorLoadingWithDebug } from "../../components/ErrorLoadingWithDebug.js"; import { Transactions } from "../../components/Transactions/index.js"; import { useBankCoreApiContext } from "../../context/config.js"; import { useConversionInfo, useLastMonitorInfo } from "../../hooks/circuit.js"; +import { RouteDefinition } from "../../route.js"; import { RenderAmount } from "../PaytoWireTransferForm.js"; import { WireTransfer } from "../WireTransfer.js"; import { AccountList } from "./AccountList.js"; -import { RouteDefinition } from "../../route.js"; /** * Query account information and show QR code if there is pending withdrawal */ interface Props { routeCreate: RouteDefinition<Record<string, never>>; + routeDownloadStats: RouteDefinition<Record<string, never>>; + routeCreateWireTransfer: RouteDefinition<{ destination: string }>; routeShowAccount: RouteDefinition<{ account: string }>; routeRemoveAccount: RouteDefinition<{ account: string }>; @@ -65,14 +66,16 @@ export function AdminHome({ routeShowAccount, routeShowCashoutsAccount, routeUpdatePasswordAccount, + routeDownloadStats, + routeCreateWireTransfer, onAuthorizationRequired, }: Props): VNode { return ( <Fragment> - <Metrics /> + <Metrics routeDownloadStats={routeDownloadStats} /> <WireTransfer onAuthorizationRequired={onAuthorizationRequired} /> - <Transactions account="admin" /> + <Transactions account="admin" routeCreateWireTransfer={routeCreateWireTransfer} /> <AccountList routeCreate={routeCreate} routeRemoveAccount={routeRemoveAccount} @@ -140,7 +143,9 @@ export function getTimeframesForDate( } } -function Metrics(): VNode { +function Metrics({ routeDownloadStats }: { + routeDownloadStats: RouteDefinition<Record<string, never>>; +}): VNode { const { i18n, dateLocale } = useTranslationContext(); const [metricType, setMetricType] = useState<TalerCorebankApi.MonitorTimeframeParam>( @@ -335,7 +340,7 @@ function Metrics(): VNode { </div> <dl class="mt-5 grid grid-cols-1 md:grid-cols-2 divide-y divide-gray-200 overflow-hidden rounded-lg bg-white shadow-lg md:divide-x md:divide-y-0"> {resp.current.body.type !== "with-conversions" || - resp.previous.body.type !== "with-conversions" ? undefined : ( + resp.previous.body.type !== "with-conversions" ? undefined : ( <Fragment> <div class="px-4 py-5 sm:p-6"> <dt class="text-base font-normal text-gray-900"> @@ -382,7 +387,7 @@ function Metrics(): VNode { </dl> <div class="flex justify-end mt-2"> <a - href={privatePages.statsDownload.url({})} + href={routeDownloadStats.url({})} class="disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" > <i18n.Translate>Download stats as CSV</i18n.Translate> @@ -411,9 +416,9 @@ function MetricValue({ const rate = !currAmount || - Number.isNaN(currAmount) || - !prevAmount || - Number.isNaN(prevAmount) + Number.isNaN(currAmount) || + !prevAmount || + Number.isNaN(prevAmount) ? 0 : cmp === -1 ? 1 - Math.round(currAmount) / Math.round(prevAmount) |