refactor / format
This commit is contained in:
parent
8144b0f553
commit
51aa6d8146
@ -23,14 +23,13 @@
|
||||
|
||||
import * as i18n from "../../i18n";
|
||||
|
||||
import { runOnceWhenReady } from "./common";
|
||||
|
||||
import { BenchmarkResult } from "../../walletTypes";
|
||||
|
||||
import * as wxApi from "../wxApi";
|
||||
|
||||
import * as React from "react";
|
||||
import * as ReactDOM from "react-dom";
|
||||
import { registerMountPage } from "../renderHtml";
|
||||
|
||||
|
||||
interface BenchmarkRunnerState {
|
||||
@ -103,9 +102,6 @@ class BenchmarkRunner extends React.Component<any, BenchmarkRunnerState> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
runOnceWhenReady(() => {
|
||||
ReactDOM.render(<BenchmarkRunner />, document.getElementById("container")!);
|
||||
// Will be used by the backend to detect when the popup gets closed,
|
||||
// so we can clear notifications
|
||||
registerMountPage(() => {
|
||||
return <BenchmarkRunner />;
|
||||
});
|
||||
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
(C) 2018 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/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Common helper functions for all web extension pages.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Make sure that a function is executed exactly once
|
||||
* after the DOM has been loaded.
|
||||
*/
|
||||
export function runOnceWhenReady(f: () => void): void {
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", f);
|
||||
return;
|
||||
}
|
||||
f();
|
||||
}
|
@ -72,7 +72,7 @@
|
||||
<body>
|
||||
<section id="main">
|
||||
<h1>GNU Taler Wallet</h1>
|
||||
<article id="contract" class="fade"></article>
|
||||
<article id="container" class="fade"></article>
|
||||
</section>
|
||||
</body>
|
||||
|
||||
|
@ -24,19 +24,13 @@
|
||||
*/
|
||||
import * as i18n from "../../i18n";
|
||||
|
||||
import { runOnceWhenReady } from "./common";
|
||||
|
||||
import { ExchangeRecord, ProposalDownloadRecord } from "../../dbTypes";
|
||||
import { ContractTerms } from "../../talerTypes";
|
||||
import { CheckPayResult, PreparePayResult } from "../../walletTypes";
|
||||
|
||||
import { renderAmount, ProgressButton } from "../renderHtml";
|
||||
import { renderAmount, ProgressButton, registerMountPage } from "../renderHtml";
|
||||
import * as wxApi from "../wxApi";
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import * as ReactDOM from "react-dom";
|
||||
import URI = require("urijs");
|
||||
import { WalletApiError } from "../wxApi";
|
||||
|
||||
import * as Amounts from "../../amounts";
|
||||
|
||||
@ -153,22 +147,11 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
runOnceWhenReady(() => {
|
||||
try {
|
||||
registerMountPage(() => {
|
||||
const url = new URI(document.location.href);
|
||||
const query: any = URI.parseQuery(url.query());
|
||||
|
||||
let talerPayUri = query.talerPayUri;
|
||||
|
||||
ReactDOM.render(
|
||||
<TalerPayDialog talerPayUri={talerPayUri} />,
|
||||
document.getElementById("contract")!,
|
||||
);
|
||||
} catch (e) {
|
||||
ReactDOM.render(
|
||||
<span>Fatal error: {e.message}</span>,
|
||||
document.getElementById("contract")!,
|
||||
);
|
||||
console.error(e);
|
||||
}
|
||||
return <TalerPayDialog talerPayUri={talerPayUri} />;
|
||||
});
|
||||
|
@ -12,7 +12,7 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="content" style="margin:0;padding:0"></div>
|
||||
<div id="container" style="margin:0;padding:0"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
@ -26,8 +26,6 @@
|
||||
*/
|
||||
import * as i18n from "../../i18n";
|
||||
|
||||
import { runOnceWhenReady } from "./common";
|
||||
|
||||
import { AmountJson } from "../../amounts";
|
||||
import * as Amounts from "../../amounts";
|
||||
|
||||
@ -37,7 +35,12 @@ import {
|
||||
WalletBalanceEntry,
|
||||
} from "../../walletTypes";
|
||||
|
||||
import { abbrev, renderAmount, PageLink } from "../renderHtml";
|
||||
import {
|
||||
abbrev,
|
||||
renderAmount,
|
||||
PageLink,
|
||||
registerMountPage,
|
||||
} from "../renderHtml";
|
||||
import * as wxApi from "../wxApi";
|
||||
|
||||
import * as React from "react";
|
||||
@ -196,8 +199,7 @@ function EmptyBalanceView() {
|
||||
<div>
|
||||
<i18n.Translate wrap="p">
|
||||
You have no balance to show. Need some{" "}
|
||||
<PageLink pageName="welcome.html">help</PageLink> getting
|
||||
started?
|
||||
<PageLink pageName="welcome.html">help</PageLink> getting started?
|
||||
</i18n.Translate>
|
||||
</div>
|
||||
);
|
||||
@ -303,7 +305,8 @@ class WalletBalanceView extends React.Component<any, any> {
|
||||
<div>
|
||||
<p>{i18n.str`Error: could not retrieve balance information.`}</p>
|
||||
<p>
|
||||
Click <PageLink pageName="welcome.html">here</PageLink> for help and diagnostics.
|
||||
Click <PageLink pageName="welcome.html">here</PageLink> for help and
|
||||
diagnostics.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
@ -551,7 +554,8 @@ function openTab(page: string) {
|
||||
};
|
||||
}
|
||||
|
||||
const el = (
|
||||
function WalletPopup() {
|
||||
return (
|
||||
<div>
|
||||
<WalletNavBar />
|
||||
<div style={{ margin: "1em" }}>
|
||||
@ -562,11 +566,10 @@ const el = (
|
||||
</Router>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
runOnceWhenReady(() => {
|
||||
ReactDOM.render(el, document.getElementById("content")!);
|
||||
// Will be used by the backend to detect when the popup gets closed,
|
||||
// so we can clear notifications
|
||||
registerMountPage(() => {
|
||||
chrome.runtime.connect({ name: "popup" });
|
||||
return <WalletPopup />
|
||||
});
|
||||
|
@ -20,24 +20,18 @@
|
||||
* @author Florian Dold
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Imports.
|
||||
*/
|
||||
import { AmountJson } from "../amounts";
|
||||
import * as Amounts from "../amounts";
|
||||
import {
|
||||
DenominationRecord,
|
||||
} from "../dbTypes";
|
||||
import {
|
||||
ReserveCreationInfo,
|
||||
} from "../walletTypes";
|
||||
import { DenominationRecord } from "../dbTypes";
|
||||
import { ReserveCreationInfo } from "../walletTypes";
|
||||
import * as moment from "moment";
|
||||
import * as i18n from "../i18n";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
|
||||
/**
|
||||
* Render amount as HTML, which non-breaking space between
|
||||
* decimal value and currency.
|
||||
@ -53,11 +47,15 @@ export function renderAmount(amount: AmountJson | string) {
|
||||
return <span>(invalid amount)</span>;
|
||||
}
|
||||
const x = a.value + a.fraction / Amounts.fractionalBase;
|
||||
return <span>{x} {a.currency}</span>;
|
||||
return (
|
||||
<span>
|
||||
{x} {a.currency}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export const AmountView = ({amount}: {amount: AmountJson | string}) => renderAmount(amount);
|
||||
|
||||
export const AmountView = ({ amount }: { amount: AmountJson | string }) =>
|
||||
renderAmount(amount);
|
||||
|
||||
/**
|
||||
* Abbreviate a string to a given length, and show the full
|
||||
@ -75,50 +73,61 @@ export function abbrev(s: string, n: number = 5) {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
interface CollapsibleState {
|
||||
collapsed: boolean;
|
||||
}
|
||||
|
||||
|
||||
interface CollapsibleProps {
|
||||
initiallyCollapsed: boolean;
|
||||
title: string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Component that shows/hides its children when clicking
|
||||
* a heading.
|
||||
*/
|
||||
export class Collapsible extends React.Component<CollapsibleProps, CollapsibleState> {
|
||||
export class Collapsible extends React.Component<
|
||||
CollapsibleProps,
|
||||
CollapsibleState
|
||||
> {
|
||||
constructor(props: CollapsibleProps) {
|
||||
super(props);
|
||||
this.state = { collapsed: props.initiallyCollapsed };
|
||||
}
|
||||
render() {
|
||||
const doOpen = (e: any) => {
|
||||
this.setState({collapsed: false});
|
||||
this.setState({ collapsed: false });
|
||||
e.preventDefault();
|
||||
};
|
||||
const doClose = (e: any) => {
|
||||
this.setState({collapsed: true});
|
||||
this.setState({ collapsed: true });
|
||||
e.preventDefault();
|
||||
};
|
||||
if (this.state.collapsed) {
|
||||
return <h2><a className="opener opener-collapsed" href="#" onClick={doOpen}>{this.props.title}</a></h2>;
|
||||
return (
|
||||
<h2>
|
||||
<a className="opener opener-collapsed" href="#" onClick={doOpen}>
|
||||
{this.props.title}
|
||||
</a>
|
||||
</h2>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<h2><a className="opener opener-open" href="#" onClick={doClose}>{this.props.title}</a></h2>
|
||||
<h2>
|
||||
<a className="opener opener-open" href="#" onClick={doClose}>
|
||||
{this.props.title}
|
||||
</a>
|
||||
</h2>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function AuditorDetailsView(props: {rci: ReserveCreationInfo|null}): JSX.Element {
|
||||
function AuditorDetailsView(props: {
|
||||
rci: ReserveCreationInfo | null;
|
||||
}): JSX.Element {
|
||||
const rci = props.rci;
|
||||
console.log("rci", rci);
|
||||
if (!rci) {
|
||||
@ -129,27 +138,33 @@ function AuditorDetailsView(props: {rci: ReserveCreationInfo|null}): JSX.Element
|
||||
);
|
||||
}
|
||||
if (rci.exchangeInfo.auditors.length === 0) {
|
||||
return (
|
||||
<p>
|
||||
The exchange is not audited by any auditors.
|
||||
</p>
|
||||
);
|
||||
return <p>The exchange is not audited by any auditors.</p>;
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
{rci.exchangeInfo.auditors.map((a) => (
|
||||
{rci.exchangeInfo.auditors.map(a => (
|
||||
<div>
|
||||
<h3>Auditor {a.auditor_url}</h3>
|
||||
<p>Public key: <ExpanderText text={a.auditor_pub} /></p>
|
||||
<p>Trusted: {rci.trustedAuditorPubs.indexOf(a.auditor_pub) >= 0 ? "yes" : "no"}</p>
|
||||
<p>Audits {a.denomination_keys.length} of {rci.numOfferedDenoms} denominations</p>
|
||||
<p>
|
||||
Public key: <ExpanderText text={a.auditor_pub} />
|
||||
</p>
|
||||
<p>
|
||||
Trusted:{" "}
|
||||
{rci.trustedAuditorPubs.indexOf(a.auditor_pub) >= 0 ? "yes" : "no"}
|
||||
</p>
|
||||
<p>
|
||||
Audits {a.denomination_keys.length} of {rci.numOfferedDenoms}{" "}
|
||||
denominations
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function FeeDetailsView(props: {rci: ReserveCreationInfo|null}): JSX.Element {
|
||||
function FeeDetailsView(props: {
|
||||
rci: ReserveCreationInfo | null;
|
||||
}): JSX.Element {
|
||||
const rci = props.rci;
|
||||
if (!rci) {
|
||||
return (
|
||||
@ -161,7 +176,7 @@ function FeeDetailsView(props: {rci: ReserveCreationInfo|null}): JSX.Element {
|
||||
|
||||
const denoms = rci.selectedDenoms;
|
||||
|
||||
const countByPub: {[s: string]: number} = {};
|
||||
const countByPub: { [s: string]: number } = {};
|
||||
const uniq: DenominationRecord[] = [];
|
||||
|
||||
denoms.forEach((x: DenominationRecord) => {
|
||||
@ -198,7 +213,7 @@ function FeeDetailsView(props: {rci: ReserveCreationInfo|null}): JSX.Element {
|
||||
</tr>
|
||||
</thead>,
|
||||
<tbody>
|
||||
{rci!.wireFees.feesForType[s].map((f) => (
|
||||
{rci!.wireFees.feesForType[s].map(f => (
|
||||
<tr>
|
||||
<td>{moment.unix(f.endStamp).format("llll")}</td>
|
||||
<td>{renderAmount(f.wireFee)}</td>
|
||||
@ -215,12 +230,20 @@ function FeeDetailsView(props: {rci: ReserveCreationInfo|null}): JSX.Element {
|
||||
return (
|
||||
<div>
|
||||
<h3>Overview</h3>
|
||||
<p>Public key: <ExpanderText text={rci.exchangeInfo.masterPublicKey} /></p>
|
||||
<p>{i18n.str`Withdrawal fees:`} {withdrawFee}</p>
|
||||
<p>{i18n.str`Rounding loss:`} {overhead}</p>
|
||||
<p>{i18n.str`Earliest expiration (for deposit): ${moment.unix(rci.earliestDepositExpiration).fromNow()}`}</p>
|
||||
<p>
|
||||
Public key: <ExpanderText text={rci.exchangeInfo.masterPublicKey} />
|
||||
</p>
|
||||
<p>
|
||||
{i18n.str`Withdrawal fees:`} {withdrawFee}
|
||||
</p>
|
||||
<p>
|
||||
{i18n.str`Rounding loss:`} {overhead}
|
||||
</p>
|
||||
<p>{i18n.str`Earliest expiration (for deposit): ${moment
|
||||
.unix(rci.earliestDepositExpiration)
|
||||
.fromNow()}`}</p>
|
||||
<h3>Coin Fees</h3>
|
||||
<div style={{overflow: "auto"}}>
|
||||
<div style={{ overflow: "auto" }}>
|
||||
<table className="pure-table">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -231,13 +254,11 @@ function FeeDetailsView(props: {rci: ReserveCreationInfo|null}): JSX.Element {
|
||||
<th>{i18n.str`Deposit Fee`}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{uniq.map(row)}
|
||||
</tbody>
|
||||
<tbody>{uniq.map(row)}</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<h3>Wire Fees</h3>
|
||||
<div style={{overflow: "auto"}}>
|
||||
<div style={{ overflow: "auto" }}>
|
||||
<table className="pure-table">
|
||||
{Object.keys(rci.wireFees.feesForType).map(wireFee)}
|
||||
</table>
|
||||
@ -249,7 +270,9 @@ function FeeDetailsView(props: {rci: ReserveCreationInfo|null}): JSX.Element {
|
||||
/**
|
||||
* Shows details about a withdraw request.
|
||||
*/
|
||||
export function WithdrawDetailView(props: {rci: ReserveCreationInfo | null}): JSX.Element {
|
||||
export function WithdrawDetailView(props: {
|
||||
rci: ReserveCreationInfo | null;
|
||||
}): JSX.Element {
|
||||
const rci = props.rci;
|
||||
return (
|
||||
<div>
|
||||
@ -263,12 +286,10 @@ export function WithdrawDetailView(props: {rci: ReserveCreationInfo | null}): JS
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
interface ExpanderTextProps {
|
||||
text: string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show a heading with a toggle to show/hide the expandable content.
|
||||
*/
|
||||
@ -276,16 +297,13 @@ export function ExpanderText({ text }: ExpanderTextProps) {
|
||||
return <span>{text}</span>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export interface LoadingButtonProps {
|
||||
loading: boolean;
|
||||
}
|
||||
|
||||
export function ProgressButton(
|
||||
props:
|
||||
& React.PropsWithChildren<LoadingButtonProps>
|
||||
& React.DetailedHTMLProps<
|
||||
props: React.PropsWithChildren<LoadingButtonProps> &
|
||||
React.DetailedHTMLProps<
|
||||
React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
HTMLButtonElement
|
||||
>,
|
||||
@ -296,8 +314,14 @@ export function ProgressButton(
|
||||
type="button"
|
||||
{...props}
|
||||
>
|
||||
{props.loading ? <span><object className="svg-icon svg-baseline" data="/img/spinner-bars.svg" /></span> : null}
|
||||
{" "}
|
||||
{props.loading ? (
|
||||
<span>
|
||||
<object
|
||||
className="svg-icon svg-baseline"
|
||||
data="/img/spinner-bars.svg"
|
||||
/>
|
||||
</span>
|
||||
) : null}{" "}
|
||||
{props.children}
|
||||
</button>
|
||||
);
|
||||
@ -311,10 +335,7 @@ export function registerMountPage(mainFn: () => React.ReactElement) {
|
||||
if (!container) {
|
||||
throw Error("container not found, can't mount page contents");
|
||||
}
|
||||
ReactDOM.render(
|
||||
mainElement,
|
||||
container,
|
||||
);
|
||||
ReactDOM.render(mainElement, container);
|
||||
} catch (e) {
|
||||
document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`;
|
||||
console.error("got error", e);
|
||||
@ -329,7 +350,11 @@ export function registerMountPage(mainFn: () => React.ReactElement) {
|
||||
}
|
||||
}
|
||||
|
||||
export function PageLink(props: React.PropsWithChildren<{pageName: string}>) {
|
||||
export function PageLink(props: React.PropsWithChildren<{ pageName: string }>) {
|
||||
const url = chrome.extension.getURL(`/src/webex/pages/${props.pageName}`);
|
||||
return <a className="actionLink" href={url} target="_blank">{props.children}</a>;
|
||||
return (
|
||||
<a className="actionLink" href={url} target="_blank">
|
||||
{props.children}
|
||||
</a>
|
||||
);
|
||||
}
|
@ -71,7 +71,6 @@
|
||||
"src/webex/pages/add-auditor.tsx",
|
||||
"src/webex/pages/auditors.tsx",
|
||||
"src/webex/pages/benchmark.tsx",
|
||||
"src/webex/pages/common.ts",
|
||||
"src/webex/pages/error.tsx",
|
||||
"src/webex/pages/logs.tsx",
|
||||
"src/webex/pages/pay.tsx",
|
||||
|
Loading…
Reference in New Issue
Block a user