handler transaction error on details and added retry button
This commit is contained in:
parent
42fe576320
commit
b43c476590
@ -32,6 +32,11 @@ import { TransactionView as TestedComponent } from './Transaction';
|
|||||||
export default {
|
export default {
|
||||||
title: 'popup/transaction/details',
|
title: 'popup/transaction/details',
|
||||||
component: TestedComponent,
|
component: TestedComponent,
|
||||||
|
argTypes: {
|
||||||
|
onRetry: { action: 'onRetry' },
|
||||||
|
onDelete: { action: 'onDelete' },
|
||||||
|
onBack: { action: 'onBack' },
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const commonTransaction = {
|
const commonTransaction = {
|
||||||
@ -105,6 +110,13 @@ const exampleData = {
|
|||||||
} as TransactionRefund,
|
} 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>) {
|
function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) {
|
||||||
const r = (args: any) => <Component {...args} />
|
const r = (args: any) => <Component {...args} />
|
||||||
r.args = props
|
r.args = props
|
||||||
@ -117,6 +129,13 @@ export const Withdraw = createExample(TestedComponent, {
|
|||||||
transaction: exampleData.withdraw
|
transaction: exampleData.withdraw
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const WithdrawError = createExample(TestedComponent, {
|
||||||
|
transaction: {
|
||||||
|
...exampleData.withdraw,
|
||||||
|
error: transactionError,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const WithdrawPending = createExample(TestedComponent, {
|
export const WithdrawPending = createExample(TestedComponent, {
|
||||||
transaction: { ...exampleData.withdraw, pending: true },
|
transaction: { ...exampleData.withdraw, pending: true },
|
||||||
});
|
});
|
||||||
@ -126,6 +145,13 @@ export const Payment = createExample(TestedComponent, {
|
|||||||
transaction: exampleData.payment
|
transaction: exampleData.payment
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const PaymentError = createExample(TestedComponent, {
|
||||||
|
transaction: {
|
||||||
|
...exampleData.payment,
|
||||||
|
error: transactionError
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const PaymentWithoutFee = createExample(TestedComponent, {
|
export const PaymentWithoutFee = createExample(TestedComponent, {
|
||||||
transaction: {
|
transaction: {
|
||||||
...exampleData.payment,
|
...exampleData.payment,
|
||||||
@ -191,6 +217,13 @@ export const Deposit = createExample(TestedComponent, {
|
|||||||
transaction: exampleData.deposit
|
transaction: exampleData.deposit
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const DepositError = createExample(TestedComponent, {
|
||||||
|
transaction: {
|
||||||
|
...exampleData.deposit,
|
||||||
|
error: transactionError
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const DepositPending = createExample(TestedComponent, {
|
export const DepositPending = createExample(TestedComponent, {
|
||||||
transaction: { ...exampleData.deposit, pending: true }
|
transaction: { ...exampleData.deposit, pending: true }
|
||||||
});
|
});
|
||||||
@ -199,10 +232,24 @@ export const Refresh = createExample(TestedComponent, {
|
|||||||
transaction: exampleData.refresh
|
transaction: exampleData.refresh
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const RefreshError = createExample(TestedComponent, {
|
||||||
|
transaction: {
|
||||||
|
...exampleData.refresh,
|
||||||
|
error: transactionError
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const Tip = createExample(TestedComponent, {
|
export const Tip = createExample(TestedComponent, {
|
||||||
transaction: exampleData.tip
|
transaction: exampleData.tip
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const TipError = createExample(TestedComponent, {
|
||||||
|
transaction: {
|
||||||
|
...exampleData.tip,
|
||||||
|
error: transactionError
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const TipPending = createExample(TestedComponent, {
|
export const TipPending = createExample(TestedComponent, {
|
||||||
transaction: { ...exampleData.tip, pending: true }
|
transaction: { ...exampleData.tip, pending: true }
|
||||||
});
|
});
|
||||||
@ -211,6 +258,13 @@ export const Refund = createExample(TestedComponent, {
|
|||||||
transaction: exampleData.refund
|
transaction: exampleData.refund
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const RefundError = createExample(TestedComponent, {
|
||||||
|
transaction: {
|
||||||
|
...exampleData.refund,
|
||||||
|
error: transactionError
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const RefundPending = createExample(TestedComponent, {
|
export const RefundPending = createExample(TestedComponent, {
|
||||||
transaction: { ...exampleData.refund, pending: true }
|
transaction: { ...exampleData.refund, pending: true }
|
||||||
});
|
});
|
||||||
|
@ -44,16 +44,18 @@ export function TransactionPage({ tid }: { tid: string; }): JSX.Element {
|
|||||||
return <TransactionView
|
return <TransactionView
|
||||||
transaction={transaction}
|
transaction={transaction}
|
||||||
onDelete={() => wxApi.deleteTransaction(tid).then(_ => history.go(-1))}
|
onDelete={() => wxApi.deleteTransaction(tid).then(_ => history.go(-1))}
|
||||||
|
onRetry={() => wxApi.retryTransaction(tid).then(_ => history.go(-1))}
|
||||||
onBack={() => { history.go(-1); }} />;
|
onBack={() => { history.go(-1); }} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WalletTransactionProps {
|
export interface WalletTransactionProps {
|
||||||
transaction?: Transaction,
|
transaction?: Transaction,
|
||||||
onDelete: () => void,
|
onDelete: () => void,
|
||||||
|
onRetry: () => void,
|
||||||
onBack: () => void,
|
onBack: () => void,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TransactionView({ transaction, onDelete, onBack }: WalletTransactionProps) {
|
export function TransactionView({ transaction, onDelete, onRetry, onBack }: WalletTransactionProps) {
|
||||||
if (!transaction) {
|
if (!transaction) {
|
||||||
return <div><i18n.Translate>Loading ...</i18n.Translate></div>;
|
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 }}>
|
return <footer style={{ marginTop: 'auto', display: 'flex', flexShrink: 0 }}>
|
||||||
<button onClick={onBack}><i18n.Translate>back</i18n.Translate></button>
|
<button onClick={onBack}><i18n.Translate>back</i18n.Translate></button>
|
||||||
<div style={{ width: '100%', flexDirection: 'row', justifyContent: 'flex-end', display: 'flex' }}>
|
<div style={{ width: '100%', flexDirection: 'row', justifyContent: 'flex-end', display: 'flex' }}>
|
||||||
|
{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>
|
<button class="pure-button button-destructive" onClick={onDelete}><i18n.Translate>delete</i18n.Translate></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</footer>
|
</footer>
|
||||||
}
|
}
|
||||||
|
|
||||||
function Pending() {
|
function Status() {
|
||||||
|
if (transaction?.error) {
|
||||||
|
return <span style={{ fontWeight: 'normal', fontSize: 16, color: 'red' }}>(failed)</span>
|
||||||
|
}
|
||||||
if (!transaction?.pending) return null
|
if (!transaction?.pending) return null
|
||||||
return <span style={{ fontWeight: 'normal', fontSize: 16, color: 'gray' }}>(pending...)</span>
|
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) ?
|
const Fee = ({ value }: { value: AmountJson }) => Amounts.isNonZero(value) ?
|
||||||
<span style="font-size: 16px;font-weight: normal;color: gray;">(fee {Amounts.stringify(value)})</span> : null
|
<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">
|
<span style="float: right; font-size:small; color:gray">
|
||||||
From <b>{transaction.exchangeBaseUrl}</b>
|
From <b>{transaction.exchangeBaseUrl}</b>
|
||||||
</span>
|
</span>
|
||||||
<h3>Withdraw <Pending /></h3>
|
<Error />
|
||||||
|
<h3>Withdraw <Status /></h3>
|
||||||
<h1>{transaction.amountEffective} <Fee value={fee} /></h1>
|
<h1>{transaction.amountEffective} <Fee value={fee} /></h1>
|
||||||
</section>
|
</section>
|
||||||
<Footer />
|
<Footer />
|
||||||
@ -113,7 +127,8 @@ export function TransactionView({ transaction, onDelete, onBack }: WalletTransac
|
|||||||
<span style="float: right; font-size:small; color:gray">
|
<span style="float: right; font-size:small; color:gray">
|
||||||
To <b>{transaction.info.merchant.name}</b>
|
To <b>{transaction.info.merchant.name}</b>
|
||||||
</span>
|
</span>
|
||||||
<h3>Payment <Pending /></h3>
|
<Error />
|
||||||
|
<h3>Payment <Status /></h3>
|
||||||
<h1>{transaction.amountEffective} <Fee value={fee} /></h1>
|
<h1>{transaction.amountEffective} <Fee value={fee} /></h1>
|
||||||
<span style="font-size:small; color:gray">#{transaction.info.orderId}</span>
|
<span style="font-size:small; color:gray">#{transaction.info.orderId}</span>
|
||||||
<p>
|
<p>
|
||||||
@ -151,7 +166,8 @@ export function TransactionView({ transaction, onDelete, onBack }: WalletTransac
|
|||||||
<span style="float: right; font-size:small; color:gray">
|
<span style="float: right; font-size:small; color:gray">
|
||||||
To <b>{transaction.targetPaytoUri}</b>
|
To <b>{transaction.targetPaytoUri}</b>
|
||||||
</span>
|
</span>
|
||||||
<h3>Deposit <Pending /></h3>
|
<Error />
|
||||||
|
<h3>Deposit <Status /></h3>
|
||||||
<h1>{transaction.amountEffective} <Fee value={fee} /></h1>
|
<h1>{transaction.amountEffective} <Fee value={fee} /></h1>
|
||||||
</section>
|
</section>
|
||||||
<Footer />
|
<Footer />
|
||||||
@ -171,7 +187,8 @@ export function TransactionView({ transaction, onDelete, onBack }: WalletTransac
|
|||||||
<span style="float: right; font-size:small; color:gray">
|
<span style="float: right; font-size:small; color:gray">
|
||||||
From <b>{transaction.exchangeBaseUrl}</b>
|
From <b>{transaction.exchangeBaseUrl}</b>
|
||||||
</span>
|
</span>
|
||||||
<h3>Refresh <Pending /></h3>
|
<Error />
|
||||||
|
<h3>Refresh <Status /></h3>
|
||||||
<h1>{transaction.amountEffective} <Fee value={fee} /></h1>
|
<h1>{transaction.amountEffective} <Fee value={fee} /></h1>
|
||||||
</section>
|
</section>
|
||||||
<Footer />
|
<Footer />
|
||||||
@ -191,7 +208,8 @@ export function TransactionView({ transaction, onDelete, onBack }: WalletTransac
|
|||||||
<span style="float: right; font-size:small; color:gray">
|
<span style="float: right; font-size:small; color:gray">
|
||||||
From <b>{transaction.merchantBaseUrl}</b>
|
From <b>{transaction.merchantBaseUrl}</b>
|
||||||
</span>
|
</span>
|
||||||
<h3>Tip <Pending /></h3>
|
<Error />
|
||||||
|
<h3>Tip <Status /></h3>
|
||||||
<h1>{transaction.amountEffective} <Fee value={fee} /></h1>
|
<h1>{transaction.amountEffective} <Fee value={fee} /></h1>
|
||||||
</section>
|
</section>
|
||||||
<Footer />
|
<Footer />
|
||||||
@ -211,7 +229,8 @@ export function TransactionView({ transaction, onDelete, onBack }: WalletTransac
|
|||||||
<span style="float: right; font-size:small; color:gray">
|
<span style="float: right; font-size:small; color:gray">
|
||||||
From <b>{transaction.info.merchant.name}</b>
|
From <b>{transaction.info.merchant.name}</b>
|
||||||
</span>
|
</span>
|
||||||
<h3>Refund <Pending /></h3>
|
<Error />
|
||||||
|
<h3>Refund <Status /></h3>
|
||||||
<h1>{transaction.amountEffective} <Fee value={fee} /></h1>
|
<h1>{transaction.amountEffective} <Fee value={fee} /></h1>
|
||||||
<span style="font-size:small; color:gray">#{transaction.info.orderId}</span>
|
<span style="font-size:small; color:gray">#{transaction.info.orderId}</span>
|
||||||
<p>
|
<p>
|
||||||
|
@ -25,7 +25,8 @@ import { setupI18n } from "@gnu-taler/taler-util";
|
|||||||
import { strings } from "./i18n/strings";
|
import { strings } from "./i18n/strings";
|
||||||
import { useEffect } from "preact/hooks";
|
import { useEffect } from "preact/hooks";
|
||||||
import {
|
import {
|
||||||
Pages, WalletNavBar} from "./popup/popup";
|
Pages, WalletNavBar
|
||||||
|
} from "./popup/popup";
|
||||||
import { HistoryPage } from "./popup/History";
|
import { HistoryPage } from "./popup/History";
|
||||||
import { DebugPage } from "./popup/Debug";
|
import { DebugPage } from "./popup/Debug";
|
||||||
import { SettingsPage } from "./popup/Settings";
|
import { SettingsPage } from "./popup/Settings";
|
||||||
@ -67,7 +68,7 @@ function TalerActionFound({ url, onDismiss }: Props) {
|
|||||||
<h1>Taler Action </h1>
|
<h1>Taler Action </h1>
|
||||||
<p>This page has a Taler action.</p>
|
<p>This page has a Taler action.</p>
|
||||||
<p>
|
<p>
|
||||||
<button onClick={() => { window.open(url, "_blank"); }}>
|
<button onClick={() => { chrome.tabs.create({ "url": url }); }}>
|
||||||
Open
|
Open
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
|
@ -36,6 +36,7 @@ import {
|
|||||||
PrepareTipResult,
|
PrepareTipResult,
|
||||||
AcceptTipRequest,
|
AcceptTipRequest,
|
||||||
DeleteTransactionRequest,
|
DeleteTransactionRequest,
|
||||||
|
RetryTransactionRequest,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { OperationFailedError } from "@gnu-taler/taler-wallet-core";
|
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> {
|
export function deleteTransaction(transactionId: string): Promise<void> {
|
||||||
return callBackend("deleteTransaction", {
|
return callBackend("deleteTransaction", {
|
||||||
|
@ -234,12 +234,15 @@ button.accept:disabled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.errorbox {
|
.errorbox {
|
||||||
border: 1px solid;
|
border: 2px solid #f5c6cb;
|
||||||
display: inline-block;
|
border-radius: .25em;
|
||||||
margin: 1em;
|
display: block;
|
||||||
padding: 1em;
|
/* margin: 0.5em; */
|
||||||
font-weight: bold;
|
padding-left: 1em;
|
||||||
background: #ff8a8a;
|
padding-right: 1em;
|
||||||
|
width: '100%';
|
||||||
|
color: #721c24;
|
||||||
|
background: #f8d7da;
|
||||||
}
|
}
|
||||||
|
|
||||||
.okaybox {
|
.okaybox {
|
||||||
|
Loading…
Reference in New Issue
Block a user