summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension/src/components
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2023-01-09 20:20:09 -0300
committerSebastian <sebasjm@gmail.com>2023-01-09 20:20:09 -0300
commit4a781bd0dd8828ce152f6ab2c3f1bbd6b5e826f7 (patch)
tree5c16976f99eb973ff62d78ed64107ca01df57b99 /packages/taler-wallet-webextension/src/components
parent8a70edb2f8e235c3462127b0aa4e1b65aa1aee0b (diff)
downloadwallet-core-4a781bd0dd8828ce152f6ab2c3f1bbd6b5e826f7.tar.gz
wallet-core-4a781bd0dd8828ce152f6ab2c3f1bbd6b5e826f7.tar.bz2
wallet-core-4a781bd0dd8828ce152f6ab2c3f1bbd6b5e826f7.zip
fix #7153: more error handling
if handler do not trap error then fail at compile time, all safe handlers push alert on error errors are typed so they render good information
Diffstat (limited to 'packages/taler-wallet-webextension/src/components')
-rw-r--r--packages/taler-wallet-webextension/src/components/AmountField.stories.tsx8
-rw-r--r--packages/taler-wallet-webextension/src/components/CurrentAlerts.tsx75
-rw-r--r--packages/taler-wallet-webextension/src/components/PendingTransactions.stories.tsx8
-rw-r--r--packages/taler-wallet-webextension/src/components/QR.stories.tsx4
-rw-r--r--packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.stories.tsx10
-rw-r--r--packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.tsx13
-rw-r--r--packages/taler-wallet-webextension/src/components/TermsOfService/state.ts42
-rw-r--r--packages/taler-wallet-webextension/src/components/TermsOfService/stories.tsx4
8 files changed, 99 insertions, 65 deletions
diff --git a/packages/taler-wallet-webextension/src/components/AmountField.stories.tsx b/packages/taler-wallet-webextension/src/components/AmountField.stories.tsx
index 61c4a7661..f253d1996 100644
--- a/packages/taler-wallet-webextension/src/components/AmountField.stories.tsx
+++ b/packages/taler-wallet-webextension/src/components/AmountField.stories.tsx
@@ -20,12 +20,10 @@
*/
import { AmountJson, Amounts } from "@gnu-taler/taler-util";
-import { styled } from "@linaria/react";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { useTranslationContext } from "../context/translation.js";
-import { Grid } from "../mui/Grid.js";
-import { AmountFieldHandler, TextFieldHandler } from "../mui/handlers.js";
+import { AmountFieldHandler, nullFunction, withSafe } from "../mui/handlers.js";
import { AmountField } from "./AmountField.js";
export default {
@@ -39,9 +37,9 @@ function RenderAmount(): VNode {
const handler: AmountFieldHandler = {
value: value ?? Amounts.zeroOfCurrency("USD"),
- onInput: async (e) => {
+ onInput: withSafe(async (e) => {
setValue(e);
- },
+ }, nullFunction),
error,
};
const { i18n } = useTranslationContext();
diff --git a/packages/taler-wallet-webextension/src/components/CurrentAlerts.tsx b/packages/taler-wallet-webextension/src/components/CurrentAlerts.tsx
index a56c82dee..47863d73e 100644
--- a/packages/taler-wallet-webextension/src/components/CurrentAlerts.tsx
+++ b/packages/taler-wallet-webextension/src/components/CurrentAlerts.tsx
@@ -18,7 +18,6 @@ import { ComponentChildren, Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { useTranslationContext } from "../../../web-util/src/index.browser.js";
import {
- ErrorAlert,
Alert as AlertNotification,
useAlertContext,
} from "../context/alert.js";
@@ -37,41 +36,78 @@ function AlertContext({
context: undefined | object;
}): VNode {
const [more, setMore] = useState(false);
+ const [wrap, setWrap] = useState(false);
const { i18n } = useTranslationContext();
if (!more) {
return (
<div style={{ display: "flex", justifyContent: "right" }}>
- <a onClick={() => setMore(true)}>
+ <a
+ onClick={() => setMore(true)}
+ style={{ cursor: "pointer", textDecoration: "underline" }}
+ >
<i18n.Translate>more info</i18n.Translate>
</a>
</div>
);
}
+ const errorInfo = JSON.stringify(
+ context === undefined ? { cause } : { context, cause },
+ undefined,
+ 2,
+ );
return (
- <pre style={{ overflow: "overlay" }}>
- {JSON.stringify(
- context === undefined ? { cause } : { context, cause },
- undefined,
- 2,
- )}
- </pre>
+ <Fragment>
+ <div style={{ display: "flex", justifyContent: "right" }}>
+ <a
+ onClick={() => setWrap(!wrap)}
+ style={{ cursor: "pointer", textDecoration: "underline" }}
+ >
+ <i18n.Translate>wrap text</i18n.Translate>
+ </a>
+ &nbsp;&nbsp;
+ <a
+ onClick={() => navigator.clipboard.writeText(errorInfo)}
+ style={{ cursor: "pointer", textDecoration: "underline" }}
+ >
+ <i18n.Translate>copy content</i18n.Translate>
+ </a>
+ &nbsp;&nbsp;
+ <a
+ onClick={() => setMore(false)}
+ style={{ cursor: "pointer", textDecoration: "underline" }}
+ >
+ <i18n.Translate>less info</i18n.Translate>
+ </a>
+ </div>
+ <pre
+ style={
+ wrap
+ ? {
+ whiteSpace: "pre-wrap",
+ overflowWrap: "anywhere",
+ }
+ : {
+ overflow: "overlay",
+ }
+ }
+ >
+ {errorInfo}
+ </pre>
+ </Fragment>
);
}
export function ErrorAlertView({
- error: alert,
+ error,
onClose,
}: {
- error: ErrorAlert;
+ error: AlertNotification;
onClose?: () => Promise<void>;
}): VNode {
return (
- <Alert title={alert.message} severity={alert.type} onClose={onClose}>
- <div style={{ display: "flex", flexDirection: "column" }}>
- <div>{alert.description}</div>
- <AlertContext context={alert.context} cause={alert.cause} />
- </div>
- </Alert>
+ <Wrapper>
+ <AlertView alert={error} onClose={onClose} />
+ </Wrapper>
);
}
@@ -86,6 +122,9 @@ export function AlertView({
<Alert title={alert.message} severity={alert.type} onClose={onClose}>
<div style={{ display: "flex", flexDirection: "column" }}>
<div>{alert.description}</div>
+ {alert.type === "error" ? (
+ <AlertContext context={alert.context} cause={alert.cause} />
+ ) : undefined}
</div>
</Alert>
);
@@ -104,5 +143,5 @@ export function CurrentAlerts(): VNode {
}
function Wrapper({ children }: { children: ComponentChildren }): VNode {
- return <div style={{ margin: "2em" }}>{children}</div>;
+ return <div style={{ margin: "1em" }}>{children}</div>;
}
diff --git a/packages/taler-wallet-webextension/src/components/PendingTransactions.stories.tsx b/packages/taler-wallet-webextension/src/components/PendingTransactions.stories.tsx
index 2155c7aa6..d54dfe8fc 100644
--- a/packages/taler-wallet-webextension/src/components/PendingTransactions.stories.tsx
+++ b/packages/taler-wallet-webextension/src/components/PendingTransactions.stories.tsx
@@ -24,7 +24,7 @@ import {
Transaction,
TransactionType,
} from "@gnu-taler/taler-util";
-import { createExample } from "../test-utils.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
import { PendingTransactionsView as TestedComponent } from "./PendingTransactions.js";
export default {
@@ -32,7 +32,7 @@ export default {
component: TestedComponent,
};
-export const OnePendingTransaction = createExample(TestedComponent, {
+export const OnePendingTransaction = tests.createExample(TestedComponent, {
transactions: [
{
amountEffective: "USD:10",
@@ -42,7 +42,7 @@ export const OnePendingTransaction = createExample(TestedComponent, {
],
});
-export const ThreePendingTransactions = createExample(TestedComponent, {
+export const ThreePendingTransactions = tests.createExample(TestedComponent, {
transactions: [
{
amountEffective: "USD:10",
@@ -62,7 +62,7 @@ export const ThreePendingTransactions = createExample(TestedComponent, {
],
});
-export const TenPendingTransactions = createExample(TestedComponent, {
+export const TenPendingTransactions = tests.createExample(TestedComponent, {
transactions: [
{
amountEffective: "USD:10",
diff --git a/packages/taler-wallet-webextension/src/components/QR.stories.tsx b/packages/taler-wallet-webextension/src/components/QR.stories.tsx
index 83365670e..bdaa842f2 100644
--- a/packages/taler-wallet-webextension/src/components/QR.stories.tsx
+++ b/packages/taler-wallet-webextension/src/components/QR.stories.tsx
@@ -19,13 +19,13 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { createExample } from "../test-utils.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
import { QR } from "./QR.js";
export default {
title: "qr",
};
-export const Restore = createExample(QR, {
+export const Restore = tests.createExample(QR, {
text: "taler://restore/6J0RZTJC6AV21WXK87BTE67WTHE9P2QSHF2BZXTP7PDZY2ARYBPG@sync1.demo.taler.net,sync2.demo.taler.net,sync1.demo.taler.net,sync3.demo.taler.net",
});
diff --git a/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.stories.tsx b/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.stories.tsx
index 8c94e6e60..ef88d1c28 100644
--- a/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.stories.tsx
+++ b/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.stories.tsx
@@ -20,7 +20,7 @@
*/
import { WalletContractData } from "@gnu-taler/taler-wallet-core";
-import { createExample } from "../test-utils.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
import {
ErrorView,
HiddenView,
@@ -86,10 +86,10 @@ const cd: WalletContractData = {
deliveryLocation: undefined,
};
-export const ShowingSimpleOrder = createExample(ShowView, {
+export const ShowingSimpleOrder = tests.createExample(ShowView, {
contractTerms: cd,
});
-export const Error = createExample(ErrorView, {
+export const Error = tests.createExample(ErrorView, {
proposalId: "asd",
error: {
hasError: true,
@@ -103,5 +103,5 @@ export const Error = createExample(ErrorView, {
// },
},
});
-export const Loading = createExample(LoadingView, {});
-export const Hidden = createExample(HiddenView, {});
+export const Loading = tests.createExample(LoadingView, {});
+export const Hidden = tests.createExample(HiddenView, {});
diff --git a/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.tsx b/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.tsx
index 9871611f2..3e1f1dbe4 100644
--- a/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.tsx
+++ b/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.tsx
@@ -24,14 +24,14 @@ import { useState } from "preact/hooks";
import { Loading } from "../components/Loading.js";
import { Modal } from "../components/Modal.js";
import { Time } from "../components/Time.js";
-import { alertFromError } from "../context/alert.js";
+import { alertFromError, useAlertContext } from "../context/alert.js";
import { useBackendContext } from "../context/backend.js";
import { useTranslationContext } from "../context/translation.js";
import { HookError, useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { ButtonHandler } from "../mui/handlers.js";
import { compose, StateViewMap } from "../utils/index.js";
import { Amount } from "./Amount.js";
-import { AlertView } from "./CurrentAlerts.js";
+import { ErrorAlertView } from "./CurrentAlerts.js";
import { Link } from "./styled/index.js";
const ContractTermsTable = styled.table`
@@ -102,6 +102,7 @@ interface Props {
function useComponentState({ proposalId }: Props): State {
const api = useBackendContext();
const [show, setShow] = useState(false);
+ const { pushAlertOnError } = useAlertContext();
const hook = useAsyncAsHook(async () => {
if (!show) return undefined;
return await api.wallet.call(WalletApiOperation.GetContractTermsDetails, {
@@ -110,10 +111,10 @@ function useComponentState({ proposalId }: Props): State {
}, [show]);
const hideHandler = {
- onClick: async () => setShow(false),
+ onClick: pushAlertOnError(async () => setShow(false)),
};
const showHandler = {
- onClick: async () => setShow(true),
+ onClick: pushAlertOnError(async () => setShow(true)),
};
if (!show) {
return {
@@ -161,8 +162,8 @@ export function ErrorView({
const { i18n } = useTranslationContext();
return (
<Modal title="Full detail" onClose={hideHandler}>
- <AlertView
- alert={alertFromError(
+ <ErrorAlertView
+ error={alertFromError(
i18n.str`Could not load purchase proposal details`,
error,
{ proposalId },
diff --git a/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts b/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts
index c25c0ed13..541b2d39e 100644
--- a/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts
+++ b/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts
@@ -28,7 +28,7 @@ export function useComponentState({ exchangeUrl, onChange }: Props): State {
const readOnly = !onChange;
const [showContent, setShowContent] = useState<boolean>(readOnly);
const { i18n } = useTranslationContext();
- const { pushAlert } = useAlertContext();
+ const { pushAlertOnError } = useAlertContext();
/**
* For the exchange selected, bring the status of the terms of service
@@ -67,24 +67,20 @@ export function useComponentState({ exchangeUrl, onChange }: Props): State {
async function onUpdate(accepted: boolean): Promise<void> {
if (!state) return;
- try {
- if (accepted) {
- await api.wallet.call(WalletApiOperation.SetExchangeTosAccepted, {
- exchangeBaseUrl: exchangeUrl,
- etag: state.version,
- });
- } else {
- // mark as not accepted
- await api.wallet.call(WalletApiOperation.SetExchangeTosAccepted, {
- exchangeBaseUrl: exchangeUrl,
- etag: undefined,
- });
- }
- // setAccepted(accepted);
- if (!readOnly) onChange(accepted); //external update
- } catch (e) {
- pushAlert(alertFromError(i18n.str`Could not accept terms of service`, e));
+ if (accepted) {
+ await api.wallet.call(WalletApiOperation.SetExchangeTosAccepted, {
+ exchangeBaseUrl: exchangeUrl,
+ etag: state.version,
+ });
+ } else {
+ // mark as not accepted
+ await api.wallet.call(WalletApiOperation.SetExchangeTosAccepted, {
+ exchangeBaseUrl: exchangeUrl,
+ etag: undefined,
+ });
}
+ // setAccepted(accepted);
+ if (!readOnly) onChange(accepted); //external update
}
const accepted = state.status === "accepted";
@@ -94,20 +90,20 @@ export function useComponentState({ exchangeUrl, onChange }: Props): State {
showingTermsOfService: {
value: showContent,
button: {
- onClick: async () => {
+ onClick: pushAlertOnError(async () => {
setShowContent(!showContent);
- },
+ }),
},
},
terms: state,
termsAccepted: {
value: accepted,
button: {
- onClick: async () => {
+ onClick: pushAlertOnError(async () => {
const newValue = !accepted; //toggle
- onUpdate(newValue);
+ await onUpdate(newValue);
setShowContent(false);
- },
+ }),
},
},
};
diff --git a/packages/taler-wallet-webextension/src/components/TermsOfService/stories.tsx b/packages/taler-wallet-webextension/src/components/TermsOfService/stories.tsx
index 2479274cb..9ef1c4298 100644
--- a/packages/taler-wallet-webextension/src/components/TermsOfService/stories.tsx
+++ b/packages/taler-wallet-webextension/src/components/TermsOfService/stories.tsx
@@ -19,11 +19,11 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { createExample } from "../../test-utils.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
// import { ReadyView } from "./views.js";
export default {
title: "TermsOfService",
};
-// export const Ready = createExample(ReadyView, {});
+// export const Ready = tests.createExample(ReadyView, {});