add i18n where was missing
This commit is contained in:
parent
7647d077e7
commit
41850c9f14
@ -18,17 +18,23 @@
|
|||||||
* Popup shown to the user when they click
|
* Popup shown to the user when they click
|
||||||
* the Taler browser action button.
|
* the Taler browser action button.
|
||||||
*
|
*
|
||||||
* @author Florian Dold
|
* @author sebasjm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import { i18n } from "@gnu-taler/taler-util";
|
import { i18n, Translate } from "@gnu-taler/taler-util";
|
||||||
import { VNode, h } from "preact";
|
import { VNode, h } from "preact";
|
||||||
import { JustInDevMode } from "./components/JustInDevMode";
|
import { JustInDevMode } from "./components/JustInDevMode";
|
||||||
import { NavigationHeader, NavigationHeaderHolder } from "./components/styled";
|
import { NavigationHeader, NavigationHeaderHolder } from "./components/styled";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of pages used by the wallet
|
||||||
|
*
|
||||||
|
* @author sebasjm
|
||||||
|
*/
|
||||||
|
|
||||||
export enum Pages {
|
export enum Pages {
|
||||||
welcome = "/welcome",
|
welcome = "/welcome",
|
||||||
|
|
||||||
@ -60,17 +66,15 @@ export function PopupNavBar({ path = "" }: { path?: string }): VNode {
|
|||||||
: "#";
|
: "#";
|
||||||
return (
|
return (
|
||||||
<NavigationHeader>
|
<NavigationHeader>
|
||||||
<a
|
<a href="/balance" class={path.startsWith("/balance") ? "active" : ""}>
|
||||||
href="/balance"
|
<Translate>Balance</Translate>
|
||||||
class={path.startsWith("/balance") ? "active" : ""}
|
</a>
|
||||||
>{i18n.str`Balance`}</a>
|
<a href="/backup" class={path.startsWith("/backup") ? "active" : ""}>
|
||||||
<a
|
<Translate>Backup</Translate>
|
||||||
href="/backup"
|
</a>
|
||||||
class={path.startsWith("/backup") ? "active" : ""}
|
|
||||||
>{i18n.str`Backup`}</a>
|
|
||||||
<a />
|
<a />
|
||||||
<a href={innerUrl} target="_blank" rel="noreferrer">
|
<a href={innerUrl} target="_blank" rel="noreferrer">
|
||||||
<div class="settings-icon" title="Settings" />
|
<div class="settings-icon" title={i18n.str`Settings`} />
|
||||||
</a>
|
</a>
|
||||||
</NavigationHeader>
|
</NavigationHeader>
|
||||||
);
|
);
|
||||||
@ -80,20 +84,17 @@ export function WalletNavBar({ path = "" }: { path?: string }): VNode {
|
|||||||
return (
|
return (
|
||||||
<NavigationHeaderHolder>
|
<NavigationHeaderHolder>
|
||||||
<NavigationHeader>
|
<NavigationHeader>
|
||||||
<a
|
<a href="/balance" class={path.startsWith("/balance") ? "active" : ""}>
|
||||||
href="/balance"
|
<Translate>Balance</Translate>
|
||||||
class={path.startsWith("/balance") ? "active" : ""}
|
</a>
|
||||||
>{i18n.str`Balance`}</a>
|
<a href="/backup" class={path.startsWith("/backup") ? "active" : ""}>
|
||||||
<a
|
<Translate>Backup</Translate>
|
||||||
href="/backup"
|
</a>
|
||||||
class={path.startsWith("/backup") ? "active" : ""}
|
|
||||||
>{i18n.str`Backup`}</a>
|
|
||||||
|
|
||||||
<JustInDevMode>
|
<JustInDevMode>
|
||||||
<a
|
<a href="/dev" class={path.startsWith("/dev") ? "active" : ""}>
|
||||||
href="/dev"
|
<Translate>Dev</Translate>
|
||||||
class={path.startsWith("/dev") ? "active" : ""}
|
</a>
|
||||||
>{i18n.str`Dev`}</a>
|
|
||||||
</JustInDevMode>
|
</JustInDevMode>
|
||||||
|
|
||||||
<a />
|
<a />
|
||||||
@ -101,7 +102,7 @@ export function WalletNavBar({ path = "" }: { path?: string }): VNode {
|
|||||||
href="/settings"
|
href="/settings"
|
||||||
class={path.startsWith("/settings") ? "active" : ""}
|
class={path.startsWith("/settings") ? "active" : ""}
|
||||||
>
|
>
|
||||||
<div class="settings-icon" title="Settings" />
|
<Translate>Settings</Translate>
|
||||||
</a>
|
</a>
|
||||||
</NavigationHeader>
|
</NavigationHeader>
|
||||||
</NavigationHeaderHolder>
|
</NavigationHeaderHolder>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
/**
|
/**
|
||||||
* Entry point for the background page.
|
* Entry point for the background page.
|
||||||
*
|
*
|
||||||
* @author Florian Dold
|
* @author sebasjm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
/*
|
|
||||||
This file is part of TALER
|
|
||||||
(C) 2016 GNUnet e.V.
|
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
|
||||||
terms of the GNU General Public License as published by the Free Software
|
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
|
||||||
|
|
||||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.BrowserCryptoWorkerFactory = void 0;
|
|
||||||
/**
|
|
||||||
* API to access the Taler crypto worker thread.
|
|
||||||
* @author Florian Dold
|
|
||||||
*/
|
|
||||||
class BrowserCryptoWorkerFactory {
|
|
||||||
startWorker() {
|
|
||||||
const workerCtor = Worker;
|
|
||||||
const workerPath = "/browserWorkerEntry.js";
|
|
||||||
return new workerCtor(workerPath);
|
|
||||||
}
|
|
||||||
getConcurrency() {
|
|
||||||
let concurrency = 2;
|
|
||||||
try {
|
|
||||||
// only works in the browser
|
|
||||||
// tslint:disable-next-line:no-string-literal
|
|
||||||
concurrency = navigator["hardwareConcurrency"];
|
|
||||||
concurrency = Math.max(1, Math.ceil(concurrency / 2));
|
|
||||||
} catch (e) {
|
|
||||||
concurrency = 2;
|
|
||||||
}
|
|
||||||
return concurrency;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.BrowserCryptoWorkerFactory = BrowserCryptoWorkerFactory;
|
|
||||||
//# sourceMappingURL=browserCryptoWorkerFactory.js.map
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"browserCryptoWorkerFactory.js","sourceRoot":"","sources":["browserCryptoWorkerFactory.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAEH;;;GAGG;AAEH,MAAa,0BAA0B;IACrC,WAAW;QACT,MAAM,UAAU,GAAG,MAAM,CAAC;QAC1B,MAAM,UAAU,GAAG,wBAAwB,CAAC;QAC5C,OAAO,IAAI,UAAU,CAAC,UAAU,CAAiB,CAAC;IACpD,CAAC;IAED,cAAc;QACZ,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI;YACF,4BAA4B;YAC5B,6CAA6C;YAC7C,WAAW,GAAI,SAAiB,CAAC,qBAAqB,CAAC,CAAC;YACxD,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC;SACvD;QAAC,OAAO,CAAC,EAAE;YACV,WAAW,GAAG,CAAC,CAAC;SACjB;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;CACF;AAnBD,gEAmBC"}
|
|
@ -14,7 +14,7 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { PaytoUri } from "@gnu-taler/taler-util";
|
import { PaytoUri, Translate } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { CopiedIcon, CopyIcon } from "../svg";
|
import { CopiedIcon, CopyIcon } from "../svg";
|
||||||
@ -34,23 +34,23 @@ export function BankDetailsByPaytoType({
|
|||||||
amount,
|
amount,
|
||||||
}: BankDetailsProps): VNode {
|
}: BankDetailsProps): VNode {
|
||||||
const firstPart = !payto ? undefined : !payto.isKnown ? (
|
const firstPart = !payto ? undefined : !payto.isKnown ? (
|
||||||
<Row name="Account" value={payto.targetPath} />
|
<Row name={<Translate>Account</Translate>} value={payto.targetPath} />
|
||||||
) : payto.targetType === "x-taler-bank" ? (
|
) : payto.targetType === "x-taler-bank" ? (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Row name="Bank host" value={payto.host} />
|
<Row name={<Translate>Bank host</Translate>} value={payto.host} />
|
||||||
<Row name="Bank account" value={payto.account} />
|
<Row name={<Translate>Bank account</Translate>} value={payto.account} />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
) : payto.targetType === "iban" ? (
|
) : payto.targetType === "iban" ? (
|
||||||
<Row name="IBAN" value={payto.iban} />
|
<Row name={<Translate>IBAN</Translate>} value={payto.iban} />
|
||||||
) : undefined;
|
) : undefined;
|
||||||
return (
|
return (
|
||||||
<div style={{ textAlign: "left" }}>
|
<div style={{ textAlign: "left" }}>
|
||||||
<p>Bank transfer details</p>
|
<p>Bank transfer details</p>
|
||||||
<table>
|
<table>
|
||||||
{firstPart}
|
{firstPart}
|
||||||
<Row name="Exchange" value={exchangeBaseUrl} />
|
<Row name={<Translate>Exchange</Translate>} value={exchangeBaseUrl} />
|
||||||
<Row name="Chosen amount" value={amount} />
|
<Row name={<Translate>Chosen amount</Translate>} value={amount} />
|
||||||
<Row name="Subject" value={subject} literal />
|
<Row name={<Translate>Subject</Translate>} value={subject} literal />
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -61,7 +61,7 @@ function Row({
|
|||||||
value,
|
value,
|
||||||
literal,
|
literal,
|
||||||
}: {
|
}: {
|
||||||
name: string;
|
name: VNode;
|
||||||
value: string;
|
value: string;
|
||||||
literal?: boolean;
|
literal?: boolean;
|
||||||
}): VNode {
|
}): VNode {
|
||||||
|
@ -19,9 +19,9 @@ import { h, VNode } from "preact";
|
|||||||
interface Props {
|
interface Props {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
onToggle: () => void;
|
onToggle: () => void;
|
||||||
label: string;
|
label: VNode;
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: VNode;
|
||||||
}
|
}
|
||||||
export function Checkbox({
|
export function Checkbox({
|
||||||
name,
|
name,
|
||||||
|
@ -20,7 +20,7 @@ import { h, VNode } from "preact";
|
|||||||
interface Props {
|
interface Props {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
onToggle: () => void;
|
onToggle: () => void;
|
||||||
label: string;
|
label: VNode;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Translate } from "@gnu-taler/taler-util";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
|
|
||||||
export function DebugCheckbox({
|
export function DebugCheckbox({
|
||||||
@ -36,7 +37,7 @@ export function DebugCheckbox({
|
|||||||
htmlFor="checkbox-perm"
|
htmlFor="checkbox-perm"
|
||||||
style={{ marginLeft: "0.5em", fontWeight: "bold" }}
|
style={{ marginLeft: "0.5em", fontWeight: "bold" }}
|
||||||
>
|
>
|
||||||
Automatically open wallet based on page content
|
<Translate>Automatically open wallet based on page content</Translate>
|
||||||
</label>
|
</label>
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
@ -46,8 +47,12 @@ export function DebugCheckbox({
|
|||||||
marginLeft: "2em",
|
marginLeft: "2em",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
(Enabling this option below will make using the wallet faster, but
|
(
|
||||||
requires more permissions from your browser.)
|
<Translate>
|
||||||
|
Enabling this option below will make using the wallet faster, but
|
||||||
|
requires more permissions from your browser.
|
||||||
|
</Translate>
|
||||||
|
)
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { WalletDiagnostics } from "@gnu-taler/taler-util";
|
import { Translate, WalletDiagnostics } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { PageLink } from "../renderHtml";
|
import { PageLink } from "../renderHtml";
|
||||||
|
|
||||||
@ -25,7 +25,13 @@ interface Props {
|
|||||||
|
|
||||||
export function Diagnostics({ timedOut, diagnostics }: Props): VNode {
|
export function Diagnostics({ timedOut, diagnostics }: Props): VNode {
|
||||||
if (timedOut) {
|
if (timedOut) {
|
||||||
return <p>Diagnostics timed out. Could not talk to the wallet backend.</p>;
|
return (
|
||||||
|
<p>
|
||||||
|
<Translate>
|
||||||
|
Diagnostics timed out. Could not talk to the wallet backend.
|
||||||
|
</Translate>
|
||||||
|
</p>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diagnostics) {
|
if (diagnostics) {
|
||||||
@ -41,7 +47,9 @@ export function Diagnostics({ timedOut, diagnostics }: Props): VNode {
|
|||||||
paddingBottom: "0.2em",
|
paddingBottom: "0.2em",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p>Problems detected:</p>
|
<p>
|
||||||
|
<Translate>Problems detected:</Translate>
|
||||||
|
</p>
|
||||||
<ol>
|
<ol>
|
||||||
{diagnostics.errors.map((errMsg) => (
|
{diagnostics.errors.map((errMsg) => (
|
||||||
<li key={errMsg}>{errMsg}</li>
|
<li key={errMsg}>{errMsg}</li>
|
||||||
@ -49,22 +57,32 @@ export function Diagnostics({ timedOut, diagnostics }: Props): VNode {
|
|||||||
</ol>
|
</ol>
|
||||||
{diagnostics.firefoxIdbProblem ? (
|
{diagnostics.firefoxIdbProblem ? (
|
||||||
<p>
|
<p>
|
||||||
Please check in your <code>about:config</code> settings that you
|
<Translate>
|
||||||
have IndexedDB enabled (check the preference name{" "}
|
Please check in your <code>about:config</code> settings that you
|
||||||
<code>dom.indexedDB.enabled</code>).
|
have IndexedDB enabled (check the preference name{" "}
|
||||||
|
<code>dom.indexedDB.enabled</code>).
|
||||||
|
</Translate>
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
{diagnostics.dbOutdated ? (
|
{diagnostics.dbOutdated ? (
|
||||||
<p>
|
<p>
|
||||||
Your wallet database is outdated. Currently automatic migration is
|
<Translate>
|
||||||
not supported. Please go{" "}
|
Your wallet database is outdated. Currently automatic migration is
|
||||||
<PageLink pageName="/reset-required">here</PageLink> to reset the
|
not supported. Please go{" "}
|
||||||
wallet database.
|
<PageLink pageName="/reset-required">
|
||||||
|
<Translate>here</Translate>
|
||||||
|
</PageLink>{" "}
|
||||||
|
to reset the wallet database.
|
||||||
|
</Translate>
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <p>Running diagnostics ...</p>;
|
return (
|
||||||
|
<p>
|
||||||
|
<Translate>Running diagnostics</Translate> ...
|
||||||
|
</p>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Translate } from "@gnu-taler/taler-util";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
import { useRef, useState } from "preact/hooks";
|
import { useRef, useState } from "preact/hooks";
|
||||||
|
|
||||||
@ -39,7 +40,9 @@ export function EditableText({
|
|||||||
return (
|
return (
|
||||||
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
||||||
<p>{value}</p>
|
<p>{value}</p>
|
||||||
<button onClick={() => setEditing(true)}>edit</button>
|
<button onClick={() => setEditing(true)}>
|
||||||
|
<Translate>Edit</Translate>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -54,7 +57,7 @@ export function EditableText({
|
|||||||
onChange(ref.current.value).then(() => setEditing(false));
|
onChange(ref.current.value).then(() => setEditing(false));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
confirm
|
<Translate>Confirm</Translate>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
import { VNode, h } from "preact";
|
import { VNode, h, ComponentChildren } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import arrowDown from "../../static/img/chevron-down.svg";
|
import arrowDown from "../../static/img/chevron-down.svg";
|
||||||
import { ErrorBox } from "./styled";
|
import { ErrorBox } from "./styled";
|
||||||
@ -22,11 +22,10 @@ export function ErrorMessage({
|
|||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
}: {
|
}: {
|
||||||
title?: string | VNode;
|
title: VNode;
|
||||||
description?: string;
|
description?: string;
|
||||||
}): VNode | null {
|
}): VNode | null {
|
||||||
const [showErrorDetail, setShowErrorDetail] = useState(false);
|
const [showErrorDetail, setShowErrorDetail] = useState(false);
|
||||||
if (!title) return null;
|
|
||||||
return (
|
return (
|
||||||
<ErrorBox style={{ paddingTop: 0, paddingBottom: 0 }}>
|
<ErrorBox style={{ paddingTop: 0, paddingBottom: 0 }}>
|
||||||
<div>
|
<div>
|
||||||
|
@ -24,7 +24,7 @@ export function ErrorTalerOperation({
|
|||||||
title,
|
title,
|
||||||
error,
|
error,
|
||||||
}: {
|
}: {
|
||||||
title?: string;
|
title?: VNode;
|
||||||
error?: TalerErrorDetails;
|
error?: TalerErrorDetails;
|
||||||
}): VNode | null {
|
}): VNode | null {
|
||||||
const { devMode } = useDevContext();
|
const { devMode } = useDevContext();
|
||||||
|
@ -13,8 +13,13 @@
|
|||||||
You should have received a copy of the GNU General Public License along with
|
You should have received a copy of the GNU General Public License along with
|
||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
import { Translate } from "@gnu-taler/taler-util";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
|
|
||||||
export function Loading(): VNode {
|
export function Loading(): VNode {
|
||||||
return <div>Loading...</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
<Translate>Loading</Translate>...
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import { ErrorMessage } from "./ErrorMessage";
|
|||||||
import { ErrorTalerOperation } from "./ErrorTalerOperation";
|
import { ErrorTalerOperation } from "./ErrorTalerOperation";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
title: string;
|
title: VNode;
|
||||||
error: HookError;
|
error: HookError;
|
||||||
}
|
}
|
||||||
export function LoadingError({ title, error }: Props): VNode {
|
export function LoadingError({ title, error }: Props): VNode {
|
||||||
|
@ -4,7 +4,7 @@ import { ButtonBoxPrimary, ButtonPrimary, ParagraphClickable } from "./styled";
|
|||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
label: (s: string) => string;
|
label: (s: string) => VNode;
|
||||||
actions: string[];
|
actions: string[];
|
||||||
onClick: (s: string) => void;
|
onClick: (s: string) => void;
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
import { AmountLike } from "@gnu-taler/taler-util";
|
import { AmountLike } from "@gnu-taler/taler-util";
|
||||||
import { ExtraLargeText, LargeText, SmallLightText } from "./styled";
|
import { ExtraLargeText, LargeText, SmallLightText } from "./styled";
|
||||||
import { h } from "preact";
|
import { h, VNode } from "preact";
|
||||||
|
|
||||||
export type Kind = "positive" | "negative" | "neutral";
|
export type Kind = "positive" | "negative" | "neutral";
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string;
|
title: VNode;
|
||||||
text: AmountLike;
|
text: AmountLike;
|
||||||
kind: Kind;
|
kind: Kind;
|
||||||
big?: boolean;
|
big?: boolean;
|
||||||
|
@ -14,13 +14,14 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Translate } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { NiceSelect } from "./styled";
|
import { NiceSelect } from "./styled";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
value?: string;
|
value?: string;
|
||||||
onChange: (s: string) => void;
|
onChange: (s: string) => void;
|
||||||
label: string;
|
label: VNode;
|
||||||
list: {
|
list: {
|
||||||
[label: string]: string;
|
[label: string]: string;
|
||||||
};
|
};
|
||||||
@ -58,7 +59,7 @@ export function SelectList({
|
|||||||
{value === undefined ||
|
{value === undefined ||
|
||||||
(canBeNull && (
|
(canBeNull && (
|
||||||
<option selected disabled>
|
<option selected disabled>
|
||||||
Select one option
|
<Translate>Select one option</Translate>
|
||||||
</option>
|
</option>
|
||||||
// ) : (
|
// ) : (
|
||||||
// <option selected>{list[value]}</option>
|
// <option selected>{list[value]}</option>
|
||||||
|
@ -21,6 +21,7 @@ import {
|
|||||||
Timestamp,
|
Timestamp,
|
||||||
Transaction,
|
Transaction,
|
||||||
TransactionType,
|
TransactionType,
|
||||||
|
Translate,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
import imageBank from "../../static/img/ri-bank-line.svg";
|
import imageBank from "../../static/img/ri-bank-line.svg";
|
||||||
@ -133,7 +134,7 @@ function TransactionLayout(props: TransactionLayoutProps): VNode {
|
|||||||
</LargeText>
|
</LargeText>
|
||||||
{props.pending && (
|
{props.pending && (
|
||||||
<LightText style={{ marginTop: 5, marginBottom: 5 }}>
|
<LightText style={{ marginTop: 5, marginBottom: 5 }}>
|
||||||
Waiting for confirmation
|
<Translate>Waiting for confirmation</Translate>
|
||||||
</LightText>
|
</LightText>
|
||||||
)}
|
)}
|
||||||
<SmallLightText style={{ marginTop: 5 }}>
|
<SmallLightText style={{ marginTop: 5 }}>
|
||||||
@ -195,7 +196,11 @@ function TransactionAmount(props: TransactionAmountProps): VNode {
|
|||||||
{sign}
|
{sign}
|
||||||
{Amounts.stringifyValue(props.amount)}
|
{Amounts.stringifyValue(props.amount)}
|
||||||
</ExtraLargeText>
|
</ExtraLargeText>
|
||||||
{props.pending && <div>PENDING</div>}
|
{props.pending && (
|
||||||
|
<div>
|
||||||
|
<Translate>PENDING</Translate>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ import {
|
|||||||
NotificationType,
|
NotificationType,
|
||||||
PreparePayResult,
|
PreparePayResult,
|
||||||
PreparePayResultType,
|
PreparePayResultType,
|
||||||
|
Translate,
|
||||||
} 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";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
@ -108,7 +109,11 @@ export function DepositPage({ talerPayUri, goBack }: Props): VNode {
|
|||||||
}, [talerPayUri, foundAmountStr]);
|
}, [talerPayUri, foundAmountStr]);
|
||||||
|
|
||||||
if (!talerPayUri) {
|
if (!talerPayUri) {
|
||||||
return <span>missing pay uri</span>;
|
return (
|
||||||
|
<span>
|
||||||
|
<Translate>missing pay uri</Translate>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!payStatus) {
|
if (!payStatus) {
|
||||||
@ -116,10 +121,16 @@ export function DepositPage({ talerPayUri, goBack }: Props): VNode {
|
|||||||
return (
|
return (
|
||||||
<WalletAction>
|
<WalletAction>
|
||||||
<LogoHeader />
|
<LogoHeader />
|
||||||
<h2>{i18n.str`Digital cash payment`}</h2>
|
<h2>
|
||||||
|
<Translate>Digital cash payment</Translate>
|
||||||
|
</h2>
|
||||||
<section>
|
<section>
|
||||||
<ErrorTalerOperation
|
<ErrorTalerOperation
|
||||||
title="Could not get the payment information for this order"
|
title={
|
||||||
|
<Translate>
|
||||||
|
Could not get the payment information for this order
|
||||||
|
</Translate>
|
||||||
|
}
|
||||||
error={payErrMsg?.operationError}
|
error={payErrMsg?.operationError}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
@ -130,15 +141,25 @@ export function DepositPage({ talerPayUri, goBack }: Props): VNode {
|
|||||||
return (
|
return (
|
||||||
<WalletAction>
|
<WalletAction>
|
||||||
<LogoHeader />
|
<LogoHeader />
|
||||||
<h2>{i18n.str`Digital cash payment`}</h2>
|
<h2>
|
||||||
|
<Translate>Digital cash payment</Translate>
|
||||||
|
</h2>
|
||||||
<section>
|
<section>
|
||||||
<p>Could not get the payment information for this order</p>
|
<p>
|
||||||
|
<Translate>
|
||||||
|
Could not get the payment information for this order
|
||||||
|
</Translate>
|
||||||
|
</p>
|
||||||
<ErrorBox>{payErrMsg}</ErrorBox>
|
<ErrorBox>{payErrMsg}</ErrorBox>
|
||||||
</section>
|
</section>
|
||||||
</WalletAction>
|
</WalletAction>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return <span>Loading payment information ...</span>;
|
return (
|
||||||
|
<span>
|
||||||
|
<Translate>Loading payment information</Translate> ...
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const onClick = async (): Promise<void> => {
|
const onClick = async (): Promise<void> => {
|
||||||
@ -183,20 +204,32 @@ export function PaymentRequestView({
|
|||||||
<WalletAction>
|
<WalletAction>
|
||||||
<LogoHeader />
|
<LogoHeader />
|
||||||
|
|
||||||
<h2>{i18n.str`Digital cash deposit`}</h2>
|
<h2>
|
||||||
|
<Translate>Digital cash deposit</Translate>
|
||||||
|
</h2>
|
||||||
{payStatus.status === PreparePayResultType.AlreadyConfirmed &&
|
{payStatus.status === PreparePayResultType.AlreadyConfirmed &&
|
||||||
(payStatus.paid ? (
|
(payStatus.paid ? (
|
||||||
<SuccessBox> Already paid </SuccessBox>
|
<SuccessBox>
|
||||||
|
<Translate>Already paid</Translate>
|
||||||
|
</SuccessBox>
|
||||||
) : (
|
) : (
|
||||||
<WarningBox> Already claimed </WarningBox>
|
<WarningBox>
|
||||||
|
<Translate>Already claimed</Translate>
|
||||||
|
</WarningBox>
|
||||||
))}
|
))}
|
||||||
{payResult && payResult.type === ConfirmPayResultType.Done && (
|
{payResult && payResult.type === ConfirmPayResultType.Done && (
|
||||||
<SuccessBox>
|
<SuccessBox>
|
||||||
<h3>Payment complete</h3>
|
<h3>
|
||||||
|
<Translate>Payment complete</Translate>
|
||||||
|
</h3>
|
||||||
<p>
|
<p>
|
||||||
{!payResult.contractTerms.fulfillment_message
|
{!payResult.contractTerms.fulfillment_message ? (
|
||||||
? "You will now be sent back to the merchant you came from."
|
<Translate>
|
||||||
: payResult.contractTerms.fulfillment_message}
|
You will now be sent back to the merchant you came from.
|
||||||
|
</Translate>
|
||||||
|
) : (
|
||||||
|
payResult.contractTerms.fulfillment_message
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
</SuccessBox>
|
</SuccessBox>
|
||||||
)}
|
)}
|
||||||
@ -205,7 +238,7 @@ export function PaymentRequestView({
|
|||||||
Amounts.isNonZero(totalFees) && (
|
Amounts.isNonZero(totalFees) && (
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Total to pay"
|
title={<Translate>Total to pay</Translate>}
|
||||||
text={amountToPretty(
|
text={amountToPretty(
|
||||||
Amounts.parseOrThrow(payStatus.amountEffective),
|
Amounts.parseOrThrow(payStatus.amountEffective),
|
||||||
)}
|
)}
|
||||||
@ -214,7 +247,7 @@ export function PaymentRequestView({
|
|||||||
)}
|
)}
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Purchase amount"
|
title={<Translate>Purchase amount</Translate>}
|
||||||
text={amountToPretty(Amounts.parseOrThrow(payStatus.amountRaw))}
|
text={amountToPretty(Amounts.parseOrThrow(payStatus.amountRaw))}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
@ -222,21 +255,25 @@ export function PaymentRequestView({
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Fee"
|
title={<Translate>Fee</Translate>}
|
||||||
text={amountToPretty(totalFees)}
|
text={amountToPretty(totalFees)}
|
||||||
kind="negative"
|
kind="negative"
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
<Part
|
<Part
|
||||||
title="Merchant"
|
title={<Translate>Merchant</Translate>}
|
||||||
text={contractTerms.merchant.name}
|
text={contractTerms.merchant.name}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
<Part title="Purchase" text={contractTerms.summary} kind="neutral" />
|
<Part
|
||||||
|
title={<Translate>Purchase</Translate>}
|
||||||
|
text={contractTerms.summary}
|
||||||
|
kind="neutral"
|
||||||
|
/>
|
||||||
{contractTerms.order_id && (
|
{contractTerms.order_id && (
|
||||||
<Part
|
<Part
|
||||||
title="Receipt"
|
title={<Translate>Receipt</Translate>}
|
||||||
text={`#${contractTerms.order_id}`}
|
text={`#${contractTerms.order_id}`}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
|
@ -37,10 +37,12 @@ import {
|
|||||||
PreparePayResult,
|
PreparePayResult,
|
||||||
PreparePayResultType,
|
PreparePayResultType,
|
||||||
Product,
|
Product,
|
||||||
|
Translate,
|
||||||
} 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";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
|
import { ErrorMessage } from "../components/ErrorMessage";
|
||||||
import { Loading } from "../components/Loading";
|
import { Loading } from "../components/Loading";
|
||||||
import { LoadingError } from "../components/LoadingError";
|
import { LoadingError } from "../components/LoadingError";
|
||||||
import { LogoHeader } from "../components/LogoHeader";
|
import { LogoHeader } from "../components/LogoHeader";
|
||||||
@ -106,7 +108,12 @@ export function PayPage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hook.hasError) {
|
if (hook.hasError) {
|
||||||
return <LoadingError title="Could not load pay status" error={hook} />;
|
return (
|
||||||
|
<LoadingError
|
||||||
|
title={<Translate>Could not load pay status</Translate>}
|
||||||
|
error={hook}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const foundBalance = hook.response.balance.balances.find(
|
const foundBalance = hook.response.balance.balances.find(
|
||||||
@ -178,9 +185,13 @@ export function PaymentRequestView({
|
|||||||
|
|
||||||
if (!contractTerms) {
|
if (!contractTerms) {
|
||||||
return (
|
return (
|
||||||
<span>
|
<ErrorMessage
|
||||||
Error: did not get contract terms from merchant or wallet backend.
|
title={
|
||||||
</span>
|
<Translate>
|
||||||
|
Could not load contract terms from merchant or wallet backend.
|
||||||
|
</Translate>
|
||||||
|
}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,13 +203,6 @@ export function PaymentRequestView({
|
|||||||
totalFees = Amounts.sub(amountEffective, amountRaw).amount;
|
totalFees = Amounts.sub(amountEffective, amountRaw).amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// let merchantName: VNode;
|
|
||||||
// if (contractTerms.merchant && contractTerms.merchant.name) {
|
|
||||||
// merchantName = <strong>{contractTerms.merchant.name}</strong>;
|
|
||||||
// } else {
|
|
||||||
// merchantName = <strong>(pub: {contractTerms.merchant_pub})</strong>;
|
|
||||||
// }
|
|
||||||
|
|
||||||
function Alternative(): VNode {
|
function Alternative(): VNode {
|
||||||
const [showQR, setShowQR] = useState<boolean>(false);
|
const [showQR, setShowQR] = useState<boolean>(false);
|
||||||
const privateUri =
|
const privateUri =
|
||||||
@ -209,12 +213,21 @@ export function PaymentRequestView({
|
|||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<LinkSuccess upperCased onClick={() => setShowQR((qr) => !qr)}>
|
<LinkSuccess upperCased onClick={() => setShowQR((qr) => !qr)}>
|
||||||
{!showQR ? i18n.str`Pay with a mobile phone` : i18n.str`Hide QR`}
|
{!showQR ? (
|
||||||
|
<Translate>Pay with a mobile phone</Translate>
|
||||||
|
) : (
|
||||||
|
<Translate>Hide QR</Translate>
|
||||||
|
)}
|
||||||
</LinkSuccess>
|
</LinkSuccess>
|
||||||
{showQR && (
|
{showQR && (
|
||||||
<div>
|
<div>
|
||||||
<QR text={privateUri} />
|
<QR text={privateUri} />
|
||||||
Scan the QR code or <a href={privateUri}>click here</a>
|
<Translate>
|
||||||
|
Scan the QR code or
|
||||||
|
<a href={privateUri}>
|
||||||
|
<Translate>click here</Translate>
|
||||||
|
</a>
|
||||||
|
</Translate>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
@ -227,7 +240,9 @@ export function PaymentRequestView({
|
|||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<div>
|
<div>
|
||||||
<p>Processing...</p>
|
<p>
|
||||||
|
<Translate>Processing</Translate>...
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
@ -239,7 +254,9 @@ export function PaymentRequestView({
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<section>
|
<section>
|
||||||
<ButtonSuccess upperCased onClick={onClick}>
|
<ButtonSuccess upperCased onClick={onClick}>
|
||||||
{i18n.str`Pay`} {amountToString(payStatus.amountEffective)}
|
<Translate>
|
||||||
|
Pay {amountToString(payStatus.amountEffective)}
|
||||||
|
</Translate>
|
||||||
</ButtonSuccess>
|
</ButtonSuccess>
|
||||||
</section>
|
</section>
|
||||||
<Alternative />
|
<Alternative />
|
||||||
@ -252,18 +269,22 @@ export function PaymentRequestView({
|
|||||||
<section>
|
<section>
|
||||||
{balance ? (
|
{balance ? (
|
||||||
<WarningBox>
|
<WarningBox>
|
||||||
Your balance of {amountToString(balance)} is not enough to pay
|
<Translate>
|
||||||
for this purchase
|
Your balance of {amountToString(balance)} is not enough to pay
|
||||||
|
for this purchase
|
||||||
|
</Translate>
|
||||||
</WarningBox>
|
</WarningBox>
|
||||||
) : (
|
) : (
|
||||||
<WarningBox>
|
<WarningBox>
|
||||||
Your balance is not enough to pay for this purchase.
|
<Translate>
|
||||||
|
Your balance is not enough to pay for this purchase.
|
||||||
|
</Translate>
|
||||||
</WarningBox>
|
</WarningBox>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<ButtonSuccess upperCased onClick={goToWalletManualWithdraw}>
|
<ButtonSuccess upperCased onClick={goToWalletManualWithdraw}>
|
||||||
{i18n.str`Withdraw digital cash`}
|
<Translate>Withdraw digital cash</Translate>
|
||||||
</ButtonSuccess>
|
</ButtonSuccess>
|
||||||
</section>
|
</section>
|
||||||
<Alternative />
|
<Alternative />
|
||||||
@ -276,7 +297,7 @@ export function PaymentRequestView({
|
|||||||
<section>
|
<section>
|
||||||
{payStatus.paid && contractTerms.fulfillment_message && (
|
{payStatus.paid && contractTerms.fulfillment_message && (
|
||||||
<Part
|
<Part
|
||||||
title="Merchant message"
|
title={<Translate>Merchant message</Translate>}
|
||||||
text={contractTerms.fulfillment_message}
|
text={contractTerms.fulfillment_message}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
@ -293,31 +314,48 @@ export function PaymentRequestView({
|
|||||||
<WalletAction>
|
<WalletAction>
|
||||||
<LogoHeader />
|
<LogoHeader />
|
||||||
|
|
||||||
<h2>{i18n.str`Digital cash payment`}</h2>
|
<h2>
|
||||||
|
<Translate>Digital cash payment</Translate>
|
||||||
|
</h2>
|
||||||
{payStatus.status === PreparePayResultType.AlreadyConfirmed &&
|
{payStatus.status === PreparePayResultType.AlreadyConfirmed &&
|
||||||
(payStatus.paid ? (
|
(payStatus.paid ? (
|
||||||
payStatus.contractTerms.fulfillment_url ? (
|
payStatus.contractTerms.fulfillment_url ? (
|
||||||
<SuccessBox>
|
<SuccessBox>
|
||||||
Already paid, you are going to be redirected to{" "}
|
<Translate>
|
||||||
<a href={payStatus.contractTerms.fulfillment_url}>
|
Already paid, you are going to be redirected to{" "}
|
||||||
{payStatus.contractTerms.fulfillment_url}
|
<a href={payStatus.contractTerms.fulfillment_url}>
|
||||||
</a>
|
{payStatus.contractTerms.fulfillment_url}
|
||||||
|
</a>
|
||||||
|
</Translate>
|
||||||
</SuccessBox>
|
</SuccessBox>
|
||||||
) : (
|
) : (
|
||||||
<SuccessBox> Already paid </SuccessBox>
|
<SuccessBox>
|
||||||
|
<Translate>Already paid</Translate>
|
||||||
|
</SuccessBox>
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<WarningBox> Already claimed </WarningBox>
|
<WarningBox>
|
||||||
|
<Translate>Already claimed</Translate>
|
||||||
|
</WarningBox>
|
||||||
))}
|
))}
|
||||||
{payResult && payResult.type === ConfirmPayResultType.Done && (
|
{payResult && payResult.type === ConfirmPayResultType.Done && (
|
||||||
<SuccessBox>
|
<SuccessBox>
|
||||||
<h3>Payment complete</h3>
|
<h3>
|
||||||
|
<Translate>Payment complete</Translate>
|
||||||
|
</h3>
|
||||||
<p>
|
<p>
|
||||||
{!payResult.contractTerms.fulfillment_message
|
{!payResult.contractTerms.fulfillment_message ? (
|
||||||
? payResult.contractTerms.fulfillment_url
|
payResult.contractTerms.fulfillment_url ? (
|
||||||
? `You are going to be redirected to ${payResult.contractTerms.fulfillment_url}`
|
<Translate>
|
||||||
: "You can close this page."
|
You are going to be redirected to $
|
||||||
: payResult.contractTerms.fulfillment_message}
|
{payResult.contractTerms.fulfillment_url}
|
||||||
|
</Translate>
|
||||||
|
) : (
|
||||||
|
<Translate>You can close this page.</Translate>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
payResult.contractTerms.fulfillment_message
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
</SuccessBox>
|
</SuccessBox>
|
||||||
)}
|
)}
|
||||||
@ -326,14 +364,14 @@ export function PaymentRequestView({
|
|||||||
Amounts.isNonZero(totalFees) && (
|
Amounts.isNonZero(totalFees) && (
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Total to pay"
|
title={<Translate>Total to pay</Translate>}
|
||||||
text={amountToString(payStatus.amountEffective)}
|
text={amountToString(payStatus.amountEffective)}
|
||||||
kind="negative"
|
kind="negative"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Purchase amount"
|
title={<Translate>Purchase amount</Translate>}
|
||||||
text={amountToString(payStatus.amountRaw)}
|
text={amountToString(payStatus.amountRaw)}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
@ -341,21 +379,25 @@ export function PaymentRequestView({
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Fee"
|
title={<Translate>Fee</Translate>}
|
||||||
text={amountToString(totalFees)}
|
text={amountToString(totalFees)}
|
||||||
kind="negative"
|
kind="negative"
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
<Part
|
<Part
|
||||||
title="Merchant"
|
title={<Translate>Merchant</Translate>}
|
||||||
text={contractTerms.merchant.name}
|
text={contractTerms.merchant.name}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
<Part title="Purchase" text={contractTerms.summary} kind="neutral" />
|
<Part
|
||||||
|
title={<Translate>Purchase</Translate>}
|
||||||
|
text={contractTerms.summary}
|
||||||
|
kind="neutral"
|
||||||
|
/>
|
||||||
{contractTerms.order_id && (
|
{contractTerms.order_id && (
|
||||||
<Part
|
<Part
|
||||||
title="Receipt"
|
title={<Translate>Receipt</Translate>}
|
||||||
text={`#${contractTerms.order_id}`}
|
text={`#${contractTerms.order_id}`}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
@ -373,7 +415,7 @@ function ProductList({ products }: { products: Product[] }): VNode {
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<SmallLightText style={{ margin: ".5em" }}>
|
<SmallLightText style={{ margin: ".5em" }}>
|
||||||
List of products
|
<Translate>List of products</Translate>
|
||||||
</SmallLightText>
|
</SmallLightText>
|
||||||
<dl>
|
<dl>
|
||||||
{products.map((p, i) => {
|
{products.map((p, i) => {
|
||||||
@ -415,15 +457,18 @@ function ProductList({ products }: { products: Product[] }): VNode {
|
|||||||
{p.quantity ?? 1} x {p.description}
|
{p.quantity ?? 1} x {p.description}
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
Total{` `}
|
<Translate>Total</Translate>
|
||||||
{p.price
|
{` `}
|
||||||
? `${Amounts.stringifyValue(
|
{p.price ? (
|
||||||
Amounts.mult(
|
`${Amounts.stringifyValue(
|
||||||
Amounts.parseOrThrow(p.price),
|
Amounts.mult(
|
||||||
p.quantity ?? 1,
|
Amounts.parseOrThrow(p.price),
|
||||||
).amount,
|
p.quantity ?? 1,
|
||||||
)} ${p}`
|
).amount,
|
||||||
: "free"}
|
)} ${p}`
|
||||||
|
) : (
|
||||||
|
<Translate>free</Translate>
|
||||||
|
)}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,10 +17,10 @@
|
|||||||
/**
|
/**
|
||||||
* Page that shows refund status for purchases.
|
* Page that shows refund status for purchases.
|
||||||
*
|
*
|
||||||
* @author Florian Dold
|
* @author sebasjm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Amounts, ApplyRefundResponse } from "@gnu-taler/taler-util";
|
import { Amounts, ApplyRefundResponse, Translate } from "@gnu-taler/taler-util";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { AmountView } from "../renderHtml";
|
import { AmountView } from "../renderHtml";
|
||||||
@ -37,20 +37,28 @@ export function View({ applyResult }: ViewProps): VNode {
|
|||||||
<section class="main">
|
<section class="main">
|
||||||
<h1>GNU Taler Wallet</h1>
|
<h1>GNU Taler Wallet</h1>
|
||||||
<article class="fade">
|
<article class="fade">
|
||||||
<h2>Refund Status</h2>
|
<h2>
|
||||||
|
<Translate>Refund Status</Translate>
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
The product <em>{applyResult.info.summary}</em> has received a total
|
<Translate>
|
||||||
effective refund of{" "}
|
The product <em>{applyResult.info.summary}</em> has received a total
|
||||||
|
effective refund of{" "}
|
||||||
|
</Translate>
|
||||||
<AmountView amount={applyResult.amountRefundGranted} />.
|
<AmountView amount={applyResult.amountRefundGranted} />.
|
||||||
</p>
|
</p>
|
||||||
{applyResult.pendingAtExchange ? (
|
{applyResult.pendingAtExchange ? (
|
||||||
<p>Refund processing is still in progress.</p>
|
<p>
|
||||||
|
<Translate>Refund processing is still in progress.</Translate>
|
||||||
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
{!Amounts.isZero(applyResult.amountRefundGone) ? (
|
{!Amounts.isZero(applyResult.amountRefundGone) ? (
|
||||||
<p>
|
<p>
|
||||||
The refund amount of{" "}
|
<Translate>
|
||||||
<AmountView amount={applyResult.amountRefundGone} /> could not be
|
The refund amount of{" "}
|
||||||
applied.
|
<AmountView amount={applyResult.amountRefundGone} /> could not be
|
||||||
|
applied.
|
||||||
|
</Translate>
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
</article>
|
</article>
|
||||||
@ -82,15 +90,27 @@ export function RefundPage({ talerRefundUri }: Props): VNode {
|
|||||||
console.log("rendering");
|
console.log("rendering");
|
||||||
|
|
||||||
if (!talerRefundUri) {
|
if (!talerRefundUri) {
|
||||||
return <span>missing taler refund uri</span>;
|
return (
|
||||||
|
<span>
|
||||||
|
<Translate>missing taler refund uri</Translate>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errMsg) {
|
if (errMsg) {
|
||||||
return <span>Error: {errMsg}</span>;
|
return (
|
||||||
|
<span>
|
||||||
|
<Translate>Error: {errMsg}</Translate>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!applyResult) {
|
if (!applyResult) {
|
||||||
return <span>Updating refund status</span>;
|
return (
|
||||||
|
<span>
|
||||||
|
<Translate>Updating refund status</Translate>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <View applyResult={applyResult} />;
|
return <View applyResult={applyResult} />;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { i18n } from "@gnu-taler/taler-util";
|
import { i18n, Translate } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { CheckboxOutlined } from "../components/CheckboxOutlined";
|
import { CheckboxOutlined } from "../components/CheckboxOutlined";
|
||||||
import { ExchangeXmlTos } from "../components/ExchangeToS";
|
import { ExchangeXmlTos } from "../components/ExchangeToS";
|
||||||
@ -34,7 +34,7 @@ export function TermsOfServiceSection({
|
|||||||
{terms.status === "notfound" && (
|
{terms.status === "notfound" && (
|
||||||
<section>
|
<section>
|
||||||
<WarningText>
|
<WarningText>
|
||||||
{i18n.str`Exchange doesn't have terms of service`}
|
<Translate>Exchange doesn't have terms of service</Translate>
|
||||||
</WarningText>
|
</WarningText>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
@ -46,21 +46,21 @@ export function TermsOfServiceSection({
|
|||||||
{terms.status === "notfound" && (
|
{terms.status === "notfound" && (
|
||||||
<section>
|
<section>
|
||||||
<WarningText>
|
<WarningText>
|
||||||
{i18n.str`Exchange doesn't have terms of service`}
|
<Translate>Exchange doesn't have terms of service</Translate>
|
||||||
</WarningText>
|
</WarningText>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
{terms.status === "new" && (
|
{terms.status === "new" && (
|
||||||
<section>
|
<section>
|
||||||
<ButtonSuccess upperCased onClick={() => onReview(true)}>
|
<ButtonSuccess upperCased onClick={() => onReview(true)}>
|
||||||
{i18n.str`Review exchange terms of service`}
|
<Translate>Review exchange terms of service</Translate>
|
||||||
</ButtonSuccess>
|
</ButtonSuccess>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
{terms.status === "changed" && (
|
{terms.status === "changed" && (
|
||||||
<section>
|
<section>
|
||||||
<ButtonWarning upperCased onClick={() => onReview(true)}>
|
<ButtonWarning upperCased onClick={() => onReview(true)}>
|
||||||
{i18n.str`Review new version of terms of service`}
|
<Translate>Review new version of terms of service</Translate>
|
||||||
</ButtonWarning>
|
</ButtonWarning>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
@ -72,7 +72,7 @@ export function TermsOfServiceSection({
|
|||||||
{onReview && (
|
{onReview && (
|
||||||
<section>
|
<section>
|
||||||
<LinkSuccess upperCased onClick={() => onReview(true)}>
|
<LinkSuccess upperCased onClick={() => onReview(true)}>
|
||||||
{i18n.str`Show terms of service`}
|
<Translate>Show terms of service</Translate>
|
||||||
</LinkSuccess>
|
</LinkSuccess>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
@ -80,7 +80,9 @@ export function TermsOfServiceSection({
|
|||||||
<CheckboxOutlined
|
<CheckboxOutlined
|
||||||
name="terms"
|
name="terms"
|
||||||
enabled={reviewed}
|
enabled={reviewed}
|
||||||
label={i18n.str`I accept the exchange terms of service`}
|
label={
|
||||||
|
<Translate>I accept the exchange terms of service</Translate>
|
||||||
|
}
|
||||||
onToggle={() => {
|
onToggle={() => {
|
||||||
onAccept(!reviewed);
|
onAccept(!reviewed);
|
||||||
if (onReview) onReview(false);
|
if (onReview) onReview(false);
|
||||||
@ -95,7 +97,9 @@ export function TermsOfServiceSection({
|
|||||||
{terms.status !== "notfound" && !terms.content && (
|
{terms.status !== "notfound" && !terms.content && (
|
||||||
<section>
|
<section>
|
||||||
<WarningBox>
|
<WarningBox>
|
||||||
The exchange reply with a empty terms of service
|
<Translate>
|
||||||
|
The exchange reply with a empty terms of service
|
||||||
|
</Translate>
|
||||||
</WarningBox>
|
</WarningBox>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
@ -116,7 +120,7 @@ export function TermsOfServiceSection({
|
|||||||
)}
|
)}
|
||||||
{terms.content.type === "pdf" && (
|
{terms.content.type === "pdf" && (
|
||||||
<a href={terms.content.location.toString()} download="tos.pdf">
|
<a href={terms.content.location.toString()} download="tos.pdf">
|
||||||
Download Terms of Service
|
<Translate>Download Terms of Service</Translate>
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
@ -124,7 +128,7 @@ export function TermsOfServiceSection({
|
|||||||
{reviewed && onReview && (
|
{reviewed && onReview && (
|
||||||
<section>
|
<section>
|
||||||
<LinkSuccess upperCased onClick={() => onReview(false)}>
|
<LinkSuccess upperCased onClick={() => onReview(false)}>
|
||||||
{i18n.str`Hide terms of service`}
|
<Translate>Hide terms of service</Translate>
|
||||||
</LinkSuccess>
|
</LinkSuccess>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
@ -133,7 +137,9 @@ export function TermsOfServiceSection({
|
|||||||
<CheckboxOutlined
|
<CheckboxOutlined
|
||||||
name="terms"
|
name="terms"
|
||||||
enabled={reviewed}
|
enabled={reviewed}
|
||||||
label={i18n.str`I accept the exchange terms of service`}
|
label={
|
||||||
|
<Translate>I accept the exchange terms of service</Translate>
|
||||||
|
}
|
||||||
onToggle={() => {
|
onToggle={() => {
|
||||||
onAccept(!reviewed);
|
onAccept(!reviewed);
|
||||||
if (onReview) onReview(false);
|
if (onReview) onReview(false);
|
||||||
|
@ -17,10 +17,10 @@
|
|||||||
/**
|
/**
|
||||||
* Page shown to the user to accept or ignore a tip from a merchant.
|
* Page shown to the user to accept or ignore a tip from a merchant.
|
||||||
*
|
*
|
||||||
* @author Florian Dold <dold@taler.net>
|
* @author sebasjm <dold@taler.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { PrepareTipResult } from "@gnu-taler/taler-util";
|
import { PrepareTipResult, Translate } from "@gnu-taler/taler-util";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { Loading } from "../components/Loading";
|
import { Loading } from "../components/Loading";
|
||||||
@ -46,21 +46,29 @@ export function View({
|
|||||||
<article class="fade">
|
<article class="fade">
|
||||||
{prepareTipResult.accepted ? (
|
{prepareTipResult.accepted ? (
|
||||||
<span>
|
<span>
|
||||||
Tip from <code>{prepareTipResult.merchantBaseUrl}</code> accepted.
|
<Translate>
|
||||||
Check your transactions list for more details.
|
Tip from <code>{prepareTipResult.merchantBaseUrl}</code> accepted.
|
||||||
|
Check your transactions list for more details.
|
||||||
|
</Translate>
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
The merchant <code>{prepareTipResult.merchantBaseUrl}</code> is
|
<Translate>
|
||||||
offering you a tip of{" "}
|
The merchant <code>{prepareTipResult.merchantBaseUrl}</code> is
|
||||||
<strong>
|
offering you a tip of{" "}
|
||||||
<AmountView amount={prepareTipResult.tipAmountEffective} />
|
<strong>
|
||||||
</strong>{" "}
|
<AmountView amount={prepareTipResult.tipAmountEffective} />
|
||||||
via the exchange <code>{prepareTipResult.exchangeBaseUrl}</code>
|
</strong>{" "}
|
||||||
|
via the exchange <code>{prepareTipResult.exchangeBaseUrl}</code>
|
||||||
|
</Translate>
|
||||||
</p>
|
</p>
|
||||||
<button onClick={onAccept}>Accept tip</button>
|
<button onClick={onAccept}>
|
||||||
<button onClick={onIgnore}>Ignore</button>
|
<Translate>Accept tip</Translate>
|
||||||
|
</button>
|
||||||
|
<button onClick={onIgnore}>
|
||||||
|
<Translate>Ignore</Translate>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</article>
|
</article>
|
||||||
@ -98,11 +106,19 @@ export function TipPage({ talerTipUri }: Props): VNode {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (!talerTipUri) {
|
if (!talerTipUri) {
|
||||||
return <span>missing tip uri</span>;
|
return (
|
||||||
|
<span>
|
||||||
|
<Translate>missing tip uri</Translate>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tipIgnored) {
|
if (tipIgnored) {
|
||||||
return <span>You've ignored the tip.</span>;
|
return (
|
||||||
|
<span>
|
||||||
|
<Translate>You've ignored the tip.</Translate>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prepareTipResult) {
|
if (!prepareTipResult) {
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
* Page shown to the user to confirm creation
|
* Page shown to the user to confirm creation
|
||||||
* of a reserve, usually requested by the bank.
|
* of a reserve, usually requested by the bank.
|
||||||
*
|
*
|
||||||
* @author Florian Dold
|
* @author sebasjm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -26,6 +26,7 @@ import {
|
|||||||
Amounts,
|
Amounts,
|
||||||
ExchangeListItem,
|
ExchangeListItem,
|
||||||
i18n,
|
i18n,
|
||||||
|
Translate,
|
||||||
WithdrawUriInfoResponse,
|
WithdrawUriInfoResponse,
|
||||||
} 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";
|
||||||
@ -117,37 +118,46 @@ export function View({
|
|||||||
return (
|
return (
|
||||||
<WalletAction>
|
<WalletAction>
|
||||||
<LogoHeader />
|
<LogoHeader />
|
||||||
<h2>{i18n.str`Digital cash withdrawal`}</h2>
|
<h2>
|
||||||
|
<Translate>Digital cash withdrawal</Translate>
|
||||||
|
</h2>
|
||||||
|
|
||||||
{withdrawError && (
|
{withdrawError && (
|
||||||
<ErrorTalerOperation
|
<ErrorTalerOperation
|
||||||
title="Could not finish the withdrawal operation"
|
title={
|
||||||
|
<Translate>Could not finish the withdrawal operation</Translate>
|
||||||
|
}
|
||||||
error={withdrawError.operationError}
|
error={withdrawError.operationError}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<Part
|
<Part
|
||||||
title="Total to withdraw"
|
title={<Translate>Total to withdraw</Translate>}
|
||||||
text={amountToString(Amounts.sub(amount, withdrawalFee).amount)}
|
text={amountToString(Amounts.sub(amount, withdrawalFee).amount)}
|
||||||
kind="positive"
|
kind="positive"
|
||||||
/>
|
/>
|
||||||
{Amounts.isNonZero(withdrawalFee) && (
|
{Amounts.isNonZero(withdrawalFee) && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Part
|
<Part
|
||||||
title="Chosen amount"
|
title={<Translate>Chosen amount</Translate>}
|
||||||
text={amountToString(amount)}
|
text={amountToString(amount)}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
<Part
|
<Part
|
||||||
title="Exchange fee"
|
title={<Translate>Exchange fee</Translate>}
|
||||||
text={amountToString(withdrawalFee)}
|
text={amountToString(withdrawalFee)}
|
||||||
kind="negative"
|
kind="negative"
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
{exchangeBaseUrl && (
|
{exchangeBaseUrl && (
|
||||||
<Part title="Exchange" text={exchangeBaseUrl} kind="neutral" big />
|
<Part
|
||||||
|
title={<Translate>Exchange</Translate>}
|
||||||
|
text={exchangeBaseUrl}
|
||||||
|
kind="neutral"
|
||||||
|
big
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
{!reviewing && (
|
{!reviewing && (
|
||||||
@ -156,7 +166,7 @@ export function View({
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<div>
|
<div>
|
||||||
<SelectList
|
<SelectList
|
||||||
label="Known exchanges"
|
label={<Translate>Known exchanges</Translate>}
|
||||||
list={exchanges}
|
list={exchanges}
|
||||||
value={nextExchange}
|
value={nextExchange}
|
||||||
name="switchingExchange"
|
name="switchingExchange"
|
||||||
@ -172,14 +182,16 @@ export function View({
|
|||||||
setSwitchingExchange(false);
|
setSwitchingExchange(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{nextExchange === undefined
|
{nextExchange === undefined ? (
|
||||||
? i18n.str`Cancel exchange selection`
|
<Translate>Cancel exchange selection</Translate>
|
||||||
: i18n.str`Confirm exchange selection`}
|
) : (
|
||||||
|
<Translate>Confirm exchange selection</Translate>
|
||||||
|
)}
|
||||||
</LinkSuccess>
|
</LinkSuccess>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
) : (
|
) : (
|
||||||
<LinkSuccess upperCased onClick={() => setSwitchingExchange(true)}>
|
<LinkSuccess upperCased onClick={() => setSwitchingExchange(true)}>
|
||||||
{i18n.str`Switch exchange`}
|
<Translate>Switch exchange</Translate>
|
||||||
</LinkSuccess>
|
</LinkSuccess>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
@ -198,7 +210,7 @@ export function View({
|
|||||||
disabled={!exchangeBaseUrl || confirmDisabled}
|
disabled={!exchangeBaseUrl || confirmDisabled}
|
||||||
onClick={doWithdrawAndCheckError}
|
onClick={doWithdrawAndCheckError}
|
||||||
>
|
>
|
||||||
{i18n.str`Confirm withdrawal`}
|
<Translate>Confirm withdrawal</Translate>
|
||||||
</ButtonSuccess>
|
</ButtonSuccess>
|
||||||
)}
|
)}
|
||||||
{terms.status === "notfound" && (
|
{terms.status === "notfound" && (
|
||||||
@ -207,7 +219,7 @@ export function View({
|
|||||||
disabled={!exchangeBaseUrl}
|
disabled={!exchangeBaseUrl}
|
||||||
onClick={doWithdrawAndCheckError}
|
onClick={doWithdrawAndCheckError}
|
||||||
>
|
>
|
||||||
{i18n.str`Withdraw anyway`}
|
<Translate>Withdraw anyway</Translate>
|
||||||
</ButtonWarning>
|
</ButtonWarning>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
@ -270,7 +282,7 @@ export function WithdrawPageWithParsedURI({
|
|||||||
if (detailsHook.hasError) {
|
if (detailsHook.hasError) {
|
||||||
return (
|
return (
|
||||||
<LoadingError
|
<LoadingError
|
||||||
title="Could not load the withdrawal details"
|
title={<Translate>Could not load the withdrawal details</Translate>}
|
||||||
error={detailsHook}
|
error={detailsHook}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -293,9 +305,7 @@ export function WithdrawPageWithParsedURI({
|
|||||||
|
|
||||||
const onWithdraw = async (): Promise<void> => {
|
const onWithdraw = async (): Promise<void> => {
|
||||||
if (!exchange) return;
|
if (!exchange) return;
|
||||||
console.log("accepting exchange", exchange);
|
|
||||||
const res = await wxApi.acceptWithdrawal(uri, exchange);
|
const res = await wxApi.acceptWithdrawal(uri, exchange);
|
||||||
console.log("accept withdrawal response", res);
|
|
||||||
if (res.confirmTransferUrl) {
|
if (res.confirmTransferUrl) {
|
||||||
document.location.href = res.confirmTransferUrl;
|
document.location.href = res.confirmTransferUrl;
|
||||||
}
|
}
|
||||||
@ -327,7 +337,7 @@ export function WithdrawPage({ talerWithdrawUri }: Props): VNode {
|
|||||||
if (!talerWithdrawUri) {
|
if (!talerWithdrawUri) {
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
<i18n.Translate>missing withdraw uri</i18n.Translate>
|
<Translate>missing withdraw uri</Translate>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -337,7 +347,7 @@ export function WithdrawPage({ talerWithdrawUri }: Props): VNode {
|
|||||||
if (uriInfoHook.hasError) {
|
if (uriInfoHook.hasError) {
|
||||||
return (
|
return (
|
||||||
<LoadingError
|
<LoadingError
|
||||||
title="Could not get the info from the URI"
|
title={<Translate>Could not get the info from the URI</Translate>}
|
||||||
error={uriInfoHook}
|
error={uriInfoHook}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of TALER
|
|
||||||
(C) 2017 Inria
|
|
||||||
|
|
||||||
TALER is free software; you can redistribute it and/or modify it under the
|
|
||||||
terms of the GNU General Public License as published by the Free Software
|
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
|
||||||
|
|
||||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { h, VNode } from "preact";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* View and edit auditors.
|
|
||||||
*
|
|
||||||
* @author Florian Dold
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Imports.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export function makePaybackPage(): VNode {
|
|
||||||
return <div>not implemented</div>;
|
|
||||||
}
|
|
@ -17,9 +17,10 @@
|
|||||||
/**
|
/**
|
||||||
* Page to inform the user when a database reset is required.
|
* Page to inform the user when a database reset is required.
|
||||||
*
|
*
|
||||||
* @author Florian Dold
|
* @author sebasjm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Translate } from "@gnu-taler/taler-util";
|
||||||
import { Component, h, VNode } from "preact";
|
import { Component, h, VNode } from "preact";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
|
||||||
@ -49,14 +50,20 @@ class ResetNotification extends Component<any, State> {
|
|||||||
if (this.state.resetRequired) {
|
if (this.state.resetRequired) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>Manual Reset Required</h1>
|
<h1>
|
||||||
|
<Translate>Manual Reset Required</Translate>
|
||||||
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
The wallet's database in your browser is incompatible with the{" "}
|
<Translate>
|
||||||
currently installed wallet. Please reset manually.
|
The wallet's database in your browser is incompatible with
|
||||||
|
the currently installed wallet. Please reset manually.
|
||||||
|
</Translate>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Once the database format has stabilized, we will provide automatic
|
<Translate>
|
||||||
upgrades.
|
Once the database format has stabilized, we will provide automatic
|
||||||
|
upgrades.
|
||||||
|
</Translate>
|
||||||
</p>
|
</p>
|
||||||
<input
|
<input
|
||||||
id="check"
|
id="check"
|
||||||
@ -67,7 +74,7 @@ class ResetNotification extends Component<any, State> {
|
|||||||
}}
|
}}
|
||||||
/>{" "}
|
/>{" "}
|
||||||
<label htmlFor="check">
|
<label htmlFor="check">
|
||||||
I understand that I will lose all my data
|
<Translate>I understand that I will lose all my data</Translate>
|
||||||
</label>
|
</label>
|
||||||
<br />
|
<br />
|
||||||
<button
|
<button
|
||||||
@ -75,15 +82,21 @@ class ResetNotification extends Component<any, State> {
|
|||||||
disabled={!this.state.checked}
|
disabled={!this.state.checked}
|
||||||
onClick={() => wxApi.resetDb()}
|
onClick={() => wxApi.resetDb()}
|
||||||
>
|
>
|
||||||
Reset
|
<Translate>Reset</Translate>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>Everything is fine!</h1>A reset is not required anymore, you can
|
<h1>
|
||||||
close this page.
|
<Translate>Everything is fine!</Translate>
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
<Translate>
|
||||||
|
A reset is not required anymore, you can close this page.
|
||||||
|
</Translate>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -14,16 +14,21 @@
|
|||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Translate } from "@gnu-taler/taler-util";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
/**
|
/**
|
||||||
* Return coins to own bank account.
|
* Return coins to own bank account.
|
||||||
*
|
*
|
||||||
* @author Florian Dold
|
* @author sebasjm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
export function createReturnCoinsPage(): VNode {
|
export function createReturnCoinsPage(): VNode {
|
||||||
return <span>Not implemented yet.</span>;
|
return (
|
||||||
|
<span>
|
||||||
|
<Translate>Not implemented yet.</Translate>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -17,275 +17,38 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: src/NavigationBar.tsx:86
|
#: src/NavigationBar.tsx:71
|
||||||
#, c-format
|
|
||||||
msgid "Balance"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/NavigationBar.tsx:87
|
|
||||||
#, c-format
|
|
||||||
msgid "Pending"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/NavigationBar.tsx:88
|
|
||||||
#, c-format
|
|
||||||
msgid "Backup"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/NavigationBar.tsx:89
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/NavigationBar.tsx:90
|
#: src/popup/DeveloperPage.tsx:377
|
||||||
#, c-format
|
|
||||||
msgid "Dev"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/BackupPage.tsx:127
|
|
||||||
#, c-format
|
|
||||||
msgid "Add provider"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/BackupPage.tsx:137
|
|
||||||
#, c-format
|
|
||||||
msgid "Sync all backups"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/BackupPage.tsx:139
|
|
||||||
#, c-format
|
|
||||||
msgid "Sync now"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/popup/BalancePage.tsx:79
|
|
||||||
#, c-format
|
|
||||||
msgid "You have no balance to show. Need some %1$s getting started?"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ProviderAddPage.tsx:145
|
|
||||||
#, c-format
|
|
||||||
msgid "< Back"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ProviderAddPage.tsx:156
|
|
||||||
#, c-format
|
|
||||||
msgid "Next"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:57
|
|
||||||
#, c-format
|
|
||||||
msgid "Loading..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:64
|
|
||||||
#, c-format
|
|
||||||
msgid "There was an error loading the provider detail for \"%1$s\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:75
|
|
||||||
#, c-format
|
|
||||||
msgid "There is not known provider with url \"%1$s\". Redirecting back..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:131
|
|
||||||
#, c-format
|
|
||||||
msgid "Back up"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:142
|
|
||||||
#, c-format
|
|
||||||
msgid "Extend"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:148
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"terms has changed, extending the service will imply accepting the new terms of "
|
"Do you want to IRREVOCABLY DESTROY everything inside your wallet and LOSE ALL "
|
||||||
"service"
|
"YOUR COINS?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:158
|
#: src/wallet/CreateManualWithdraw.tsx:102
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "old"
|
msgid "Manual Withdrawal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:162
|
#: src/wallet/CreateManualWithdraw.tsx:104
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "new"
|
msgid ""
|
||||||
|
"Choose a exchange from where the coins will be withdrawn. The exchange\n"
|
||||||
|
" will send the coins to this wallet after receiving a wire transfer\n"
|
||||||
|
" with the correct subject."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:169
|
#: src/wallet/CreateManualWithdraw.tsx:109
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "fee"
|
msgid "No exchange configured"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:177
|
#: src/wallet/CreateManualWithdraw.tsx:111
|
||||||
#, c-format
|
|
||||||
msgid "storage"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:190
|
|
||||||
#, c-format
|
|
||||||
msgid "< back"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:194
|
|
||||||
#, c-format
|
|
||||||
msgid "remove provider"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:213
|
|
||||||
#, c-format
|
|
||||||
msgid "There is conflict with another backup from %1$s"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:228
|
|
||||||
#, c-format
|
|
||||||
msgid "Unknown backup problem: %1$s"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ProviderDetailPage.tsx:247
|
|
||||||
#, c-format
|
|
||||||
msgid "service paid"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/popup/Settings.tsx:46
|
|
||||||
#, c-format
|
|
||||||
msgid "Permissions"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/TermsOfServiceSection.tsx:37
|
|
||||||
#, c-format
|
|
||||||
msgid "Exchange doesn't have terms of service"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/TermsOfServiceSection.tsx:56
|
|
||||||
#, c-format
|
|
||||||
msgid "Review exchange terms of service"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/TermsOfServiceSection.tsx:63
|
|
||||||
#, c-format
|
|
||||||
msgid "Review new version of terms of service"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/TermsOfServiceSection.tsx:75
|
|
||||||
#, c-format
|
|
||||||
msgid "Show terms of service"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/TermsOfServiceSection.tsx:83
|
|
||||||
#, c-format
|
|
||||||
msgid "I accept the exchange terms of service"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/TermsOfServiceSection.tsx:127
|
|
||||||
#, c-format
|
|
||||||
msgid "Hide terms of service"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ExchangeAddConfirm.tsx:110
|
|
||||||
#, c-format
|
|
||||||
msgid "Cancel"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ExchangeAddConfirm.tsx:114
|
|
||||||
#, c-format
|
|
||||||
msgid "Loading terms.."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/ExchangeAddConfirm.tsx:121
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Add exchange"
|
msgid "Add exchange"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/wallet/ExchangeAddConfirm.tsx:131
|
|
||||||
#, c-format
|
|
||||||
msgid "Add exchange anyway"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/Settings.tsx:95
|
|
||||||
#, c-format
|
|
||||||
msgid "Known exchanges"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/Transaction.tsx:159
|
|
||||||
#, c-format
|
|
||||||
msgid "retry"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/Transaction.tsx:163
|
|
||||||
#, c-format
|
|
||||||
msgid "Forget"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/wallet/Transaction.tsx:198
|
|
||||||
#, c-format
|
|
||||||
msgid "Confirm"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/Pay.tsx:211
|
|
||||||
#, c-format
|
|
||||||
msgid "Pay with a mobile phone"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/Pay.tsx:211
|
|
||||||
#, c-format
|
|
||||||
msgid "Hide QR"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/Pay.tsx:241
|
|
||||||
#, c-format
|
|
||||||
msgid "Pay"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/Pay.tsx:265
|
|
||||||
#, c-format
|
|
||||||
msgid "Withdraw digital cash"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/Pay.tsx:295
|
|
||||||
#, c-format
|
|
||||||
msgid "Digital cash payment"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/Withdraw.tsx:101
|
|
||||||
#, c-format
|
|
||||||
msgid "Digital cash withdrawal"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/Withdraw.tsx:149
|
|
||||||
#, c-format
|
|
||||||
msgid "Cancel exchange selection"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/Withdraw.tsx:150
|
|
||||||
#, c-format
|
|
||||||
msgid "Confirm exchange selection"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/Withdraw.tsx:155
|
|
||||||
#, c-format
|
|
||||||
msgid "Switch exchange"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/Withdraw.tsx:174
|
|
||||||
#, c-format
|
|
||||||
msgid "Confirm withdrawal"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/Withdraw.tsx:183
|
|
||||||
#, c-format
|
|
||||||
msgid "Withdraw anyway"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/Withdraw.tsx:310
|
|
||||||
#, c-format
|
|
||||||
msgid "missing withdraw uri"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/cta/Deposit.tsx:186
|
|
||||||
#, c-format
|
|
||||||
msgid "Digital cash deposit"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Amounts, Balance } from "@gnu-taler/taler-util";
|
import { Amounts, Balance, Translate } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import { BalanceTable } from "../components/BalanceTable";
|
import { BalanceTable } from "../components/BalanceTable";
|
||||||
@ -47,7 +47,12 @@ export function BalancePage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state.hasError) {
|
if (state.hasError) {
|
||||||
return <LoadingError title="Could not load balance page" error={state} />;
|
return (
|
||||||
|
<LoadingError
|
||||||
|
title={<Translate>Could not load balance page</Translate>}
|
||||||
|
error={state}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addingAction) {
|
if (addingAction) {
|
||||||
@ -99,17 +104,19 @@ export function BalanceView({
|
|||||||
</section>
|
</section>
|
||||||
<footer style={{ justifyContent: "space-between" }}>
|
<footer style={{ justifyContent: "space-between" }}>
|
||||||
<ButtonPrimary onClick={goToWalletManualWithdraw}>
|
<ButtonPrimary onClick={goToWalletManualWithdraw}>
|
||||||
Withdraw
|
<Translate>Withdraw</Translate>
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
{currencyWithNonZeroAmount.length > 0 && (
|
{currencyWithNonZeroAmount.length > 0 && (
|
||||||
<MultiActionButton
|
<MultiActionButton
|
||||||
label={(s) => `Deposit ${s}`}
|
label={(s) => <Translate>Deposit {s}</Translate>}
|
||||||
actions={currencyWithNonZeroAmount}
|
actions={currencyWithNonZeroAmount}
|
||||||
onClick={(c) => goToWalletDeposit(c)}
|
onClick={(c) => goToWalletDeposit(c)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<JustInDevMode>
|
<JustInDevMode>
|
||||||
<ButtonBoxPrimary onClick={goToAddAction}>enter uri</ButtonBoxPrimary>
|
<ButtonBoxPrimary onClick={goToAddAction}>
|
||||||
|
<Translate>Enter URI</Translate>
|
||||||
|
</ButtonBoxPrimary>
|
||||||
</JustInDevMode>
|
</JustInDevMode>
|
||||||
</footer>
|
</footer>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -20,6 +20,8 @@ import {
|
|||||||
CoinDumpJson,
|
CoinDumpJson,
|
||||||
ExchangeListItem,
|
ExchangeListItem,
|
||||||
NotificationType,
|
NotificationType,
|
||||||
|
Translate,
|
||||||
|
i18n,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { PendingTaskInfo } from "@gnu-taler/taler-wallet-core";
|
import { PendingTaskInfo } from "@gnu-taler/taler-wallet-core";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
@ -31,7 +33,6 @@ import { Time } from "../components/Time";
|
|||||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
||||||
import { useDiagnostics } from "../hooks/useDiagnostics";
|
import { useDiagnostics } from "../hooks/useDiagnostics";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
import BalanceStories from "./Balance.stories";
|
|
||||||
|
|
||||||
export function DeveloperPage(): VNode {
|
export function DeveloperPage(): VNode {
|
||||||
const [status, timedOut] = useDiagnostics();
|
const [status, timedOut] = useDiagnostics();
|
||||||
@ -149,10 +150,16 @@ export function View({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>Debug tools:</p>
|
<p>
|
||||||
<button onClick={confirmReset}>reset</button>
|
<Translate>Debug tools</Translate>:
|
||||||
|
</p>
|
||||||
|
<button onClick={confirmReset}>
|
||||||
|
<Translate>reset</Translate>
|
||||||
|
</button>
|
||||||
<br />
|
<br />
|
||||||
<button onClick={() => fileRef?.current?.click()}>import database</button>
|
<button onClick={() => fileRef?.current?.click()}>
|
||||||
|
<Translate>import database</Translate>
|
||||||
|
</button>
|
||||||
<input
|
<input
|
||||||
ref={fileRef}
|
ref={fileRef}
|
||||||
style={{ display: "none" }}
|
style={{ display: "none" }}
|
||||||
@ -171,31 +178,36 @@ export function View({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<button onClick={onExportDatabase}>export database</button>
|
<button onClick={onExportDatabase}>
|
||||||
|
<Translate>export database</Translate>
|
||||||
|
</button>
|
||||||
{downloadedDatabase && (
|
{downloadedDatabase && (
|
||||||
<div>
|
<div>
|
||||||
Database exported at
|
<Translate>
|
||||||
<Time
|
Database exported at
|
||||||
timestamp={{ t_ms: downloadedDatabase.time.getTime() }}
|
<Time
|
||||||
format="yyyy/MM/dd HH:mm:ss"
|
timestamp={{ t_ms: downloadedDatabase.time.getTime() }}
|
||||||
/>
|
format="yyyy/MM/dd HH:mm:ss"
|
||||||
<a
|
/>
|
||||||
href={`data:text/plain;charset=utf-8;base64,${toBase64(
|
<a
|
||||||
downloadedDatabase.content,
|
href={`data:text/plain;charset=utf-8;base64,${toBase64(
|
||||||
)}`}
|
downloadedDatabase.content,
|
||||||
download={`taler-wallet-database-${format(
|
)}`}
|
||||||
downloadedDatabase.time,
|
download={`taler-wallet-database-${format(
|
||||||
"yyyy/MM/dd_HH:mm",
|
downloadedDatabase.time,
|
||||||
)}.json`}
|
"yyyy/MM/dd_HH:mm",
|
||||||
>
|
)}.json`}
|
||||||
{" "}
|
>
|
||||||
click here{" "}
|
<Translate>click here</Translate>
|
||||||
</a>
|
</a>
|
||||||
to download
|
to download
|
||||||
|
</Translate>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<br />
|
<br />
|
||||||
<p>Coins:</p>
|
<p>
|
||||||
|
<Translate>Coins</Translate>:
|
||||||
|
</p>
|
||||||
{Object.keys(money_by_exchange).map((ex) => {
|
{Object.keys(money_by_exchange).map((ex) => {
|
||||||
const allcoins = money_by_exchange[ex];
|
const allcoins = money_by_exchange[ex];
|
||||||
allcoins.sort((a, b) => {
|
allcoins.sort((a, b) => {
|
||||||
@ -220,7 +232,9 @@ export function View({
|
|||||||
<Diagnostics diagnostics={status} timedOut={timedOut} />
|
<Diagnostics diagnostics={status} timedOut={timedOut} />
|
||||||
{operations && operations.length > 0 && (
|
{operations && operations.length > 0 && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<p>Pending operations</p>
|
<p>
|
||||||
|
<Translate>Pending operations</Translate>
|
||||||
|
</p>
|
||||||
<dl>
|
<dl>
|
||||||
{operations.reverse().map((o) => {
|
{operations.reverse().map((o) => {
|
||||||
return (
|
return (
|
||||||
@ -257,18 +271,30 @@ function ShowAllCoins({
|
|||||||
<b>{ex}</b>: {total} {currencies[ex]}
|
<b>{ex}</b>: {total} {currencies[ex]}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<b>usable coins</b>
|
<b>
|
||||||
|
<Translate>usable coins</Translate>
|
||||||
|
</b>
|
||||||
</p>
|
</p>
|
||||||
{collapsedUnspent ? (
|
{collapsedUnspent ? (
|
||||||
<div onClick={() => setCollapsedUnspent(false)}>click to show</div>
|
<div onClick={() => setCollapsedUnspent(false)}>click to show</div>
|
||||||
) : (
|
) : (
|
||||||
<table onClick={() => setCollapsedUnspent(true)}>
|
<table onClick={() => setCollapsedUnspent(true)}>
|
||||||
<tr>
|
<tr>
|
||||||
<td>id</td>
|
<td>
|
||||||
<td>denom</td>
|
<Translate>id</Translate>
|
||||||
<td>value</td>
|
</td>
|
||||||
<td>status</td>
|
<td>
|
||||||
<td>from refresh?</td>
|
<Translate>denom</Translate>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Translate>value</Translate>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Translate>status</Translate>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Translate>from refresh?</Translate>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{coins.usable.map((c) => {
|
{coins.usable.map((c) => {
|
||||||
return (
|
return (
|
||||||
@ -283,17 +309,31 @@ function ShowAllCoins({
|
|||||||
})}
|
})}
|
||||||
</table>
|
</table>
|
||||||
)}
|
)}
|
||||||
<p>spent coins</p>
|
<p>
|
||||||
|
<Translate>spent coins</Translate>
|
||||||
|
</p>
|
||||||
{collapsedSpent ? (
|
{collapsedSpent ? (
|
||||||
<div onClick={() => setCollapsedSpent(false)}>click to show</div>
|
<div onClick={() => setCollapsedSpent(false)}>
|
||||||
|
<Translate>click to show</Translate>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<table onClick={() => setCollapsedSpent(true)}>
|
<table onClick={() => setCollapsedSpent(true)}>
|
||||||
<tr>
|
<tr>
|
||||||
<td>id</td>
|
<td>
|
||||||
<td>denom</td>
|
<Translate>id</Translate>
|
||||||
<td>value</td>
|
</td>
|
||||||
<td>status</td>
|
<td>
|
||||||
<td>refresh?</td>
|
<Translate>denom</Translate>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Translate>value</Translate>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Translate>status</Translate>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Translate>from refresh?</Translate>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{coins.spent.map((c) => {
|
{coins.spent.map((c) => {
|
||||||
return (
|
return (
|
||||||
@ -335,8 +375,7 @@ function runIntegrationTest() {}
|
|||||||
export async function confirmReset(): Promise<void> {
|
export async function confirmReset(): Promise<void> {
|
||||||
if (
|
if (
|
||||||
confirm(
|
confirm(
|
||||||
"Do you want to IRREVOCABLY DESTROY everything inside your" +
|
i18n.str`Do you want to IRREVOCABLY DESTROY everything inside your wallet and LOSE ALL YOUR COINS?`,
|
||||||
" wallet and LOSE ALL YOUR COINS?",
|
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
await wxApi.resetDb();
|
await wxApi.resetDb();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { i18n } from "@gnu-taler/taler-util";
|
import { Translate } from "@gnu-taler/taler-util";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
import { ButtonBoxWarning, WarningBox } from "../components/styled";
|
import { ButtonBoxWarning, WarningBox } from "../components/styled";
|
||||||
|
|
||||||
@ -11,16 +11,16 @@ export function NoBalanceHelp({
|
|||||||
<WarningBox>
|
<WarningBox>
|
||||||
<p>
|
<p>
|
||||||
<b>
|
<b>
|
||||||
<i18n.Translate>You have no balance to show.</i18n.Translate>
|
<Translate>You have no balance to show.</Translate>
|
||||||
</b>
|
</b>
|
||||||
<br />
|
<br />
|
||||||
<i18n.Translate>
|
<Translate>
|
||||||
To withdraw money you can start from your bank site or click the
|
To withdraw money you can start from your bank site or click the
|
||||||
"withdraw" button to use a known exchange.
|
"withdraw" button to use a known exchange.
|
||||||
</i18n.Translate>
|
</Translate>
|
||||||
</p>
|
</p>
|
||||||
<ButtonBoxWarning onClick={() => goToWalletManualWithdraw()}>
|
<ButtonBoxWarning onClick={() => goToWalletManualWithdraw()}>
|
||||||
Withdraw
|
<Translate>Withdraw</Translate>
|
||||||
</ButtonBoxWarning>
|
</ButtonBoxWarning>
|
||||||
</WarningBox>
|
</WarningBox>
|
||||||
);
|
);
|
||||||
|
@ -19,7 +19,11 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { classifyTalerUri, TalerUriType } from "@gnu-taler/taler-util";
|
import {
|
||||||
|
classifyTalerUri,
|
||||||
|
TalerUriType,
|
||||||
|
Translate,
|
||||||
|
} from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h } from "preact";
|
import { Fragment, h } from "preact";
|
||||||
import { ButtonPrimary, ButtonSuccess } from "../components/styled";
|
import { ButtonPrimary, ButtonSuccess } from "../components/styled";
|
||||||
import { actionForTalerUri } from "../utils/index";
|
import { actionForTalerUri } from "../utils/index";
|
||||||
@ -52,46 +56,56 @@ export function TalerActionFound({ url, onDismiss }: Props) {
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<section>
|
<section>
|
||||||
<h1>Taler Action </h1>
|
<h1>
|
||||||
|
<Translate>Taler Action</Translate>
|
||||||
|
</h1>
|
||||||
{uriType === TalerUriType.TalerPay && (
|
{uriType === TalerUriType.TalerPay && (
|
||||||
<div>
|
<div>
|
||||||
<p>This page has pay action.</p>
|
<p>
|
||||||
|
<Translate>This page has pay action.</Translate>
|
||||||
|
</p>
|
||||||
<ButtonSuccess
|
<ButtonSuccess
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigateTo(actionForTalerUri(uriType, url));
|
navigateTo(actionForTalerUri(uriType, url));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Open pay page
|
<Translate>Open pay page</Translate>
|
||||||
</ButtonSuccess>
|
</ButtonSuccess>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{uriType === TalerUriType.TalerWithdraw && (
|
{uriType === TalerUriType.TalerWithdraw && (
|
||||||
<div>
|
<div>
|
||||||
<p>This page has a withdrawal action.</p>
|
<p>
|
||||||
|
<Translate>This page has a withdrawal action.</Translate>
|
||||||
|
</p>
|
||||||
<ButtonSuccess
|
<ButtonSuccess
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigateTo(actionForTalerUri(uriType, url));
|
navigateTo(actionForTalerUri(uriType, url));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Open withdraw page
|
<Translate>Open withdraw page</Translate>
|
||||||
</ButtonSuccess>
|
</ButtonSuccess>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{uriType === TalerUriType.TalerTip && (
|
{uriType === TalerUriType.TalerTip && (
|
||||||
<div>
|
<div>
|
||||||
<p>This page has a tip action.</p>
|
<p>
|
||||||
|
<Translate>This page has a tip action.</Translate>
|
||||||
|
</p>
|
||||||
<ButtonSuccess
|
<ButtonSuccess
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigateTo(actionForTalerUri(uriType, url));
|
navigateTo(actionForTalerUri(uriType, url));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Open tip page
|
<Translate>Open tip page</Translate>
|
||||||
</ButtonSuccess>
|
</ButtonSuccess>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{uriType === TalerUriType.TalerNotifyReserve && (
|
{uriType === TalerUriType.TalerNotifyReserve && (
|
||||||
<div>
|
<div>
|
||||||
<p>This page has a notify reserve action.</p>
|
<p>
|
||||||
|
<Translate>This page has a notify reserve action.</Translate>
|
||||||
|
</p>
|
||||||
<ButtonSuccess
|
<ButtonSuccess
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigateTo(actionForTalerUri(uriType, url));
|
navigateTo(actionForTalerUri(uriType, url));
|
||||||
@ -103,26 +117,33 @@ export function TalerActionFound({ url, onDismiss }: Props) {
|
|||||||
)}
|
)}
|
||||||
{uriType === TalerUriType.TalerRefund && (
|
{uriType === TalerUriType.TalerRefund && (
|
||||||
<div>
|
<div>
|
||||||
<p>This page has a refund action.</p>
|
<p>
|
||||||
|
<Translate>This page has a refund action.</Translate>
|
||||||
|
</p>
|
||||||
<ButtonSuccess
|
<ButtonSuccess
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigateTo(actionForTalerUri(uriType, url));
|
navigateTo(actionForTalerUri(uriType, url));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Open refund page
|
<Translate>Open refund page</Translate>
|
||||||
</ButtonSuccess>
|
</ButtonSuccess>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{uriType === TalerUriType.Unknown && (
|
{uriType === TalerUriType.Unknown && (
|
||||||
<div>
|
<div>
|
||||||
<p>This page has a malformed taler uri.</p>
|
<p>
|
||||||
|
<Translate>This page has a malformed taler uri.</Translate>
|
||||||
|
</p>
|
||||||
<p>{url}</p>
|
<p>{url}</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
<div />
|
<div />
|
||||||
<ButtonPrimary onClick={() => onDismiss()}> Dismiss </ButtonPrimary>
|
<ButtonPrimary onClick={() => onDismiss()}>
|
||||||
|
{" "}
|
||||||
|
<Translate>Dismiss</Translate>{" "}
|
||||||
|
</ButtonPrimary>
|
||||||
</footer>
|
</footer>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
@ -17,10 +17,10 @@
|
|||||||
/**
|
/**
|
||||||
* Main entry point for extension pages.
|
* Main entry point for extension pages.
|
||||||
*
|
*
|
||||||
* @author Florian Dold <dold@taler.net>
|
* @author sebasjm <dold@taler.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { setupI18n } from "@gnu-taler/taler-util";
|
import { setupI18n, Translate } from "@gnu-taler/taler-util";
|
||||||
import { createHashHistory } from "history";
|
import { createHashHistory } from "history";
|
||||||
import { Fragment, h, render, VNode } from "preact";
|
import { Fragment, h, render, VNode } from "preact";
|
||||||
import Router, { route, Route } from "preact-router";
|
import Router, { route, Route } from "preact-router";
|
||||||
@ -87,27 +87,20 @@ function Application(): VNode {
|
|||||||
<CheckTalerActionComponent />
|
<CheckTalerActionComponent />
|
||||||
<PopupBox devMode={devMode}>
|
<PopupBox devMode={devMode}>
|
||||||
<Router history={hash_history}>
|
<Router history={hash_history}>
|
||||||
<Route path={Pages.dev} component={DeveloperPage} />
|
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={Pages.balance}
|
path={Pages.balance}
|
||||||
component={BalancePage}
|
component={BalancePage}
|
||||||
goToWalletManualWithdraw={() =>
|
goToWalletManualWithdraw={() =>
|
||||||
goToWalletPage(
|
route(Pages.balance_manual_withdraw.replace(":currency?", ""))
|
||||||
Pages.balance_manual_withdraw.replace(":currency?", ""),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
goToWalletDeposit={(currency: string) =>
|
goToWalletDeposit={(currency: string) =>
|
||||||
goToWalletPage(
|
route(Pages.balance_deposit.replace(":currency", currency))
|
||||||
Pages.balance_deposit.replace(":currency", currency),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
goToWalletHistory={(currency: string) =>
|
goToWalletHistory={(currency: string) =>
|
||||||
goToWalletPage(
|
route(Pages.balance_history.replace(":currency", currency))
|
||||||
Pages.balance_history.replace(":currency", currency),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={Pages.cta}
|
path={Pages.cta}
|
||||||
component={function Action({ action }: { action: string }) {
|
component={function Action({ action }: { action: string }) {
|
||||||
@ -139,21 +132,29 @@ function Application(): VNode {
|
|||||||
route(Pages.backup);
|
route(Pages.backup);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Route
|
|
||||||
path={Pages.backup_provider_add}
|
|
||||||
component={ProviderAddPage}
|
|
||||||
onBack={() => {
|
|
||||||
route(Pages.backup);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={Pages.settings_exchange_add}
|
path={Pages.balance_manual_withdraw}
|
||||||
component={ExchangeAddPage}
|
component={RedirectToWalletPage}
|
||||||
onBack={() => {
|
|
||||||
route(Pages.balance);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path={Pages.balance_deposit}
|
||||||
|
component={RedirectToWalletPage}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path={Pages.balance_history}
|
||||||
|
component={RedirectToWalletPage}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path={Pages.backup_provider_add}
|
||||||
|
component={RedirectToWalletPage}
|
||||||
|
/>
|
||||||
|
<Route path={Pages.settings} component={RedirectToWalletPage} />
|
||||||
|
<Route
|
||||||
|
path={Pages.settings_exchange_add}
|
||||||
|
component={RedirectToWalletPage}
|
||||||
|
/>
|
||||||
|
<Route path={Pages.dev} component={RedirectToWalletPage} />
|
||||||
|
|
||||||
<Route default component={Redirect} to={Pages.balance} />
|
<Route default component={Redirect} to={Pages.balance} />
|
||||||
</Router>
|
</Router>
|
||||||
@ -165,15 +166,26 @@ function Application(): VNode {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function goToWalletPage(page: Pages | string): Promise<void> {
|
function RedirectToWalletPage(): VNode {
|
||||||
// eslint-disable-next-line no-undef
|
const page = document.location.hash || "#/";
|
||||||
await chrome.tabs.create({
|
useEffect(() => {
|
||||||
active: true,
|
chrome.tabs
|
||||||
// eslint-disable-next-line no-undef
|
.create({
|
||||||
url: chrome.runtime.getURL(`/static/wallet.html#${page}`),
|
active: true,
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
url: chrome.runtime.getURL(`/static/wallet.html${page}`),
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
window.close();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
window.close();
|
return (
|
||||||
// return null;
|
<span>
|
||||||
|
<Translate>
|
||||||
|
this popup is being closed and you are being redirected to {page}
|
||||||
|
</Translate>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Redirect({ to }: { to: string }): null {
|
function Redirect({ to }: { to: string }): null {
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
import { classifyTalerUri, TalerUriType } from "@gnu-taler/taler-util";
|
import {
|
||||||
|
classifyTalerUri,
|
||||||
|
TalerUriType,
|
||||||
|
Translate,
|
||||||
|
} from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import { Button, ButtonSuccess, InputWithLabel } from "../components/styled";
|
import { Button, ButtonSuccess, InputWithLabel } from "../components/styled";
|
||||||
@ -8,20 +12,20 @@ export interface Props {
|
|||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buttonLabelByTalerType(type: TalerUriType): string {
|
function buttonLabelByTalerType(type: TalerUriType): VNode {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TalerUriType.TalerNotifyReserve:
|
case TalerUriType.TalerNotifyReserve:
|
||||||
return "Open reserve page";
|
return <Translate>Open reserve page</Translate>;
|
||||||
case TalerUriType.TalerPay:
|
case TalerUriType.TalerPay:
|
||||||
return "Open pay page";
|
return <Translate>Open pay page</Translate>;
|
||||||
case TalerUriType.TalerRefund:
|
case TalerUriType.TalerRefund:
|
||||||
return "Open refund page";
|
return <Translate>Open refund page</Translate>;
|
||||||
case TalerUriType.TalerTip:
|
case TalerUriType.TalerTip:
|
||||||
return "Open tip page";
|
return <Translate>Open tip page</Translate>;
|
||||||
case TalerUriType.TalerWithdraw:
|
case TalerUriType.TalerWithdraw:
|
||||||
return "Open withdraw page";
|
return <Translate>Open withdraw page</Translate>;
|
||||||
}
|
}
|
||||||
return "";
|
return <Fragment />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AddNewActionView({ onCancel }: Props): VNode {
|
export function AddNewActionView({ onCancel }: Props): VNode {
|
||||||
@ -47,7 +51,9 @@ export function AddNewActionView({ onCancel }: Props): VNode {
|
|||||||
</InputWithLabel>
|
</InputWithLabel>
|
||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
<Button onClick={onCancel}>Back</Button>
|
<Button onClick={onCancel}>
|
||||||
|
<Translate>Back</Translate>
|
||||||
|
</Button>
|
||||||
{uriType !== TalerUriType.Unknown && (
|
{uriType !== TalerUriType.Unknown && (
|
||||||
<ButtonSuccess
|
<ButtonSuccess
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { i18n, Timestamp } from "@gnu-taler/taler-util";
|
import { i18n, Timestamp, Translate } from "@gnu-taler/taler-util";
|
||||||
import {
|
import {
|
||||||
ProviderInfo,
|
ProviderInfo,
|
||||||
ProviderPaymentPaid,
|
ProviderPaymentPaid,
|
||||||
@ -71,7 +71,10 @@ export function BackupPage({ onAddProvider }: Props): VNode {
|
|||||||
}
|
}
|
||||||
if (status.hasError) {
|
if (status.hasError) {
|
||||||
return (
|
return (
|
||||||
<LoadingError title="Could not load backup providers" error={status} />
|
<LoadingError
|
||||||
|
title={<Translate>Could not load backup providers</Translate>}
|
||||||
|
error={status}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,9 +125,11 @@ export function BackupView({
|
|||||||
))}
|
))}
|
||||||
{!providers.length && (
|
{!providers.length && (
|
||||||
<Centered style={{ marginTop: 100 }}>
|
<Centered style={{ marginTop: 100 }}>
|
||||||
<BoldLight>No backup providers configured</BoldLight>
|
<BoldLight>
|
||||||
|
<Translate>No backup providers configured</Translate>
|
||||||
|
</BoldLight>
|
||||||
<ButtonSuccess onClick={onAddProvider}>
|
<ButtonSuccess onClick={onAddProvider}>
|
||||||
<i18n.Translate>Add provider</i18n.Translate>
|
<Translate>Add provider</Translate>
|
||||||
</ButtonSuccess>
|
</ButtonSuccess>
|
||||||
</Centered>
|
</Centered>
|
||||||
)}
|
)}
|
||||||
@ -135,12 +140,14 @@ export function BackupView({
|
|||||||
<div>
|
<div>
|
||||||
<ButtonPrimary onClick={onSyncAll}>
|
<ButtonPrimary onClick={onSyncAll}>
|
||||||
{providers.length > 1 ? (
|
{providers.length > 1 ? (
|
||||||
<i18n.Translate>Sync all backups</i18n.Translate>
|
<Translate>Sync all backups</Translate>
|
||||||
) : (
|
) : (
|
||||||
<i18n.Translate>Sync now</i18n.Translate>
|
<Translate>Sync now</Translate>
|
||||||
)}
|
)}
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
<ButtonSuccess onClick={onAddProvider}>Add provider</ButtonSuccess>
|
<ButtonSuccess onClick={onAddProvider}>
|
||||||
|
<Translate>Add provider</Translate>
|
||||||
|
</ButtonSuccess>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
)}
|
)}
|
||||||
@ -176,10 +183,14 @@ function BackupLayout(props: TransactionLayoutProps): VNode {
|
|||||||
</a>
|
</a>
|
||||||
|
|
||||||
{dateStr && (
|
{dateStr && (
|
||||||
<SmallText style={{ marginTop: 5 }}>Last synced: {dateStr}</SmallText>
|
<SmallText style={{ marginTop: 5 }}>
|
||||||
|
<Translate>Last synced</Translate>: {dateStr}
|
||||||
|
</SmallText>
|
||||||
)}
|
)}
|
||||||
{!dateStr && (
|
{!dateStr && (
|
||||||
<SmallLightText style={{ marginTop: 5 }}>Not synced</SmallLightText>
|
<SmallLightText style={{ marginTop: 5 }}>
|
||||||
|
<Translate>Not synced</Translate>
|
||||||
|
</SmallLightText>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -196,7 +207,9 @@ function BackupLayout(props: TransactionLayoutProps): VNode {
|
|||||||
function ExpirationText({ until }: { until: Timestamp }): VNode {
|
function ExpirationText({ until }: { until: Timestamp }): VNode {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<CenteredText> Expires in </CenteredText>
|
<CenteredText>
|
||||||
|
<Translate>Expires in</Translate>
|
||||||
|
</CenteredText>
|
||||||
<CenteredBoldText {...{ color: colorByTimeToExpire(until) }}>
|
<CenteredBoldText {...{ color: colorByTimeToExpire(until) }}>
|
||||||
{" "}
|
{" "}
|
||||||
{daysUntil(until)}{" "}
|
{daysUntil(until)}{" "}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { AmountJson, Amounts, i18n } from "@gnu-taler/taler-util";
|
import { AmountJson, Amounts, i18n, Translate } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import { ErrorMessage } from "../components/ErrorMessage";
|
import { ErrorMessage } from "../components/ErrorMessage";
|
||||||
@ -99,16 +99,22 @@ export function CreateManualWithdraw({
|
|||||||
if (!initialExchange) {
|
if (!initialExchange) {
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<h2>Manual Withdrawal</h2>
|
<h2>
|
||||||
|
<Translate>Manual Withdrawal</Translate>
|
||||||
|
</h2>
|
||||||
<LightText>
|
<LightText>
|
||||||
Choose a exchange from where the coins will be withdrawn. The exchange
|
<Translate>
|
||||||
will send the coins to this wallet after receiving a wire transfer
|
Choose a exchange from where the coins will be withdrawn. The
|
||||||
with the correct subject.
|
exchange will send the coins to this wallet after receiving a wire
|
||||||
|
transfer with the correct subject.
|
||||||
|
</Translate>
|
||||||
</LightText>
|
</LightText>
|
||||||
<Centered style={{ marginTop: 100 }}>
|
<Centered style={{ marginTop: 100 }}>
|
||||||
<BoldLight>No exchange configured</BoldLight>
|
<BoldLight>
|
||||||
|
<Translate>No exchange configured</Translate>
|
||||||
|
</BoldLight>
|
||||||
<ButtonSuccess onClick={onAddExchange}>
|
<ButtonSuccess onClick={onAddExchange}>
|
||||||
<i18n.Translate>Add exchange</i18n.Translate>
|
<Translate>Add exchange</Translate>
|
||||||
</ButtonSuccess>
|
</ButtonSuccess>
|
||||||
</Centered>
|
</Centered>
|
||||||
</section>
|
</section>
|
||||||
@ -118,20 +124,26 @@ export function CreateManualWithdraw({
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<section>
|
<section>
|
||||||
<ErrorMessage
|
{error && (
|
||||||
title={error && "Can't create the reserve"}
|
<ErrorMessage
|
||||||
description={error}
|
title={<Translate>Can't create the reserve</Translate>}
|
||||||
/>
|
description={error}
|
||||||
<h2>Manual Withdrawal</h2>
|
/>
|
||||||
|
)}
|
||||||
|
<h2>
|
||||||
|
<Translate>Manual Withdrawal</Translate>
|
||||||
|
</h2>
|
||||||
<LightText>
|
<LightText>
|
||||||
Choose a exchange from where the coins will be withdrawn. The exchange
|
<Translate>
|
||||||
will send the coins to this wallet after receiving a wire transfer
|
Choose a exchange from where the coins will be withdrawn. The
|
||||||
with the correct subject.
|
exchange will send the coins to this wallet after receiving a wire
|
||||||
|
transfer with the correct subject.
|
||||||
|
</Translate>
|
||||||
</LightText>
|
</LightText>
|
||||||
<p>
|
<p>
|
||||||
<Input>
|
<Input>
|
||||||
<SelectList
|
<SelectList
|
||||||
label="Currency"
|
label={<Translate>Currency</Translate>}
|
||||||
list={currencyMap}
|
list={currencyMap}
|
||||||
name="currency"
|
name="currency"
|
||||||
value={currency}
|
value={currency}
|
||||||
@ -140,7 +152,7 @@ export function CreateManualWithdraw({
|
|||||||
</Input>
|
</Input>
|
||||||
<Input>
|
<Input>
|
||||||
<SelectList
|
<SelectList
|
||||||
label="Exchange"
|
label={<Translate>Exchange</Translate>}
|
||||||
list={exchangeMap}
|
list={exchangeMap}
|
||||||
name="currency"
|
name="currency"
|
||||||
value={exchange}
|
value={exchange}
|
||||||
@ -149,12 +161,14 @@ export function CreateManualWithdraw({
|
|||||||
</Input>
|
</Input>
|
||||||
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
||||||
<LinkPrimary onClick={onAddExchange} style={{ marginLeft: "auto" }}>
|
<LinkPrimary onClick={onAddExchange} style={{ marginLeft: "auto" }}>
|
||||||
<i18n.Translate>Add exchange</i18n.Translate>
|
<Translate>Add Exchange</Translate>
|
||||||
</LinkPrimary>
|
</LinkPrimary>
|
||||||
</div>
|
</div>
|
||||||
{currency && (
|
{currency && (
|
||||||
<InputWithLabel invalid={!!amount && !parsedAmount}>
|
<InputWithLabel invalid={!!amount && !parsedAmount}>
|
||||||
<label>Amount</label>
|
<label>
|
||||||
|
<Translate>Amount</Translate>
|
||||||
|
</label>
|
||||||
<div>
|
<div>
|
||||||
<span>{currency}</span>
|
<span>{currency}</span>
|
||||||
<input
|
<input
|
||||||
@ -173,7 +187,7 @@ export function CreateManualWithdraw({
|
|||||||
disabled={!parsedAmount || !exchange}
|
disabled={!parsedAmount || !exchange}
|
||||||
onClick={() => onCreate(exchange, parsedAmount!)}
|
onClick={() => onCreate(exchange, parsedAmount!)}
|
||||||
>
|
>
|
||||||
Start withdrawal
|
<Translate>Start withdrawal</Translate>
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
</footer>
|
</footer>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -19,6 +19,7 @@ import {
|
|||||||
Amounts,
|
Amounts,
|
||||||
AmountString,
|
AmountString,
|
||||||
PaytoUri,
|
PaytoUri,
|
||||||
|
Translate,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { DepositFee } from "@gnu-taler/taler-wallet-core/src/operations/deposits";
|
import { DepositFee } from "@gnu-taler/taler-wallet-core/src/operations/deposits";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
@ -132,13 +133,21 @@ export function View({
|
|||||||
}, [amount]);
|
}, [amount]);
|
||||||
|
|
||||||
if (!balance) {
|
if (!balance) {
|
||||||
return <div>no balance</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
<Translate>no balance</Translate>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (!knownBankAccounts || !knownBankAccounts.length) {
|
if (!knownBankAccounts || !knownBankAccounts.length) {
|
||||||
return (
|
return (
|
||||||
<WarningBox>
|
<WarningBox>
|
||||||
<p>There is no known bank account to send money to</p>
|
<p>
|
||||||
<ButtonBoxWarning>Withdraw</ButtonBoxWarning>
|
<Translate>There is no known bank account to send money to</Translate>
|
||||||
|
</p>
|
||||||
|
<ButtonBoxWarning>
|
||||||
|
<Translate>Withdraw</Translate>
|
||||||
|
</ButtonBoxWarning>
|
||||||
</WarningBox>
|
</WarningBox>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -162,11 +171,13 @@ export function View({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<h2>Send {currency} to your account</h2>
|
<h2>
|
||||||
|
<Translate>Send {currency} to your account</Translate>
|
||||||
|
</h2>
|
||||||
<section>
|
<section>
|
||||||
<Input>
|
<Input>
|
||||||
<SelectList
|
<SelectList
|
||||||
label="Bank account IBAN number"
|
label={<Translate>Bank account IBAN number</Translate>}
|
||||||
list={accountMap}
|
list={accountMap}
|
||||||
name="account"
|
name="account"
|
||||||
value={String(accountIdx)}
|
value={String(accountIdx)}
|
||||||
@ -174,7 +185,9 @@ export function View({
|
|||||||
/>
|
/>
|
||||||
</Input>
|
</Input>
|
||||||
<InputWithLabel invalid={!!error}>
|
<InputWithLabel invalid={!!error}>
|
||||||
<label>Amount</label>
|
<label>
|
||||||
|
<Translate>Amount</Translate>
|
||||||
|
</label>
|
||||||
<div>
|
<div>
|
||||||
<span>{currency}</span>
|
<span>{currency}</span>
|
||||||
<input
|
<input
|
||||||
@ -196,7 +209,9 @@ export function View({
|
|||||||
{
|
{
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<InputWithLabel>
|
<InputWithLabel>
|
||||||
<label>Deposit fee</label>
|
<label>
|
||||||
|
<Translate>Deposit fee</Translate>
|
||||||
|
</label>
|
||||||
<div>
|
<div>
|
||||||
<span>{currency}</span>
|
<span>{currency}</span>
|
||||||
<input
|
<input
|
||||||
@ -208,7 +223,9 @@ export function View({
|
|||||||
</InputWithLabel>
|
</InputWithLabel>
|
||||||
|
|
||||||
<InputWithLabel>
|
<InputWithLabel>
|
||||||
<label>Total deposit</label>
|
<label>
|
||||||
|
<Translate>Total deposit</Translate>
|
||||||
|
</label>
|
||||||
<div>
|
<div>
|
||||||
<span>{currency}</span>
|
<span>{currency}</span>
|
||||||
<input
|
<input
|
||||||
@ -224,10 +241,14 @@ export function View({
|
|||||||
<footer>
|
<footer>
|
||||||
<div />
|
<div />
|
||||||
{unableToDeposit ? (
|
{unableToDeposit ? (
|
||||||
<ButtonPrimary disabled>Deposit</ButtonPrimary>
|
<ButtonPrimary disabled>
|
||||||
|
<Translate>Deposit</Translate>
|
||||||
|
</ButtonPrimary>
|
||||||
) : (
|
) : (
|
||||||
<ButtonPrimary onClick={() => onSend(accountURI, amountStr)}>
|
<ButtonPrimary onClick={() => onSend(accountURI, amountStr)}>
|
||||||
Deposit {Amounts.stringifyValue(totalToDeposit)} {currency}
|
<Translate>
|
||||||
|
Deposit {Amounts.stringifyValue(totalToDeposit)} {currency}
|
||||||
|
</Translate>
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
)}
|
)}
|
||||||
</footer>
|
</footer>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { i18n } from "@gnu-taler/taler-util";
|
import { i18n, Translate } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import { Button, ButtonSuccess, ButtonWarning } from "../components/styled";
|
import { Button, ButtonSuccess, ButtonWarning } from "../components/styled";
|
||||||
@ -84,9 +84,11 @@ export function View({
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<section>
|
<section>
|
||||||
<h1>Review terms of service</h1>
|
<h1>
|
||||||
|
<Translate>Review terms of service</Translate>
|
||||||
|
</h1>
|
||||||
<div>
|
<div>
|
||||||
Exchange URL:
|
<Translate>Exchange URL</Translate>:
|
||||||
<a href={url} target="_blank" rel="noreferrer">
|
<a href={url} target="_blank" rel="noreferrer">
|
||||||
{url}
|
{url}
|
||||||
</a>
|
</a>
|
||||||
@ -107,28 +109,28 @@ export function View({
|
|||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<Button onClick={onCancel}>
|
<Button onClick={onCancel}>
|
||||||
<i18n.Translate>Cancel</i18n.Translate>
|
<Translate>Cancel</Translate>
|
||||||
</Button>
|
</Button>
|
||||||
{!terms && (
|
{!terms && (
|
||||||
<Button disabled>
|
<Button disabled>
|
||||||
<i18n.Translate>Loading terms..</i18n.Translate>
|
<Translate>Loading terms..</Translate>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{terms && (
|
{terms && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{needsReview && !reviewed && (
|
{needsReview && !reviewed && (
|
||||||
<ButtonSuccess disabled upperCased onClick={onConfirm}>
|
<ButtonSuccess disabled upperCased onClick={onConfirm}>
|
||||||
{i18n.str`Add exchange`}
|
<Translate>Add exchange</Translate>
|
||||||
</ButtonSuccess>
|
</ButtonSuccess>
|
||||||
)}
|
)}
|
||||||
{(terms.status === "accepted" || (needsReview && reviewed)) && (
|
{(terms.status === "accepted" || (needsReview && reviewed)) && (
|
||||||
<ButtonSuccess upperCased onClick={onConfirm}>
|
<ButtonSuccess upperCased onClick={onConfirm}>
|
||||||
{i18n.str`Add exchange`}
|
<Translate>Add exchange</Translate>
|
||||||
</ButtonSuccess>
|
</ButtonSuccess>
|
||||||
)}
|
)}
|
||||||
{terms.status === "notfound" && (
|
{terms.status === "notfound" && (
|
||||||
<ButtonWarning upperCased onClick={onConfirm}>
|
<ButtonWarning upperCased onClick={onConfirm}>
|
||||||
{i18n.str`Add exchange anyway`}
|
<Translate>Add exchange anyway</Translate>
|
||||||
</ButtonWarning>
|
</ButtonWarning>
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -2,6 +2,7 @@ import {
|
|||||||
canonicalizeBaseUrl,
|
canonicalizeBaseUrl,
|
||||||
i18n,
|
i18n,
|
||||||
TalerConfigResponse,
|
TalerConfigResponse,
|
||||||
|
Translate,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h } from "preact";
|
import { Fragment, h } from "preact";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
@ -91,32 +92,46 @@ export function ExchangeSetUrlPage({
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<section>
|
<section>
|
||||||
{!expectedCurrency ? (
|
{!expectedCurrency ? (
|
||||||
<h1>Add new exchange</h1>
|
<h1>
|
||||||
|
<Translate>Add new exchange</Translate>
|
||||||
|
</h1>
|
||||||
) : (
|
) : (
|
||||||
<h2>Add exchange for {expectedCurrency}</h2>
|
<h2>
|
||||||
|
<Translate>Add exchange for {expectedCurrency}</Translate>
|
||||||
|
</h2>
|
||||||
)}
|
)}
|
||||||
{!result && (
|
{!result && (
|
||||||
<LightText>Enter the URL of an exchange you trust.</LightText>
|
<LightText>
|
||||||
|
<Translate>Enter the URL of an exchange you trust.</Translate>
|
||||||
|
</LightText>
|
||||||
)}
|
)}
|
||||||
{result && (
|
{result && (
|
||||||
<LightText>
|
<LightText>
|
||||||
An exchange has been found! Review the information and click next
|
<Translate>
|
||||||
|
An exchange has been found! Review the information and click next
|
||||||
|
</Translate>
|
||||||
</LightText>
|
</LightText>
|
||||||
)}
|
)}
|
||||||
{result && expectedCurrency && expectedCurrency !== result.currency && (
|
{result && expectedCurrency && expectedCurrency !== result.currency && (
|
||||||
<WarningBox>
|
<WarningBox>
|
||||||
This exchange doesn't match the expected currency{" "}
|
<Translate>
|
||||||
<b>{expectedCurrency}</b>
|
This exchange doesn't match the expected currency
|
||||||
|
<b>{expectedCurrency}</b>
|
||||||
|
</Translate>
|
||||||
</WarningBox>
|
</WarningBox>
|
||||||
)}
|
)}
|
||||||
<ErrorMessage
|
{error && (
|
||||||
title={error && "Unable to add this exchange"}
|
<ErrorMessage
|
||||||
description={error}
|
title={<Translate>Unable to verify this exchange</Translate>}
|
||||||
/>
|
description={error}
|
||||||
<ErrorMessage
|
/>
|
||||||
title={confirmationError && "Unable to add this exchange"}
|
)}
|
||||||
description={confirmationError}
|
{confirmationError && (
|
||||||
/>
|
<ErrorMessage
|
||||||
|
title={<Translate>Unable to add this exchange</Translate>}
|
||||||
|
description={confirmationError}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<p>
|
<p>
|
||||||
<Input invalid={!!error}>
|
<Input invalid={!!error}>
|
||||||
<label>URL</label>
|
<label>URL</label>
|
||||||
@ -127,15 +142,23 @@ export function ExchangeSetUrlPage({
|
|||||||
onInput={(e) => updateEndpoint(e.currentTarget.value)}
|
onInput={(e) => updateEndpoint(e.currentTarget.value)}
|
||||||
/>
|
/>
|
||||||
</Input>
|
</Input>
|
||||||
{loading && <div>loading... </div>}
|
{loading && (
|
||||||
|
<div>
|
||||||
|
<Translate>loading</Translate>...
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{result && !loading && (
|
{result && !loading && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Input>
|
<Input>
|
||||||
<label>Version</label>
|
<label>
|
||||||
|
<Translate>Version</Translate>
|
||||||
|
</label>
|
||||||
<input type="text" disabled value={result.version} />
|
<input type="text" disabled value={result.version} />
|
||||||
</Input>
|
</Input>
|
||||||
<Input>
|
<Input>
|
||||||
<label>Currency</label>
|
<label>
|
||||||
|
<Translate>Currency</Translate>
|
||||||
|
</label>
|
||||||
<input type="text" disabled value={result.currency} />
|
<input type="text" disabled value={result.currency} />
|
||||||
</Input>
|
</Input>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
@ -144,7 +167,7 @@ export function ExchangeSetUrlPage({
|
|||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
<Button onClick={onCancel}>
|
<Button onClick={onCancel}>
|
||||||
<i18n.Translate>Cancel</i18n.Translate>
|
<Translate>Cancel</Translate>
|
||||||
</Button>
|
</Button>
|
||||||
<ButtonPrimary
|
<ButtonPrimary
|
||||||
disabled={
|
disabled={
|
||||||
@ -160,7 +183,7 @@ export function ExchangeSetUrlPage({
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<i18n.Translate>Next</i18n.Translate>
|
<Translate>Next</Translate>
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
</footer>
|
</footer>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -19,6 +19,7 @@ import {
|
|||||||
Balance,
|
Balance,
|
||||||
NotificationType,
|
NotificationType,
|
||||||
Transaction,
|
Transaction,
|
||||||
|
Translate,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
@ -66,7 +67,7 @@ export function HistoryPage({
|
|||||||
if (transactionQuery.hasError) {
|
if (transactionQuery.hasError) {
|
||||||
return (
|
return (
|
||||||
<LoadingError
|
<LoadingError
|
||||||
title="Could not load the list of transactions"
|
title={<Translate>Could not load the list of transactions</Translate>}
|
||||||
error={transactionQuery}
|
error={transactionQuery}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -193,21 +194,23 @@ export function HistoryView({
|
|||||||
style={{ marginLeft: 0, marginTop: 8 }}
|
style={{ marginLeft: 0, marginTop: 8 }}
|
||||||
onClick={() => goToWalletManualWithdraw(selectedCurrency)}
|
onClick={() => goToWalletManualWithdraw(selectedCurrency)}
|
||||||
>
|
>
|
||||||
Withdraw
|
<Translate>Withdraw</Translate>
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
{currencyAmount && Amounts.isNonZero(currencyAmount) && (
|
{currencyAmount && Amounts.isNonZero(currencyAmount) && (
|
||||||
<ButtonBoxPrimary
|
<ButtonBoxPrimary
|
||||||
style={{ marginLeft: 0, marginTop: 8 }}
|
style={{ marginLeft: 0, marginTop: 8 }}
|
||||||
onClick={() => goToWalletDeposit(selectedCurrency)}
|
onClick={() => goToWalletDeposit(selectedCurrency)}
|
||||||
>
|
>
|
||||||
Deposit
|
<Translate>Deposit</Translate>
|
||||||
</ButtonBoxPrimary>
|
</ButtonBoxPrimary>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{datesWithTransaction.length === 0 ? (
|
{datesWithTransaction.length === 0 ? (
|
||||||
<section>There is no history for this currency</section>
|
<section>
|
||||||
|
<Translate>There is no history for this currency</Translate>
|
||||||
|
</section>
|
||||||
) : (
|
) : (
|
||||||
<section>
|
<section>
|
||||||
{datesWithTransaction.map((d, i) => {
|
{datesWithTransaction.map((d, i) => {
|
||||||
|
@ -19,6 +19,7 @@ import {
|
|||||||
AmountJson,
|
AmountJson,
|
||||||
Amounts,
|
Amounts,
|
||||||
NotificationType,
|
NotificationType,
|
||||||
|
Translate,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
@ -95,7 +96,9 @@ export function ManualWithdrawPage({ currency, onCancel }: Props): VNode {
|
|||||||
if (state.hasError) {
|
if (state.hasError) {
|
||||||
return (
|
return (
|
||||||
<LoadingError
|
<LoadingError
|
||||||
title="Could not load the list of known exchanges"
|
title={
|
||||||
|
<Translate>Could not load the list of known exchanges</Translate>
|
||||||
|
}
|
||||||
error={state}
|
error={state}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -19,6 +19,7 @@ import {
|
|||||||
BackupBackupProviderTerms,
|
BackupBackupProviderTerms,
|
||||||
canonicalizeBaseUrl,
|
canonicalizeBaseUrl,
|
||||||
i18n,
|
i18n,
|
||||||
|
Translate,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
@ -113,15 +114,23 @@ export function SetUrlView({
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<section>
|
<section>
|
||||||
<h1> Add backup provider</h1>
|
<h1>
|
||||||
<ErrorMessage
|
<Translate>Add backup provider</Translate>
|
||||||
title={error && "Could not get provider information"}
|
</h1>
|
||||||
description={error}
|
{error && (
|
||||||
/>
|
<ErrorMessage
|
||||||
<LightText> Backup providers may charge for their service</LightText>
|
title={<Translate>Could not get provider information</Translate>}
|
||||||
|
description={error}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<LightText>
|
||||||
|
<Translate>Backup providers may charge for their service</Translate>
|
||||||
|
</LightText>
|
||||||
<p>
|
<p>
|
||||||
<Input invalid={urlError}>
|
<Input invalid={urlError}>
|
||||||
<label>URL</label>
|
<label>
|
||||||
|
<Translate>URL</Translate>
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="https://"
|
placeholder="https://"
|
||||||
@ -130,7 +139,9 @@ export function SetUrlView({
|
|||||||
/>
|
/>
|
||||||
</Input>
|
</Input>
|
||||||
<Input>
|
<Input>
|
||||||
<label>Name</label>
|
<label>
|
||||||
|
<Translate>Name</Translate>
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
disabled={name === undefined}
|
disabled={name === undefined}
|
||||||
@ -142,7 +153,7 @@ export function SetUrlView({
|
|||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
<Button onClick={onCancel}>
|
<Button onClick={onCancel}>
|
||||||
<i18n.Translate> < Back</i18n.Translate>
|
< <Translate>Back</Translate>
|
||||||
</Button>
|
</Button>
|
||||||
<ButtonPrimary
|
<ButtonPrimary
|
||||||
disabled={!value && !urlError}
|
disabled={!value && !urlError}
|
||||||
@ -153,7 +164,7 @@ export function SetUrlView({
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<i18n.Translate>Next</i18n.Translate>
|
<Translate>Next</Translate>
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
</footer>
|
</footer>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
@ -177,29 +188,41 @@ export function ConfirmProviderView({
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<section>
|
<section>
|
||||||
<h1>Review terms of service</h1>
|
<h1>
|
||||||
|
<Translate>Review terms of service</Translate>
|
||||||
|
</h1>
|
||||||
<div>
|
<div>
|
||||||
Provider URL:{" "}
|
<Translate>Provider URL</Translate>:{" "}
|
||||||
<a href={url} target="_blank">
|
<a href={url} target="_blank">
|
||||||
{url}
|
{url}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<SmallLightText>
|
<SmallLightText>
|
||||||
Please review and accept this provider's terms of service
|
<Translate>
|
||||||
|
Please review and accept this provider's terms of service
|
||||||
|
</Translate>
|
||||||
</SmallLightText>
|
</SmallLightText>
|
||||||
<h2>1. Pricing</h2>
|
<h2>
|
||||||
|
1. <Translate>Pricing</Translate>
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
{Amounts.isZero(provider.annual_fee)
|
{Amounts.isZero(provider.annual_fee) ? (
|
||||||
? "free of charge"
|
<Translate>free of charge</Translate>
|
||||||
: `${provider.annual_fee} per year of service`}
|
) : (
|
||||||
|
<Translate>{provider.annual_fee} per year of service</Translate>
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
<h2>2. Storage</h2>
|
<h2>
|
||||||
|
2. <Translate>Storage</Translate>
|
||||||
|
</h2>
|
||||||
<p>
|
<p>
|
||||||
{provider.storage_limit_in_megabytes} megabytes of storage per year of
|
<Translate>
|
||||||
service
|
{provider.storage_limit_in_megabytes} megabytes of storage per year
|
||||||
|
of service
|
||||||
|
</Translate>
|
||||||
</p>
|
</p>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Accept terms of service"
|
label={<Translate>Accept terms of service</Translate>}
|
||||||
name="terms"
|
name="terms"
|
||||||
onToggle={() => setAccepted((old) => !old)}
|
onToggle={() => setAccepted((old) => !old)}
|
||||||
enabled={accepted}
|
enabled={accepted}
|
||||||
@ -207,10 +230,10 @@ export function ConfirmProviderView({
|
|||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
<Button onClick={onCancel}>
|
<Button onClick={onCancel}>
|
||||||
<i18n.Translate> < Back</i18n.Translate>
|
< <Translate>Back</Translate>
|
||||||
</Button>
|
</Button>
|
||||||
<ButtonPrimary disabled={!accepted} onClick={onConfirm}>
|
<ButtonPrimary disabled={!accepted} onClick={onConfirm}>
|
||||||
<i18n.Translate>Add provider</i18n.Translate>
|
<Translate>Add provider</Translate>
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
</footer>
|
</footer>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { i18n } from "@gnu-taler/taler-util";
|
import { Translate } from "@gnu-taler/taler-util";
|
||||||
import {
|
import {
|
||||||
ProviderInfo,
|
ProviderInfo,
|
||||||
ProviderPaymentStatus,
|
ProviderPaymentStatus,
|
||||||
@ -22,6 +22,8 @@ import {
|
|||||||
} from "@gnu-taler/taler-wallet-core";
|
} from "@gnu-taler/taler-wallet-core";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { ErrorMessage } from "../components/ErrorMessage";
|
import { ErrorMessage } from "../components/ErrorMessage";
|
||||||
|
import { Loading } from "../components/Loading";
|
||||||
|
import { LoadingError } from "../components/LoadingError";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
ButtonDestructive,
|
ButtonDestructive,
|
||||||
@ -52,35 +54,24 @@ export function ProviderDetailPage({ pid: providerURL, onBack }: Props): VNode {
|
|||||||
const state = useAsyncAsHook(getProviderInfo);
|
const state = useAsyncAsHook(getProviderInfo);
|
||||||
|
|
||||||
if (!state) {
|
if (!state) {
|
||||||
return (
|
return <Loading />;
|
||||||
<div>
|
|
||||||
<i18n.Translate>Loading...</i18n.Translate>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (state.hasError) {
|
if (state.hasError) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<LoadingError
|
||||||
<i18n.Translate>
|
title={
|
||||||
There was an error loading the provider detail for "{providerURL}"
|
<Translate>
|
||||||
</i18n.Translate>
|
There was an error loading the provider detail for "{providerURL}"
|
||||||
</div>
|
</Translate>
|
||||||
|
}
|
||||||
|
error={state}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.response === null) {
|
|
||||||
onBack();
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<i18n.Translate>
|
|
||||||
There is not known provider with url "{providerURL}". Redirecting
|
|
||||||
back...
|
|
||||||
</i18n.Translate>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<ProviderView
|
<ProviderView
|
||||||
|
url={providerURL}
|
||||||
info={state.response}
|
info={state.response}
|
||||||
onSync={async () => wxApi.syncOneProvider(providerURL)}
|
onSync={async () => wxApi.syncOneProvider(providerURL)}
|
||||||
onDelete={async () => wxApi.removeProvider(providerURL).then(onBack)}
|
onDelete={async () => wxApi.removeProvider(providerURL).then(onBack)}
|
||||||
@ -93,7 +84,8 @@ export function ProviderDetailPage({ pid: providerURL, onBack }: Props): VNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ViewProps {
|
export interface ViewProps {
|
||||||
info: ProviderInfo;
|
url: string;
|
||||||
|
info: ProviderInfo | null;
|
||||||
onDelete: () => void;
|
onDelete: () => void;
|
||||||
onSync: () => void;
|
onSync: () => void;
|
||||||
onBack: () => void;
|
onBack: () => void;
|
||||||
@ -102,12 +94,30 @@ export interface ViewProps {
|
|||||||
|
|
||||||
export function ProviderView({
|
export function ProviderView({
|
||||||
info,
|
info,
|
||||||
|
url,
|
||||||
onDelete,
|
onDelete,
|
||||||
onSync,
|
onSync,
|
||||||
onBack,
|
onBack,
|
||||||
onExtend,
|
onExtend,
|
||||||
}: ViewProps): VNode {
|
}: ViewProps): VNode {
|
||||||
const lb = info?.lastSuccessfulBackupTimestamp;
|
if (info === null) {
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<section>
|
||||||
|
<p>
|
||||||
|
<Translate>There is not known provider with url "{url}".</Translate>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<footer>
|
||||||
|
<Button onClick={onBack}>
|
||||||
|
< <Translate>Back</Translate>
|
||||||
|
</Button>
|
||||||
|
<div />
|
||||||
|
</footer>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const lb = info.lastSuccessfulBackupTimestamp;
|
||||||
const isPaid =
|
const isPaid =
|
||||||
info.paymentStatus.type === ProviderPaymentType.Paid ||
|
info.paymentStatus.type === ProviderPaymentType.Paid ||
|
||||||
info.paymentStatus.type === ProviderPaymentType.TermsChanged;
|
info.paymentStatus.type === ProviderPaymentType.TermsChanged;
|
||||||
@ -125,48 +135,55 @@ export function ProviderView({
|
|||||||
</header>
|
</header>
|
||||||
<section>
|
<section>
|
||||||
<p>
|
<p>
|
||||||
<b>Last backup:</b> <Time timestamp={lb} format="dd MMMM yyyy" />
|
<b>
|
||||||
|
<Translate>Last backup</Translate>:
|
||||||
|
</b>{" "}
|
||||||
|
<Time timestamp={lb} format="dd MMMM yyyy" />
|
||||||
</p>
|
</p>
|
||||||
<ButtonPrimary onClick={onSync}>
|
<ButtonPrimary onClick={onSync}>
|
||||||
<i18n.Translate>Back up</i18n.Translate>
|
<Translate>Back up</Translate>
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
{info.terms && (
|
{info.terms && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<p>
|
<p>
|
||||||
<b>Provider fee:</b> {info.terms && info.terms.annualFee} per year
|
<b>
|
||||||
|
<Translate>Provider fee</Translate>:
|
||||||
|
</b>{" "}
|
||||||
|
{info.terms && info.terms.annualFee}{" "}
|
||||||
|
<Translate>per year</Translate>
|
||||||
</p>
|
</p>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
<p>{descriptionByStatus(info.paymentStatus)}</p>
|
<p>{descriptionByStatus(info.paymentStatus)}</p>
|
||||||
<ButtonPrimary disabled onClick={onExtend}>
|
<ButtonPrimary disabled onClick={onExtend}>
|
||||||
<i18n.Translate>Extend</i18n.Translate>
|
<Translate>Extend</Translate>
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
|
|
||||||
{info.paymentStatus.type === ProviderPaymentType.TermsChanged && (
|
{info.paymentStatus.type === ProviderPaymentType.TermsChanged && (
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<i18n.Translate>
|
<Translate>
|
||||||
terms has changed, extending the service will imply accepting
|
terms has changed, extending the service will imply accepting
|
||||||
the new terms of service
|
the new terms of service
|
||||||
</i18n.Translate>
|
</Translate>
|
||||||
</p>
|
</p>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td> </td>
|
<td> </td>
|
||||||
<td>
|
<td>
|
||||||
<i18n.Translate>old</i18n.Translate>
|
<Translate>old</Translate>
|
||||||
</td>
|
</td>
|
||||||
<td> -></td>
|
<td> -></td>
|
||||||
<td>
|
<td>
|
||||||
<i18n.Translate>new</i18n.Translate>
|
<Translate>new</Translate>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<i18n.Translate>fee</i18n.Translate>
|
<Translate>fee</Translate>
|
||||||
</td>
|
</td>
|
||||||
<td>{info.paymentStatus.oldTerms.annualFee}</td>
|
<td>{info.paymentStatus.oldTerms.annualFee}</td>
|
||||||
<td>-></td>
|
<td>-></td>
|
||||||
@ -174,7 +191,7 @@ export function ProviderView({
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<i18n.Translate>storage</i18n.Translate>
|
<Translate>storage</Translate>
|
||||||
</td>
|
</td>
|
||||||
<td>{info.paymentStatus.oldTerms.storageLimitInMegabytes}</td>
|
<td>{info.paymentStatus.oldTerms.storageLimitInMegabytes}</td>
|
||||||
<td>-></td>
|
<td>-></td>
|
||||||
@ -187,11 +204,11 @@ export function ProviderView({
|
|||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
<Button onClick={onBack}>
|
<Button onClick={onBack}>
|
||||||
<i18n.Translate> < back</i18n.Translate>
|
< <Translate>back</Translate>
|
||||||
</Button>
|
</Button>
|
||||||
<div>
|
<div>
|
||||||
<ButtonDestructive onClick={onDelete}>
|
<ButtonDestructive onClick={onDelete}>
|
||||||
<i18n.Translate>remove provider</i18n.Translate>
|
<Translate>Remove provider</Translate>
|
||||||
</ButtonDestructive>
|
</ButtonDestructive>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
@ -201,7 +218,12 @@ export function ProviderView({
|
|||||||
|
|
||||||
function Error({ info }: { info: ProviderInfo }): VNode {
|
function Error({ info }: { info: ProviderInfo }): VNode {
|
||||||
if (info.lastError) {
|
if (info.lastError) {
|
||||||
return <ErrorMessage title={info.lastError.hint} />;
|
return (
|
||||||
|
<ErrorMessage
|
||||||
|
title={<Translate>This provider has reported an error</Translate>}
|
||||||
|
description={info.lastError.hint}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (info.backupProblem) {
|
if (info.backupProblem) {
|
||||||
switch (info.backupProblem.type) {
|
switch (info.backupProblem.type) {
|
||||||
@ -210,24 +232,26 @@ function Error({ info }: { info: ProviderInfo }): VNode {
|
|||||||
<ErrorMessage
|
<ErrorMessage
|
||||||
title={
|
title={
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<i18n.Translate>
|
<Translate>
|
||||||
There is conflict with another backup from{" "}
|
There is conflict with another backup from{" "}
|
||||||
<b>{info.backupProblem.otherDeviceId}</b>
|
<b>{info.backupProblem.otherDeviceId}</b>
|
||||||
</i18n.Translate>
|
</Translate>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case "backup-unreadable":
|
case "backup-unreadable":
|
||||||
return <ErrorMessage title="Backup is not readable" />;
|
return (
|
||||||
|
<ErrorMessage title={<Translate>Backup is not readable</Translate>} />
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<ErrorMessage
|
<ErrorMessage
|
||||||
title={
|
title={
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<i18n.Translate>
|
<Translate>
|
||||||
Unknown backup problem: {JSON.stringify(info.backupProblem)}
|
Unknown backup problem: {JSON.stringify(info.backupProblem)}
|
||||||
</i18n.Translate>
|
</Translate>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@ -239,16 +263,20 @@ function Error({ info }: { info: ProviderInfo }): VNode {
|
|||||||
|
|
||||||
function descriptionByStatus(status: ProviderPaymentStatus): VNode {
|
function descriptionByStatus(status: ProviderPaymentStatus): VNode {
|
||||||
switch (status.type) {
|
switch (status.type) {
|
||||||
// return i18n.str`no enough balance to make the payment`
|
|
||||||
// return i18n.str`not paid yet`
|
|
||||||
case ProviderPaymentType.Paid:
|
case ProviderPaymentType.Paid:
|
||||||
case ProviderPaymentType.TermsChanged:
|
case ProviderPaymentType.TermsChanged:
|
||||||
if (status.paidUntil.t_ms === "never") {
|
if (status.paidUntil.t_ms === "never") {
|
||||||
return <span>{i18n.str`service paid`}</span>;
|
return (
|
||||||
|
<span>
|
||||||
|
<Translate>service paid</Translate>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<b>Backup valid until:</b>{" "}
|
<b>
|
||||||
|
<Translate>Backup valid until</Translate>:
|
||||||
|
</b>{" "}
|
||||||
<Time timestamp={status.paidUntil} format="dd MMM yyyy" />
|
<Time timestamp={status.paidUntil} format="dd MMM yyyy" />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import { AmountJson, Amounts, parsePaytoUri } from "@gnu-taler/taler-util";
|
import {
|
||||||
|
AmountJson,
|
||||||
|
Amounts,
|
||||||
|
parsePaytoUri,
|
||||||
|
Translate,
|
||||||
|
} from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { BankDetailsByPaytoType } from "../components/BankDetailsByPaytoType";
|
import { BankDetailsByPaytoType } from "../components/BankDetailsByPaytoType";
|
||||||
import { QR } from "../components/QR";
|
import { QR } from "../components/QR";
|
||||||
@ -22,15 +27,23 @@ export function ReserveCreated({
|
|||||||
const paytoURI = parsePaytoUri(payto);
|
const paytoURI = parsePaytoUri(payto);
|
||||||
// const url = new URL(paytoURI?.targetPath);
|
// const url = new URL(paytoURI?.targetPath);
|
||||||
if (!paytoURI) {
|
if (!paytoURI) {
|
||||||
return <div>could not parse payto uri from exchange {payto}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
<Translate>could not parse payto uri from exchange {payto}</Translate>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<section>
|
<section>
|
||||||
<h1>Exchange is ready for withdrawal!</h1>
|
<h1>
|
||||||
|
<Translate>Exchange is ready for withdrawal</Translate>
|
||||||
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
To complete the process you need to wire{" "}
|
<Translate>
|
||||||
<b>{amountToString(amount)}</b> to the exchange bank account
|
To complete the process you need to wire
|
||||||
|
<b>{amountToString(amount)}</b> to the exchange bank account
|
||||||
|
</Translate>
|
||||||
</p>
|
</p>
|
||||||
<BankDetailsByPaytoType
|
<BankDetailsByPaytoType
|
||||||
amount={amountToString(amount)}
|
amount={amountToString(amount)}
|
||||||
@ -40,23 +53,27 @@ export function ReserveCreated({
|
|||||||
/>
|
/>
|
||||||
<p>
|
<p>
|
||||||
<WarningBox>
|
<WarningBox>
|
||||||
Make sure to use the correct subject, otherwise the money will not
|
<Translate>
|
||||||
arrive in this wallet.
|
Make sure to use the correct subject, otherwise the money will not
|
||||||
|
arrive in this wallet.
|
||||||
|
</Translate>
|
||||||
</WarningBox>
|
</WarningBox>
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<p>
|
<p>
|
||||||
Alternative, you can also scan this QR code or open{" "}
|
<Translate>
|
||||||
<a href={payto}>this link</a> if you have a banking app installed that
|
Alternative, you can also scan this QR code or open
|
||||||
supports RFC 8905
|
<a href={payto}>this link</a> if you have a banking app installed
|
||||||
|
that supports RFC 8905
|
||||||
|
</Translate>
|
||||||
</p>
|
</p>
|
||||||
<QR text={payto} />
|
<QR text={payto} />
|
||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
<div />
|
<div />
|
||||||
<ButtonDestructive onClick={onCancel}>
|
<ButtonDestructive onClick={onCancel}>
|
||||||
Cancel withdrawal
|
<Translate>Cancel withdrawal</Translate>
|
||||||
</ButtonDestructive>
|
</ButtonDestructive>
|
||||||
</footer>
|
</footer>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ExchangeListItem, i18n } from "@gnu-taler/taler-util";
|
import { ExchangeListItem, i18n, Translate } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { Checkbox } from "../components/Checkbox";
|
import { Checkbox } from "../components/Checkbox";
|
||||||
import {
|
import {
|
||||||
@ -81,29 +81,46 @@ export function SettingsView({
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<section>
|
<section>
|
||||||
<h2>
|
<h2>
|
||||||
<i18n.Translate>Permissions</i18n.Translate>
|
<Translate>Permissions</Translate>
|
||||||
</h2>
|
</h2>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Automatically open wallet based on page content"
|
label={
|
||||||
|
<Translate>
|
||||||
|
Automatically open wallet based on page content
|
||||||
|
</Translate>
|
||||||
|
}
|
||||||
name="perm"
|
name="perm"
|
||||||
description="(Enabling this option below will make using the wallet faster, but requires more permissions from your browser.)"
|
description={
|
||||||
|
<Translate>
|
||||||
|
Enabling this option below will make using the wallet faster, but
|
||||||
|
requires more permissions from your browser.
|
||||||
|
</Translate>
|
||||||
|
}
|
||||||
enabled={permissionsEnabled}
|
enabled={permissionsEnabled}
|
||||||
onToggle={togglePermissions}
|
onToggle={togglePermissions}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<h2>
|
<h2>
|
||||||
<i18n.Translate>Known exchanges</i18n.Translate>
|
<Translate>Known exchanges</Translate>
|
||||||
</h2>
|
</h2>
|
||||||
{!knownExchanges || !knownExchanges.length ? (
|
{!knownExchanges || !knownExchanges.length ? (
|
||||||
<div>No exchange yet!</div>
|
<div>
|
||||||
|
<Translate>No exchange yet</Translate>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>currency</th>
|
<th>
|
||||||
<th>url</th>
|
<Translate>Currency</Translate>
|
||||||
<th>term of service</th>
|
</th>
|
||||||
|
<th>
|
||||||
|
<Translate>URL</Translate>
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
<Translate>Term of Service</Translate>
|
||||||
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -116,12 +133,24 @@ export function SettingsView({
|
|||||||
);
|
);
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "accepted":
|
case "accepted":
|
||||||
return <SuccessText>ok</SuccessText>;
|
return (
|
||||||
|
<SuccessText>
|
||||||
|
<Translate>ok</Translate>
|
||||||
|
</SuccessText>
|
||||||
|
);
|
||||||
case "changed":
|
case "changed":
|
||||||
return <WarningText>changed!</WarningText>;
|
return (
|
||||||
|
<WarningText>
|
||||||
|
<Translate>changed</Translate>
|
||||||
|
</WarningText>
|
||||||
|
);
|
||||||
case "new":
|
case "new":
|
||||||
case "notfound":
|
case "notfound":
|
||||||
return <DestructiveText>not accepted</DestructiveText>;
|
return (
|
||||||
|
<DestructiveText>
|
||||||
|
<Translate>not accepted</Translate>
|
||||||
|
</DestructiveText>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
@ -143,15 +172,19 @@ export function SettingsView({
|
|||||||
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
||||||
<div />
|
<div />
|
||||||
<LinkPrimary href={Pages.settings_exchange_add}>
|
<LinkPrimary href={Pages.settings_exchange_add}>
|
||||||
Add an exchange
|
<Translate>Add an exchange</Translate>
|
||||||
</LinkPrimary>
|
</LinkPrimary>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2>Config</h2>
|
<h2>Config</h2>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Developer mode"
|
label={<Translate>Developer mode</Translate>}
|
||||||
name="devMode"
|
name="devMode"
|
||||||
description="(More options and information useful for debugging)"
|
description={
|
||||||
|
<Translate>
|
||||||
|
(More options and information useful for debugging)
|
||||||
|
</Translate>
|
||||||
|
}
|
||||||
enabled={developerMode}
|
enabled={developerMode}
|
||||||
onToggle={toggleDeveloperMode}
|
onToggle={toggleDeveloperMode}
|
||||||
/>
|
/>
|
||||||
|
@ -22,6 +22,7 @@ import {
|
|||||||
parsePaytoUri,
|
parsePaytoUri,
|
||||||
Transaction,
|
Transaction,
|
||||||
TransactionType,
|
TransactionType,
|
||||||
|
Translate,
|
||||||
WithdrawalType,
|
WithdrawalType,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { differenceInSeconds } from "date-fns";
|
import { differenceInSeconds } from "date-fns";
|
||||||
@ -47,7 +48,6 @@ import {
|
|||||||
} from "../components/styled";
|
} from "../components/styled";
|
||||||
import { Time } from "../components/Time";
|
import { Time } from "../components/Time";
|
||||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
||||||
import { Pages } from "../NavigationBar";
|
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -76,7 +76,9 @@ export function TransactionPage({ tid, goToWalletHistory }: Props): VNode {
|
|||||||
if (state.hasError) {
|
if (state.hasError) {
|
||||||
return (
|
return (
|
||||||
<LoadingError
|
<LoadingError
|
||||||
title="Could not load the transaction information"
|
title={
|
||||||
|
<Translate>Could not load the transaction information</Translate>
|
||||||
|
}
|
||||||
error={state}
|
error={state}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -139,11 +141,17 @@ export function TransactionView({
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<section style={{ padding: 8, textAlign: "center" }}>
|
<section style={{ padding: 8, textAlign: "center" }}>
|
||||||
<ErrorTalerOperation
|
<ErrorTalerOperation
|
||||||
title="There was an error trying to complete the transaction"
|
title={
|
||||||
|
<Translate>
|
||||||
|
There was an error trying to complete the transaction
|
||||||
|
</Translate>
|
||||||
|
}
|
||||||
error={transaction?.error}
|
error={transaction?.error}
|
||||||
/>
|
/>
|
||||||
{transaction.pending && (
|
{transaction.pending && (
|
||||||
<WarningBox>This transaction is not completed</WarningBox>
|
<WarningBox>
|
||||||
|
<Translate>This transaction is not completed</Translate>
|
||||||
|
</WarningBox>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
@ -151,16 +159,16 @@ export function TransactionView({
|
|||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
<Button onClick={onBack}>
|
<Button onClick={onBack}>
|
||||||
<i18n.Translate> < Back </i18n.Translate>
|
< <Translate> Back </Translate>
|
||||||
</Button>
|
</Button>
|
||||||
<div>
|
<div>
|
||||||
{showRetry ? (
|
{showRetry ? (
|
||||||
<ButtonPrimary onClick={onRetry}>
|
<ButtonPrimary onClick={onRetry}>
|
||||||
<i18n.Translate>retry</i18n.Translate>
|
<Translate>Retry</Translate>
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
) : null}
|
) : null}
|
||||||
<ButtonDestructive onClick={doCheckBeforeForget}>
|
<ButtonDestructive onClick={doCheckBeforeForget}>
|
||||||
<i18n.Translate> Forget </i18n.Translate>
|
<Translate>Forget</Translate>
|
||||||
</ButtonDestructive>
|
</ButtonDestructive>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
@ -184,24 +192,30 @@ export function TransactionView({
|
|||||||
{confirmBeforeForget ? (
|
{confirmBeforeForget ? (
|
||||||
<Overlay>
|
<Overlay>
|
||||||
<CenteredDialog>
|
<CenteredDialog>
|
||||||
<header>Caution!</header>
|
<header>
|
||||||
|
<Translate>Caution!</Translate>
|
||||||
|
</header>
|
||||||
<section>
|
<section>
|
||||||
If you have already wired money to the exchange you will loose
|
<Translate>
|
||||||
the chance to get the coins form it.
|
If you have already wired money to the exchange you will loose
|
||||||
|
the chance to get the coins form it.
|
||||||
|
</Translate>
|
||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
<Button onClick={() => setConfirmBeforeForget(false)}>
|
<Button onClick={() => setConfirmBeforeForget(false)}>
|
||||||
<i18n.Translate> Cancel </i18n.Translate>
|
<Translate>Cancel</Translate>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<ButtonDestructive onClick={onDelete}>
|
<ButtonDestructive onClick={onDelete}>
|
||||||
<i18n.Translate> Confirm </i18n.Translate>
|
<Translate>Confirm</Translate>
|
||||||
</ButtonDestructive>
|
</ButtonDestructive>
|
||||||
</footer>
|
</footer>
|
||||||
</CenteredDialog>
|
</CenteredDialog>
|
||||||
</Overlay>
|
</Overlay>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
<h2>Withdrawal</h2>
|
<h2>
|
||||||
|
<Translate>Withdrawal</Translate>
|
||||||
|
</h2>
|
||||||
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
|
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
|
||||||
{transaction.pending ? (
|
{transaction.pending ? (
|
||||||
transaction.withdrawalDetails.type ===
|
transaction.withdrawalDetails.type ===
|
||||||
@ -217,19 +231,21 @@ export function TransactionView({
|
|||||||
/>
|
/>
|
||||||
<p>
|
<p>
|
||||||
<WarningBox>
|
<WarningBox>
|
||||||
Make sure to use the correct subject, otherwise the money will
|
<Translate>
|
||||||
not arrive in this wallet.
|
Make sure to use the correct subject, otherwise the money
|
||||||
|
will not arrive in this wallet.
|
||||||
|
</Translate>
|
||||||
</WarningBox>
|
</WarningBox>
|
||||||
</p>
|
</p>
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Total withdrawn"
|
title={<Translate>Total withdrawn</Translate>}
|
||||||
text={amountToString(transaction.amountEffective)}
|
text={amountToString(transaction.amountEffective)}
|
||||||
kind="positive"
|
kind="positive"
|
||||||
/>
|
/>
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Exchange fee"
|
title={<Translate>Exchange fee</Translate>}
|
||||||
text={amountToString(fee)}
|
text={amountToString(fee)}
|
||||||
kind="negative"
|
kind="negative"
|
||||||
/>
|
/>
|
||||||
@ -239,34 +255,38 @@ export function TransactionView({
|
|||||||
{!transaction.withdrawalDetails.confirmed &&
|
{!transaction.withdrawalDetails.confirmed &&
|
||||||
transaction.withdrawalDetails.bankConfirmationUrl ? (
|
transaction.withdrawalDetails.bankConfirmationUrl ? (
|
||||||
<InfoBox>
|
<InfoBox>
|
||||||
The bank is waiting for confirmation. Go to the
|
<Translate>
|
||||||
<a
|
The bank is waiting for confirmation. Go to the
|
||||||
href={transaction.withdrawalDetails.bankConfirmationUrl}
|
<a
|
||||||
target="_blank"
|
href={transaction.withdrawalDetails.bankConfirmationUrl}
|
||||||
rel="noreferrer"
|
target="_blank"
|
||||||
>
|
rel="noreferrer"
|
||||||
bank site
|
>
|
||||||
</a>
|
<Translate>bank site</Translate>
|
||||||
|
</a>
|
||||||
|
</Translate>
|
||||||
</InfoBox>
|
</InfoBox>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{transaction.withdrawalDetails.confirmed && (
|
{transaction.withdrawalDetails.confirmed && (
|
||||||
<InfoBox>Waiting for the coins to arrive</InfoBox>
|
<InfoBox>
|
||||||
|
<Translate>Waiting for the coins to arrive</Translate>
|
||||||
|
</InfoBox>
|
||||||
)}
|
)}
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Total withdrawn"
|
title={<Translate>Total withdrawn</Translate>}
|
||||||
text={amountToString(transaction.amountEffective)}
|
text={amountToString(transaction.amountEffective)}
|
||||||
kind="positive"
|
kind="positive"
|
||||||
/>
|
/>
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Chosen amount"
|
title={<Translate>Chosen amount</Translate>}
|
||||||
text={amountToString(transaction.amountRaw)}
|
text={amountToString(transaction.amountRaw)}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Exchange fee"
|
title={<Translate>Exchange fee</Translate>}
|
||||||
text={amountToString(fee)}
|
text={amountToString(fee)}
|
||||||
kind="negative"
|
kind="negative"
|
||||||
/>
|
/>
|
||||||
@ -276,26 +296,26 @@ export function TransactionView({
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Total withdrawn"
|
title={<Translate>Total withdrawn</Translate>}
|
||||||
text={amountToString(transaction.amountEffective)}
|
text={amountToString(transaction.amountEffective)}
|
||||||
kind="positive"
|
kind="positive"
|
||||||
/>
|
/>
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Chosen amount"
|
title={<Translate>Chosen amount</Translate>}
|
||||||
text={amountToString(transaction.amountRaw)}
|
text={amountToString(transaction.amountRaw)}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Exchange fee"
|
title={<Translate>Exchange fee</Translate>}
|
||||||
text={amountToString(fee)}
|
text={amountToString(fee)}
|
||||||
kind="negative"
|
kind="negative"
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
<Part
|
<Part
|
||||||
title="Exchange"
|
title={<Translate>Exchange</Translate>}
|
||||||
text={new URL(transaction.exchangeBaseUrl).hostname}
|
text={new URL(transaction.exchangeBaseUrl).hostname}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
@ -315,30 +335,41 @@ export function TransactionView({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<TransactionTemplate>
|
<TransactionTemplate>
|
||||||
<h2>Payment </h2>
|
<h2>
|
||||||
|
<Translate>Payment</Translate>
|
||||||
|
</h2>
|
||||||
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
|
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
|
||||||
<br />
|
<br />
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Total paid"
|
title={<Translate>Total paid</Translate>}
|
||||||
text={amountToString(transaction.amountEffective)}
|
text={amountToString(transaction.amountEffective)}
|
||||||
kind="negative"
|
kind="negative"
|
||||||
/>
|
/>
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Purchase amount"
|
title={<Translate>Purchase amount</Translate>}
|
||||||
text={amountToString(transaction.amountRaw)}
|
text={amountToString(transaction.amountRaw)}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
<Part big title="Fee" text={amountToString(fee)} kind="negative" />
|
|
||||||
<Part
|
<Part
|
||||||
title="Merchant"
|
big
|
||||||
|
title={<Translate>Fee</Translate>}
|
||||||
|
text={amountToString(fee)}
|
||||||
|
kind="negative"
|
||||||
|
/>
|
||||||
|
<Part
|
||||||
|
title={<Translate>Merchant</Translate>}
|
||||||
text={transaction.info.merchant.name}
|
text={transaction.info.merchant.name}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
<Part title="Purchase" text={transaction.info.summary} kind="neutral" />
|
|
||||||
<Part
|
<Part
|
||||||
title="Receipt"
|
title={<Translate>Purchase</Translate>}
|
||||||
|
text={transaction.info.summary}
|
||||||
|
kind="neutral"
|
||||||
|
/>
|
||||||
|
<Part
|
||||||
|
title={<Translate>Receipt</Translate>}
|
||||||
text={`#${transaction.info.orderId}`}
|
text={`#${transaction.info.orderId}`}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
@ -375,22 +406,29 @@ export function TransactionView({
|
|||||||
).amount;
|
).amount;
|
||||||
return (
|
return (
|
||||||
<TransactionTemplate>
|
<TransactionTemplate>
|
||||||
<h2>Deposit </h2>
|
<h2>
|
||||||
|
<Translate>Deposit</Translate>
|
||||||
|
</h2>
|
||||||
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
|
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
|
||||||
<br />
|
<br />
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Total send"
|
title={<Translate>Total send</Translate>}
|
||||||
text={amountToString(transaction.amountEffective)}
|
text={amountToString(transaction.amountEffective)}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Deposit amount"
|
title={<Translate>Deposit amount</Translate>}
|
||||||
text={amountToString(transaction.amountRaw)}
|
text={amountToString(transaction.amountRaw)}
|
||||||
kind="positive"
|
kind="positive"
|
||||||
/>
|
/>
|
||||||
<Part big title="Fee" text={amountToString(fee)} kind="negative" />
|
<Part
|
||||||
|
big
|
||||||
|
title={<Translate>Fee</Translate>}
|
||||||
|
text={amountToString(fee)}
|
||||||
|
kind="negative"
|
||||||
|
/>
|
||||||
</TransactionTemplate>
|
</TransactionTemplate>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -402,22 +440,29 @@ export function TransactionView({
|
|||||||
).amount;
|
).amount;
|
||||||
return (
|
return (
|
||||||
<TransactionTemplate>
|
<TransactionTemplate>
|
||||||
<h2>Refresh</h2>
|
<h2>
|
||||||
|
<Translate>Refresh</Translate>
|
||||||
|
</h2>
|
||||||
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
|
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
|
||||||
<br />
|
<br />
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Total refresh"
|
title={<Translate>Total refresh</Translate>}
|
||||||
text={amountToString(transaction.amountEffective)}
|
text={amountToString(transaction.amountEffective)}
|
||||||
kind="negative"
|
kind="negative"
|
||||||
/>
|
/>
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Refresh amount"
|
title={<Translate>Refresh amount</Translate>}
|
||||||
text={amountToString(transaction.amountRaw)}
|
text={amountToString(transaction.amountRaw)}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
<Part big title="Fee" text={amountToString(fee)} kind="negative" />
|
<Part
|
||||||
|
big
|
||||||
|
title={<Translate>Fee</Translate>}
|
||||||
|
text={amountToString(fee)}
|
||||||
|
kind="negative"
|
||||||
|
/>
|
||||||
</TransactionTemplate>
|
</TransactionTemplate>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -429,22 +474,29 @@ export function TransactionView({
|
|||||||
).amount;
|
).amount;
|
||||||
return (
|
return (
|
||||||
<TransactionTemplate>
|
<TransactionTemplate>
|
||||||
<h2>Tip</h2>
|
<h2>
|
||||||
|
<Translate>Tip</Translate>
|
||||||
|
</h2>
|
||||||
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
|
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
|
||||||
<br />
|
<br />
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Total tip"
|
title={<Translate>Total tip</Translate>}
|
||||||
text={amountToString(transaction.amountEffective)}
|
text={amountToString(transaction.amountEffective)}
|
||||||
kind="positive"
|
kind="positive"
|
||||||
/>
|
/>
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Received amount"
|
title={<Translate>Received amount</Translate>}
|
||||||
text={amountToString(transaction.amountRaw)}
|
text={amountToString(transaction.amountRaw)}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
<Part big title="Fee" text={amountToString(fee)} kind="negative" />
|
<Part
|
||||||
|
big
|
||||||
|
title={<Translate>Fee</Translate>}
|
||||||
|
text={amountToString(fee)}
|
||||||
|
kind="negative"
|
||||||
|
/>
|
||||||
</TransactionTemplate>
|
</TransactionTemplate>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -456,30 +508,41 @@ export function TransactionView({
|
|||||||
).amount;
|
).amount;
|
||||||
return (
|
return (
|
||||||
<TransactionTemplate>
|
<TransactionTemplate>
|
||||||
<h2>Refund</h2>
|
<h2>
|
||||||
|
<Translate>Refund</Translate>
|
||||||
|
</h2>
|
||||||
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
|
<Time timestamp={transaction.timestamp} format="dd MMMM yyyy, HH:mm" />
|
||||||
<br />
|
<br />
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Total refund"
|
title={<Translate>Total refund</Translate>}
|
||||||
text={amountToString(transaction.amountEffective)}
|
text={amountToString(transaction.amountEffective)}
|
||||||
kind="positive"
|
kind="positive"
|
||||||
/>
|
/>
|
||||||
<Part
|
<Part
|
||||||
big
|
big
|
||||||
title="Refund amount"
|
title={<Translate>Refund amount</Translate>}
|
||||||
text={amountToString(transaction.amountRaw)}
|
text={amountToString(transaction.amountRaw)}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
<Part big title="Fee" text={amountToString(fee)} kind="negative" />
|
|
||||||
<Part
|
<Part
|
||||||
title="Merchant"
|
big
|
||||||
|
title={<Translate>Fee</Translate>}
|
||||||
|
text={amountToString(fee)}
|
||||||
|
kind="negative"
|
||||||
|
/>
|
||||||
|
<Part
|
||||||
|
title={<Translate>Merchant</Translate>}
|
||||||
text={transaction.info.merchant.name}
|
text={transaction.info.merchant.name}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
<Part title="Purchase" text={transaction.info.summary} kind="neutral" />
|
|
||||||
<Part
|
<Part
|
||||||
title="Receipt"
|
title={<Translate>Purchase</Translate>}
|
||||||
|
text={transaction.info.summary}
|
||||||
|
kind="neutral"
|
||||||
|
/>
|
||||||
|
<Part
|
||||||
|
title={<Translate>Receipt</Translate>}
|
||||||
text={`#${transaction.info.orderId}`}
|
text={`#${transaction.info.orderId}`}
|
||||||
kind="neutral"
|
kind="neutral"
|
||||||
/>
|
/>
|
||||||
|
@ -17,10 +17,10 @@
|
|||||||
/**
|
/**
|
||||||
* Welcome page, shown on first installs.
|
* Welcome page, shown on first installs.
|
||||||
*
|
*
|
||||||
* @author Florian Dold
|
* @author sebasjm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { WalletDiagnostics } from "@gnu-taler/taler-util";
|
import { Translate, WalletDiagnostics } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { Checkbox } from "../components/Checkbox";
|
import { Checkbox } from "../components/Checkbox";
|
||||||
import { Diagnostics } from "../components/Diagnostics";
|
import { Diagnostics } from "../components/Diagnostics";
|
||||||
@ -54,24 +54,41 @@ export function View({
|
|||||||
}: ViewProps): VNode {
|
}: ViewProps): VNode {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<h1>Browser Extension Installed!</h1>
|
<h1>
|
||||||
|
<Translate>Browser Extension Installed!</Translate>
|
||||||
|
</h1>
|
||||||
<div>
|
<div>
|
||||||
<p>Thank you for installing the wallet.</p>
|
<p>
|
||||||
|
<Translate>Thank you for installing the wallet.</Translate>
|
||||||
|
</p>
|
||||||
<Diagnostics diagnostics={diagnostics} timedOut={timedOut} />
|
<Diagnostics diagnostics={diagnostics} timedOut={timedOut} />
|
||||||
<h2>Permissions</h2>
|
<h2>
|
||||||
|
<Translate>Permissions</Translate>
|
||||||
|
</h2>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="Automatically open wallet based on page content"
|
label={
|
||||||
|
<Translate>
|
||||||
|
Automatically open wallet based on page content
|
||||||
|
</Translate>
|
||||||
|
}
|
||||||
name="perm"
|
name="perm"
|
||||||
description="(Enabling this option below will make using the wallet faster, but requires more permissions from your browser.)"
|
description={
|
||||||
|
<Translate>
|
||||||
|
(Enabling this option below will make using the wallet faster, but
|
||||||
|
requires more permissions from your browser.)
|
||||||
|
</Translate>
|
||||||
|
}
|
||||||
enabled={permissionsEnabled}
|
enabled={permissionsEnabled}
|
||||||
onToggle={togglePermissions}
|
onToggle={togglePermissions}
|
||||||
/>
|
/>
|
||||||
<h2>Next Steps</h2>
|
<h2>
|
||||||
|
<Translate>Next Steps</Translate>
|
||||||
|
</h2>
|
||||||
<a href="https://demo.taler.net/" style={{ display: "block" }}>
|
<a href="https://demo.taler.net/" style={{ display: "block" }}>
|
||||||
Try the demo »
|
<Translate>Try the demo</Translate> »
|
||||||
</a>
|
</a>
|
||||||
<a href="https://demo.taler.net/" style={{ display: "block" }}>
|
<a href="https://demo.taler.net/" style={{ display: "block" }}>
|
||||||
Learn how to top up your wallet balance »
|
<Translate>Learn how to top up your wallet balance</Translate> »
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -17,10 +17,10 @@
|
|||||||
/**
|
/**
|
||||||
* Main entry point for extension pages.
|
* Main entry point for extension pages.
|
||||||
*
|
*
|
||||||
* @author Florian Dold <dold@taler.net>
|
* @author sebasjm <dold@taler.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { i18n, setupI18n } from "@gnu-taler/taler-util";
|
import { i18n, setupI18n, Translate } from "@gnu-taler/taler-util";
|
||||||
import { createHashHistory } from "history";
|
import { createHashHistory } from "history";
|
||||||
import { Fragment, h, render, VNode } from "preact";
|
import { Fragment, h, render, VNode } from "preact";
|
||||||
import Router, { route, Route } from "preact-router";
|
import Router, { route, Route } from "preact-router";
|
||||||
@ -78,7 +78,7 @@ if (document.readyState === "loading") {
|
|||||||
|
|
||||||
function Application(): VNode {
|
function Application(): VNode {
|
||||||
const [globalNotification, setGlobalNotification] = useState<
|
const [globalNotification, setGlobalNotification] = useState<
|
||||||
string | undefined
|
VNode | undefined
|
||||||
>(undefined);
|
>(undefined);
|
||||||
const hash_history = createHashHistory();
|
const hash_history = createHashHistory();
|
||||||
function clearNotification(): void {
|
function clearNotification(): void {
|
||||||
@ -169,7 +169,9 @@ function Application(): VNode {
|
|||||||
onSuccess={(currency: string) => {
|
onSuccess={(currency: string) => {
|
||||||
route(Pages.balance_history.replace(":currency", currency));
|
route(Pages.balance_history.replace(":currency", currency));
|
||||||
setGlobalNotification(
|
setGlobalNotification(
|
||||||
"All done, your transaction is in progress",
|
<Translate>
|
||||||
|
All done, your transaction is in progress
|
||||||
|
</Translate>,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -41,6 +41,12 @@ import { DepositFee } from "@gnu-taler/taler-wallet-core/src/operations/deposits
|
|||||||
import { ExchangeWithdrawDetails } from "@gnu-taler/taler-wallet-core/src/operations/withdraw";
|
import { ExchangeWithdrawDetails } from "@gnu-taler/taler-wallet-core/src/operations/withdraw";
|
||||||
import { MessageFromBackend } from "./wxBackend";
|
import { MessageFromBackend } from "./wxBackend";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @autor Florian Dold
|
||||||
|
* @autor sebasjm
|
||||||
|
*/
|
||||||
|
|
||||||
export interface ExtendedPermissionsResponse {
|
export interface ExtendedPermissionsResponse {
|
||||||
newValue: boolean;
|
newValue: boolean;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user