diff options
author | Florian Dold <florian.dold@gmail.com> | 2016-10-12 02:55:53 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2016-10-12 02:55:53 +0200 |
commit | d4be3906e32ac7d9933c6030d6493f2f2152bdd9 (patch) | |
tree | 3341586381b6975a3c1fa99ca69c63fba5ac9c35 /pages | |
parent | dbcd85451edfc33f2e0a42c431f0cf3ab3b12876 (diff) |
tree view of wallet db
Diffstat (limited to 'pages')
-rw-r--r-- | pages/confirm-create-reserve.tsx | 25 | ||||
-rw-r--r-- | pages/tree.html | 32 | ||||
-rw-r--r-- | pages/tree.tsx | 305 |
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); +} |