diff options
author | Sebastian <sebasjm@gmail.com> | 2021-06-28 11:38:29 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2021-06-28 11:38:38 -0300 |
commit | b43c476590508b5b3b10a5c2da34ac30f1fbdf57 (patch) | |
tree | b37f53fd10b024e119beacf6f1a2bb774674750b | |
parent | 42fe57632002e8f6dbf175b4e984b2fa1013bbe9 (diff) |
handler transaction error on details and added retry button
5 files changed, 107 insertions, 18 deletions
diff --git a/packages/taler-wallet-webextension/src/popup/Transaction.stories.tsx b/packages/taler-wallet-webextension/src/popup/Transaction.stories.tsx index 48f945783..00108aac6 100644 --- a/packages/taler-wallet-webextension/src/popup/Transaction.stories.tsx +++ b/packages/taler-wallet-webextension/src/popup/Transaction.stories.tsx @@ -32,6 +32,11 @@ import { TransactionView as TestedComponent } from './Transaction'; export default { title: 'popup/transaction/details', component: TestedComponent, + argTypes: { + onRetry: { action: 'onRetry' }, + onDelete: { action: 'onDelete' }, + onBack: { action: 'onBack' }, + } }; const commonTransaction = { @@ -105,6 +110,13 @@ const exampleData = { } as TransactionRefund, } +const transactionError = { + code: 2000, + details: "details", + hint: "this is a hint for the error", + message: 'message' +} + function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) { const r = (args: any) => <Component {...args} /> r.args = props @@ -117,6 +129,13 @@ export const Withdraw = createExample(TestedComponent, { transaction: exampleData.withdraw }); +export const WithdrawError = createExample(TestedComponent, { + transaction: { + ...exampleData.withdraw, + error: transactionError, + }, +}); + export const WithdrawPending = createExample(TestedComponent, { transaction: { ...exampleData.withdraw, pending: true }, }); @@ -126,6 +145,13 @@ export const Payment = createExample(TestedComponent, { transaction: exampleData.payment }); +export const PaymentError = createExample(TestedComponent, { + transaction: { + ...exampleData.payment, + error: transactionError + }, +}); + export const PaymentWithoutFee = createExample(TestedComponent, { transaction: { ...exampleData.payment, @@ -191,6 +217,13 @@ export const Deposit = createExample(TestedComponent, { transaction: exampleData.deposit }); +export const DepositError = createExample(TestedComponent, { + transaction: { + ...exampleData.deposit, + error: transactionError + }, +}); + export const DepositPending = createExample(TestedComponent, { transaction: { ...exampleData.deposit, pending: true } }); @@ -199,10 +232,24 @@ export const Refresh = createExample(TestedComponent, { transaction: exampleData.refresh }); +export const RefreshError = createExample(TestedComponent, { + transaction: { + ...exampleData.refresh, + error: transactionError + }, +}); + export const Tip = createExample(TestedComponent, { transaction: exampleData.tip }); +export const TipError = createExample(TestedComponent, { + transaction: { + ...exampleData.tip, + error: transactionError + }, +}); + export const TipPending = createExample(TestedComponent, { transaction: { ...exampleData.tip, pending: true } }); @@ -211,6 +258,13 @@ export const Refund = createExample(TestedComponent, { transaction: exampleData.refund }); +export const RefundError = createExample(TestedComponent, { + transaction: { + ...exampleData.refund, + error: transactionError + }, +}); + export const RefundPending = createExample(TestedComponent, { transaction: { ...exampleData.refund, pending: true } }); diff --git a/packages/taler-wallet-webextension/src/popup/Transaction.tsx b/packages/taler-wallet-webextension/src/popup/Transaction.tsx index 12245e5be..7a66d7a0e 100644 --- a/packages/taler-wallet-webextension/src/popup/Transaction.tsx +++ b/packages/taler-wallet-webextension/src/popup/Transaction.tsx @@ -44,16 +44,18 @@ export function TransactionPage({ tid }: { tid: string; }): JSX.Element { return <TransactionView transaction={transaction} onDelete={() => wxApi.deleteTransaction(tid).then(_ => history.go(-1))} + onRetry={() => wxApi.retryTransaction(tid).then(_ => history.go(-1))} onBack={() => { history.go(-1); }} />; } export interface WalletTransactionProps { transaction?: Transaction, onDelete: () => void, + onRetry: () => void, onBack: () => void, } -export function TransactionView({ transaction, onDelete, onBack }: WalletTransactionProps) { +export function TransactionView({ transaction, onDelete, onRetry, onBack }: WalletTransactionProps) { if (!transaction) { return <div><i18n.Translate>Loading ...</i18n.Translate></div>; } @@ -62,17 +64,28 @@ export function TransactionView({ transaction, onDelete, onBack }: WalletTransac return <footer style={{ marginTop: 'auto', display: 'flex', flexShrink: 0 }}> <button onClick={onBack}><i18n.Translate>back</i18n.Translate></button> <div style={{ width: '100%', flexDirection: 'row', justifyContent: 'flex-end', display: 'flex' }}> - <button class="pure-button button-destructive" onClick={onDelete}><i18n.Translate>delete</i18n.Translate></button> + {transaction?.error ? <button class="pure-button button-secondary" style={{marginRight: 5}} onClick={onRetry}><i18n.Translate>retry</i18n.Translate></button> : null } + <button class="pure-button button-destructive" onClick={onDelete}><i18n.Translate>delete</i18n.Translate></button> </div> </footer> } - function Pending() { + function Status() { + if (transaction?.error) { + return <span style={{ fontWeight: 'normal', fontSize: 16, color: 'red' }}>(failed)</span> + } if (!transaction?.pending) return null return <span style={{ fontWeight: 'normal', fontSize: 16, color: 'gray' }}>(pending...)</span> } + function Error() { + if (!transaction?.error) return null + return <div class="errorbox" > + <p>{transaction.error.hint}</p> + </div> + } + const Fee = ({ value }: { value: AmountJson }) => Amounts.isNonZero(value) ? <span style="font-size: 16px;font-weight: normal;color: gray;">(fee {Amounts.stringify(value)})</span> : null @@ -88,7 +101,8 @@ export function TransactionView({ transaction, onDelete, onBack }: WalletTransac <span style="float: right; font-size:small; color:gray"> From <b>{transaction.exchangeBaseUrl}</b> </span> - <h3>Withdraw <Pending /></h3> + <Error /> + <h3>Withdraw <Status /></h3> <h1>{transaction.amountEffective} <Fee value={fee} /></h1> </section> <Footer /> @@ -113,7 +127,8 @@ export function TransactionView({ transaction, onDelete, onBack }: WalletTransac <span style="float: right; font-size:small; color:gray"> To <b>{transaction.info.merchant.name}</b> </span> - <h3>Payment <Pending /></h3> + <Error /> + <h3>Payment <Status /></h3> <h1>{transaction.amountEffective} <Fee value={fee} /></h1> <span style="font-size:small; color:gray">#{transaction.info.orderId}</span> <p> @@ -151,7 +166,8 @@ export function TransactionView({ transaction, onDelete, onBack }: WalletTransac <span style="float: right; font-size:small; color:gray"> To <b>{transaction.targetPaytoUri}</b> </span> - <h3>Deposit <Pending /></h3> + <Error /> + <h3>Deposit <Status /></h3> <h1>{transaction.amountEffective} <Fee value={fee} /></h1> </section> <Footer /> @@ -171,7 +187,8 @@ export function TransactionView({ transaction, onDelete, onBack }: WalletTransac <span style="float: right; font-size:small; color:gray"> From <b>{transaction.exchangeBaseUrl}</b> </span> - <h3>Refresh <Pending /></h3> + <Error /> + <h3>Refresh <Status /></h3> <h1>{transaction.amountEffective} <Fee value={fee} /></h1> </section> <Footer /> @@ -191,7 +208,8 @@ export function TransactionView({ transaction, onDelete, onBack }: WalletTransac <span style="float: right; font-size:small; color:gray"> From <b>{transaction.merchantBaseUrl}</b> </span> - <h3>Tip <Pending /></h3> + <Error /> + <h3>Tip <Status /></h3> <h1>{transaction.amountEffective} <Fee value={fee} /></h1> </section> <Footer /> @@ -211,7 +229,8 @@ export function TransactionView({ transaction, onDelete, onBack }: WalletTransac <span style="float: right; font-size:small; color:gray"> From <b>{transaction.info.merchant.name}</b> </span> - <h3>Refund <Pending /></h3> + <Error /> + <h3>Refund <Status /></h3> <h1>{transaction.amountEffective} <Fee value={fee} /></h1> <span style="font-size:small; color:gray">#{transaction.info.orderId}</span> <p> diff --git a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx index 1c569519c..84501c2d2 100644 --- a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx +++ b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx @@ -25,7 +25,8 @@ import { setupI18n } from "@gnu-taler/taler-util"; import { strings } from "./i18n/strings"; import { useEffect } from "preact/hooks"; import { - Pages, WalletNavBar} from "./popup/popup"; + Pages, WalletNavBar +} from "./popup/popup"; import { HistoryPage } from "./popup/History"; import { DebugPage } from "./popup/Debug"; import { SettingsPage } from "./popup/Settings"; @@ -67,7 +68,7 @@ function TalerActionFound({ url, onDismiss }: Props) { <h1>Taler Action </h1> <p>This page has a Taler action.</p> <p> - <button onClick={() => { window.open(url, "_blank"); }}> + <button onClick={() => { chrome.tabs.create({ "url": url }); }}> Open </button> </p> diff --git a/packages/taler-wallet-webextension/src/wxApi.ts b/packages/taler-wallet-webextension/src/wxApi.ts index 3340f27ce..095fabe85 100644 --- a/packages/taler-wallet-webextension/src/wxApi.ts +++ b/packages/taler-wallet-webextension/src/wxApi.ts @@ -36,6 +36,7 @@ import { PrepareTipResult, AcceptTipRequest, DeleteTransactionRequest, + RetryTransactionRequest, } from "@gnu-taler/taler-util"; import { OperationFailedError } from "@gnu-taler/taler-wallet-core"; @@ -132,7 +133,18 @@ export function getTransactions(): Promise<TransactionsResponse> { } /** - * Get balances for all currencies/exchanges. + * Retry a transaction + * @param transactionId + * @returns + */ + export function retryTransaction(transactionId: string): Promise<void> { + return callBackend("retryTransaction", { + transactionId + } as RetryTransactionRequest); +} + +/** + * Permanently delete a transaction from the transaction list */ export function deleteTransaction(transactionId: string): Promise<void> { return callBackend("deleteTransaction", { diff --git a/packages/taler-wallet-webextension/static/style/popup.css b/packages/taler-wallet-webextension/static/style/popup.css index d0fd5d281..cd885556a 100644 --- a/packages/taler-wallet-webextension/static/style/popup.css +++ b/packages/taler-wallet-webextension/static/style/popup.css @@ -234,12 +234,15 @@ button.accept:disabled { } .errorbox { - border: 1px solid; - display: inline-block; - margin: 1em; - padding: 1em; - font-weight: bold; - background: #ff8a8a; + border: 2px solid #f5c6cb; + border-radius: .25em; + display: block; + /* margin: 0.5em; */ + padding-left: 1em; + padding-right: 1em; + width: '100%'; + color: #721c24; + background: #f8d7da; } .okaybox { |