aboutsummaryrefslogtreecommitdiff
path: root/pages
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2016-10-12 02:55:53 +0200
committerFlorian Dold <florian.dold@gmail.com>2016-10-12 02:55:53 +0200
commitd4be3906e32ac7d9933c6030d6493f2f2152bdd9 (patch)
tree3341586381b6975a3c1fa99ca69c63fba5ac9c35 /pages
parentdbcd85451edfc33f2e0a42c431f0cf3ab3b12876 (diff)
tree view of wallet db
Diffstat (limited to 'pages')
-rw-r--r--pages/confirm-create-reserve.tsx25
-rw-r--r--pages/tree.html32
-rw-r--r--pages/tree.tsx305
3 files changed, 338 insertions, 24 deletions
diff --git a/pages/confirm-create-reserve.tsx b/pages/confirm-create-reserve.tsx
index a95bc46cb..3b5a4d161 100644
--- a/pages/confirm-create-reserve.tsx
+++ b/pages/confirm-create-reserve.tsx
@@ -27,6 +27,7 @@ import {AmountJson, CreateReserveResponse} from "../lib/wallet/types";
import {ReserveCreationInfo, Amounts} from "../lib/wallet/types";
import {Denomination} from "../lib/wallet/types";
import {getReserveCreationInfo} from "../lib/wallet/wxApi";
+import {ImplicitStateComponent, StateHolder} from "../lib/components";
"use strict";
@@ -63,30 +64,6 @@ class EventTrigger {
}
-interface StateHolder<T> {
- (): T;
- (newState: T): void;
-}
-
-/**
- * Component that doesn't hold its state in one object,
- * but has multiple state holders.
- */
-abstract class ImplicitStateComponent<PropType> extends preact.Component<PropType, void> {
- makeState<StateType>(initial: StateType): StateHolder<StateType> {
- let state: StateType = initial;
- return (s?: StateType): StateType => {
- if (s !== undefined) {
- state = s;
- // In preact, this will always schedule a (debounced) redraw
- this.setState({} as any);
- }
- return state;
- };
- }
-}
-
-
function renderReserveCreationDetails(rci: ReserveCreationInfo|null) {
if (!rci) {
return <p>
diff --git a/pages/tree.html b/pages/tree.html
new file mode 100644
index 000000000..ee12a82e4
--- /dev/null
+++ b/pages/tree.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <title>Taler Wallet: Tree View</title>
+
+ <link rel="stylesheet" type="text/css" href="../style/lang.css">
+ <link rel="stylesheet" type="text/css" href="../style/wallet.css">
+
+ <link rel="icon" href="../img/icon.png">
+
+ <script src="../lib/vendor/URI.js"></script>
+ <script src="../lib/vendor/preact.js"></script>
+
+ <!-- i18n -->
+ <script src="../lib/vendor/jed.js"></script>
+ <script src="../lib/i18n.js"></script>
+ <script src="../i18n/strings.js"></script>
+
+ <script src="../lib/vendor/system-csp-production.src.js"></script>
+ <script src="../lib/module-trampoline.js"></script>
+
+ <style>
+ .tree-item {
+ margin: 2em;
+ border-radius: 5px;
+ border: 1px solid gray;
+ padding: 1em;
+ }
+ </style>
+
+</html> \ No newline at end of file
diff --git a/pages/tree.tsx b/pages/tree.tsx
new file mode 100644
index 000000000..acc470216
--- /dev/null
+++ b/pages/tree.tsx
@@ -0,0 +1,305 @@
+/*
+ This file is part of TALER
+ (C) 2016 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/>
+ */
+
+/**
+ * Show contents of the wallet as a tree.
+ *
+ * @author Florian Dold
+ */
+
+/// <reference path="../lib/decl/preact.d.ts" />
+
+import { IExchangeInfo } from "../lib/wallet/types";
+import { Reserve, Coin, PreCoin, Denomination } from "../lib/wallet/types";
+import { ImplicitStateComponent, StateHolder } from "../lib/components";
+import { getReserves, getExchanges, getCoins, getPreCoins } from "../lib/wallet/wxApi";
+import { prettyAmount, abbrev } from "../lib/wallet/renderHtml";
+
+interface ReserveViewProps {
+ reserve: Reserve;
+}
+
+class ReserveView extends preact.Component<ReserveViewProps, void> {
+ render(): JSX.Element {
+ let r: Reserve = this.props.reserve;
+ return (
+ <div className="tree-item">
+ <ul>
+ <li>Key: {r.reserve_pub}</li>
+ <li>Created: {(new Date(r.created * 1000).toString())}</li>
+ </ul>
+ </div>
+ );
+ }
+}
+
+interface ReserveListProps {
+ exchangeBaseUrl: string;
+}
+
+interface ToggleProps {
+ expanded: StateHolder<boolean>;
+}
+
+class Toggle extends ImplicitStateComponent<ToggleProps> {
+ renderButton() {
+ let show = () => {
+ this.props.expanded(true);
+ this.setState({});
+ };
+ let hide = () => {
+ this.props.expanded(false);
+ this.setState({});
+ };
+ if (this.props.expanded()) {
+ return <button onClick={hide}>hide</button>;
+ }
+ return <button onClick={show}>show</button>;
+
+ }
+ render() {
+ return (
+ <div style="display:inline;">
+ {this.renderButton()}
+ {this.props.expanded() ? this.props.children : []}
+ </div>);
+ }
+}
+
+
+interface CoinViewProps {
+ coin: Coin;
+}
+
+class CoinView extends preact.Component<CoinViewProps, void> {
+ render() {
+ let c = this.props.coin;
+ return (
+ <div className="tree-item">
+ <ul>
+ <li>Key: {c.coinPub}</li>
+ <li>Current amount: {prettyAmount(c.currentAmount)}</li>
+ <li>Denomination: {abbrev(c.denomPub, 20)}</li>
+ <li>Suspended: {(c.suspended || false).toString()}</li>
+ </ul>
+ </div>
+ );
+ }
+}
+
+
+
+interface PreCoinViewProps {
+ precoin: PreCoin;
+}
+
+class PreCoinView extends preact.Component<PreCoinViewProps, void> {
+ render() {
+ let c = this.props.precoin;
+ return (
+ <div className="tree-item">
+ <ul>
+ <li>Key: {c.coinPub}</li>
+ </ul>
+ </div>
+ );
+ }
+}
+
+interface CoinListProps {
+ exchangeBaseUrl: string;
+}
+
+class CoinList extends ImplicitStateComponent<CoinListProps> {
+ coins = this.makeState<Coin[] | null>(null);
+ expanded = this.makeState<boolean>(false);
+
+ constructor(props: CoinListProps) {
+ super(props);
+ this.update();
+ }
+
+ async update() {
+ let coins = await getCoins(this.props.exchangeBaseUrl);
+ this.coins(coins);
+ }
+
+ render(): JSX.Element {
+ if (!this.coins()) {
+ return <div>...</div>;
+ }
+ return (
+ <div className="tree-item">
+ Coins ({this.coins() !.length.toString()})
+ {" "}
+ <Toggle expanded={this.expanded}>
+ {this.coins() !.map((c) => <CoinView coin={c} />)}
+ </Toggle>
+ </div>
+ );
+ }
+}
+
+
+interface PreCoinListProps {
+ exchangeBaseUrl: string;
+}
+
+class PreCoinList extends ImplicitStateComponent<PreCoinListProps> {
+ precoins = this.makeState<PreCoin[] | null>(null);
+ expanded = this.makeState<boolean>(false);
+
+ constructor(props: PreCoinListProps) {
+ super(props);
+ this.update();
+ }
+
+ async update() {
+ let precoins = await getPreCoins(this.props.exchangeBaseUrl);
+ this.precoins(precoins);
+ }
+
+ render(): JSX.Element {
+ if (!this.precoins()) {
+ return <div>...</div>;
+ }
+ return (
+ <div className="tree-item">
+ Pre-Coins ({this.precoins() !.length.toString()})
+ {" "}
+ <Toggle expanded={this.expanded}>
+ {this.precoins() !.map((c) => <PreCoinView precoin={c} />)}
+ </Toggle>
+ </div>
+ );
+ }
+}
+
+interface DenominationListProps {
+ exchange: IExchangeInfo;
+}
+
+class DenominationList extends ImplicitStateComponent<DenominationListProps> {
+ expanded = this.makeState<boolean>(false);
+
+ renderDenom(d: Denomination) {
+ return (
+ <div className="tree-item">
+ <ul>
+ <li>Value: {prettyAmount(d.value)}</li>
+ <li>Withdraw fee: {prettyAmount(d.fee_withdraw)}</li>
+ <li>Refresh fee: {prettyAmount(d.fee_refresh)}</li>
+ <li>Deposit fee: {prettyAmount(d.fee_deposit)}</li>
+ <li>Refund fee: {prettyAmount(d.fee_refund)}</li>
+ </ul>
+ </div>
+ );
+ }
+
+ render(): JSX.Element {
+ return (
+ <div className="tree-item">
+ Denominations ({this.props.exchange.active_denoms.length.toString()})
+ {" "}
+ <Toggle expanded={this.expanded}>
+ {this.props.exchange.active_denoms.map((d) => this.renderDenom(d))}
+ </Toggle>
+ </div>
+ );
+ }
+}
+
+class ReserveList extends ImplicitStateComponent<ReserveListProps> {
+ reserves = this.makeState<Reserve[] | null>(null);
+ expanded = this.makeState<boolean>(false);
+
+ constructor(props: ReserveListProps) {
+ super(props);
+ this.update();
+ }
+
+ async update() {
+ let reserves = await getReserves(this.props.exchangeBaseUrl);
+ this.reserves(reserves);
+ }
+
+ render(): JSX.Element {
+ if (!this.reserves()) {
+ return <div>...</div>;
+ }
+ return (
+ <div className="tree-item">
+ Reserves ({this.reserves() !.length.toString()})
+ {" "}
+ <Toggle expanded={this.expanded}>
+ {this.reserves() !.map((r) => <ReserveView reserve={r} />)}
+ </Toggle>
+ </div>
+ );
+ }
+}
+
+interface ExchangeProps {
+ exchange: IExchangeInfo;
+}
+
+class ExchangeView extends preact.Component<ExchangeProps, void> {
+ render(): JSX.Element {
+ let e = this.props.exchange;
+ return (
+ <div className="tree-item">
+ Url: {this.props.exchange.baseUrl}
+ <DenominationList exchange={e} />
+ <ReserveList exchangeBaseUrl={this.props.exchange.baseUrl} />
+ <CoinList exchangeBaseUrl={this.props.exchange.baseUrl} />
+ <PreCoinList exchangeBaseUrl={this.props.exchange.baseUrl} />
+ </div>
+ );
+ }
+}
+
+interface ExchangesListState {
+ exchanges: IExchangeInfo[];
+}
+
+class ExchangesList extends preact.Component<any, ExchangesListState> {
+ constructor() {
+ super();
+ this.update();
+ }
+
+ async update() {
+ let exchanges = await getExchanges();
+ console.log("exchanges: ", exchanges);
+ this.setState({ exchanges });
+ }
+
+ render(): JSX.Element {
+ if (!this.state.exchanges) {
+ return <span>...</span>;
+ }
+ return (
+ <div className="tree-item">
+ Exchanges ({this.state.exchanges.length.toString()}):
+ {this.state.exchanges.map(e => <ExchangeView exchange={e} />)}
+ </div>
+ );
+ }
+}
+
+export function main() {
+ preact.render(<ExchangesList />, document.body);
+}