fix small react issues
This commit is contained in:
parent
b2128609ac
commit
eb84d5747a
@ -102,6 +102,25 @@ namespace TalerNotify {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function saveOffer(offer: any): Promise<number> {
|
||||||
|
const walletMsg = {
|
||||||
|
type: "save-offer",
|
||||||
|
detail: {
|
||||||
|
offer: {
|
||||||
|
contract: offer.contract,
|
||||||
|
merchant_sig: offer.merchant_sig,
|
||||||
|
H_contract: offer.H_contract,
|
||||||
|
offer_time: new Date().getTime() / 1000
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
chrome.runtime.sendMessage(walletMsg, (resp: any) => {
|
||||||
|
resolve(resp);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
chrome.runtime.sendMessage({type: "get-tab-cookie"}, (resp) => {
|
chrome.runtime.sendMessage({type: "get-tab-cookie"}, (resp) => {
|
||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError) {
|
||||||
@ -270,12 +289,12 @@ namespace TalerNotify {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
await putHistory(historyEntry);
|
await putHistory(historyEntry);
|
||||||
|
let offerId = await saveOffer(offer);
|
||||||
|
|
||||||
const uri = URI(chrome.extension.getURL(
|
const uri = URI(chrome.extension.getURL(
|
||||||
"pages/confirm-contract.html"));
|
"pages/confirm-contract.html"));
|
||||||
const params = {
|
const params = {
|
||||||
offer: JSON.stringify(offer),
|
offerId: offerId.toString(),
|
||||||
merchantPageUrl: document.location.href,
|
|
||||||
};
|
};
|
||||||
const target = uri.query(params).href();
|
const target = uri.query(params).href();
|
||||||
if (msg.replace_navigation === true) {
|
if (msg.replace_navigation === true) {
|
||||||
|
18525
lib/vendor/react-dom.js
vendored
18525
lib/vendor/react-dom.js
vendored
File diff suppressed because it is too large
Load Diff
1
lib/vendor/react-dom.js
vendored
Symbolic link
1
lib/vendor/react-dom.js
vendored
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
react-dom.min.js
|
3783
lib/vendor/react.js
vendored
3783
lib/vendor/react.js
vendored
File diff suppressed because it is too large
Load Diff
1
lib/vendor/react.js
vendored
Symbolic link
1
lib/vendor/react.js
vendored
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
react.min.js
|
@ -26,7 +26,7 @@ import {IExchangeInfo} from "./types";
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const DB_NAME = "taler";
|
const DB_NAME = "taler";
|
||||||
const DB_VERSION = 10;
|
const DB_VERSION = 11;
|
||||||
|
|
||||||
import {Stores} from "./wallet";
|
import {Stores} from "./wallet";
|
||||||
import {Store, Index} from "./query";
|
import {Store, Index} from "./query";
|
||||||
@ -114,4 +114,4 @@ export function exportDb(db: IDBDatabase): Promise<any> {
|
|||||||
|
|
||||||
export function deleteDb() {
|
export function deleteDb() {
|
||||||
indexedDB.deleteDatabase(DB_NAME);
|
indexedDB.deleteDatabase(DB_NAME);
|
||||||
}
|
}
|
||||||
|
@ -423,6 +423,22 @@ export class QueryRoot implements PromiseLike<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
putWithResult<T>(store: Store<T>, val: T): Promise<IDBValidKey> {
|
||||||
|
const {resolve, promise} = openPromise();
|
||||||
|
let doPutWithResult = (tx: IDBTransaction) => {
|
||||||
|
let req = tx.objectStore(store.name).put(val);
|
||||||
|
req.onsuccess = () => {
|
||||||
|
resolve(req.result);
|
||||||
|
}
|
||||||
|
this.scheduleFinish();
|
||||||
|
};
|
||||||
|
this.addWork(doPutWithResult, store.name, true);
|
||||||
|
return Promise.resolve()
|
||||||
|
.then(() => this.finish())
|
||||||
|
.then(() => promise);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
mutate<T>(store: Store<T>, key: any, f: (v: T) => T): QueryRoot {
|
mutate<T>(store: Store<T>, key: any, f: (v: T) => T): QueryRoot {
|
||||||
let doPut = (tx: IDBTransaction) => {
|
let doPut = (tx: IDBTransaction) => {
|
||||||
let reqGet = tx.objectStore(store.name).get(key);
|
let reqGet = tx.objectStore(store.name).get(key);
|
||||||
|
@ -34,15 +34,15 @@ export function renderContract(contract: Contract): JSX.Element {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>{
|
<p>
|
||||||
i18n.parts`${merchantName}
|
The merchant {merchantName}
|
||||||
wants to enter a contract over ${amount}
|
wants to enter a contract over {amount}{" "}
|
||||||
with you.`}
|
with you.
|
||||||
</p>
|
</p>
|
||||||
<p>{i18n`You are about to purchase:`}</p>
|
<p>{i18n`You are about to purchase:`}</p>
|
||||||
<ul>
|
<ul>
|
||||||
{contract.products.map(
|
{contract.products.map(
|
||||||
(p: any) => (<li>{`${p.description}: ${prettyAmount(p.price)}`}</li>))
|
(p: any, i: number) => (<li key={i}>{`${p.description}: ${prettyAmount(p.price)}`}</li>))
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -142,6 +142,15 @@ export class Offer {
|
|||||||
@Checkable.String
|
@Checkable.String
|
||||||
H_contract: string;
|
H_contract: string;
|
||||||
|
|
||||||
|
@Checkable.Number
|
||||||
|
offer_time: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serial ID when the offer is stored in the wallet DB.
|
||||||
|
*/
|
||||||
|
@Checkable.Optional(Checkable.Number)
|
||||||
|
id?: number;
|
||||||
|
|
||||||
static checked: (obj: any) => Offer;
|
static checked: (obj: any) => Offer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,6 +306,15 @@ export namespace Stores {
|
|||||||
timestampIndex = new Index<number,HistoryRecord>(this, "timestamp", "timestamp");
|
timestampIndex = new Index<number,HistoryRecord>(this, "timestamp", "timestamp");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class OffersStore extends Store<Offer> {
|
||||||
|
constructor() {
|
||||||
|
super("offers", {
|
||||||
|
keyPath: "id",
|
||||||
|
autoIncrement: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class TransactionsStore extends Store<Transaction> {
|
class TransactionsStore extends Store<Transaction> {
|
||||||
constructor() {
|
constructor() {
|
||||||
super("transactions", {keyPath: "contractHash"});
|
super("transactions", {keyPath: "contractHash"});
|
||||||
@ -314,6 +332,7 @@ export namespace Stores {
|
|||||||
export let coins: CoinsStore = new CoinsStore();
|
export let coins: CoinsStore = new CoinsStore();
|
||||||
export let refresh: Store<RefreshSession> = new Store<RefreshSession>("refresh", {keyPath: "meltCoinPub"});
|
export let refresh: Store<RefreshSession> = new Store<RefreshSession>("refresh", {keyPath: "meltCoinPub"});
|
||||||
export let history: HistoryStore = new HistoryStore();
|
export let history: HistoryStore = new HistoryStore();
|
||||||
|
export let offers: OffersStore = new OffersStore();
|
||||||
export let precoins: Store<PreCoin> = new Store<PreCoin>("precoins", {keyPath: "coinPub"});
|
export let precoins: Store<PreCoin> = new Store<PreCoin>("precoins", {keyPath: "coinPub"});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,6 +604,18 @@ export class Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async saveOffer(offer: Offer): Promise<number> {
|
||||||
|
console.log(`saving offer in wallet.ts`);
|
||||||
|
let id = await this.q().putWithResult(Stores.offers, offer);
|
||||||
|
this.notifier.notify();
|
||||||
|
console.log(`saved offer with id ${id}`);
|
||||||
|
if (typeof id !== "number") {
|
||||||
|
throw Error("db schema wrong");
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a contract to the wallet and sign coins,
|
* Add a contract to the wallet and sign coins,
|
||||||
* but do not send them yet.
|
* but do not send them yet.
|
||||||
@ -1525,6 +1556,12 @@ export class Wallet {
|
|||||||
return {history};
|
return {history};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async getOffer(offerId: number): Promise<any> {
|
||||||
|
let offer = await this.q() .get(Stores.offers, offerId);
|
||||||
|
return offer;
|
||||||
|
}
|
||||||
|
|
||||||
async getExchanges(): Promise<IExchangeInfo[]> {
|
async getExchanges(): Promise<IExchangeInfo[]> {
|
||||||
return this.q()
|
return this.q()
|
||||||
.iter<IExchangeInfo>(Stores.exchanges)
|
.iter<IExchangeInfo>(Stores.exchanges)
|
||||||
|
@ -168,6 +168,14 @@ function makeHandlers(db: IDBDatabase,
|
|||||||
}
|
}
|
||||||
return wallet.putHistory(detail.historyEntry);
|
return wallet.putHistory(detail.historyEntry);
|
||||||
},
|
},
|
||||||
|
["save-offer"]: function (detail: any) {
|
||||||
|
let offer = detail.offer;
|
||||||
|
if (!offer) {
|
||||||
|
return Promise.resolve({ error: "offer missing" });
|
||||||
|
}
|
||||||
|
console.log("handling safe-offer");
|
||||||
|
return wallet.saveOffer(offer);
|
||||||
|
},
|
||||||
["reserve-creation-info"]: function (detail, sender) {
|
["reserve-creation-info"]: function (detail, sender) {
|
||||||
if (!detail.baseUrl || typeof detail.baseUrl !== "string") {
|
if (!detail.baseUrl || typeof detail.baseUrl !== "string") {
|
||||||
return Promise.resolve({ error: "bad url" });
|
return Promise.resolve({ error: "bad url" });
|
||||||
@ -183,6 +191,9 @@ function makeHandlers(db: IDBDatabase,
|
|||||||
// TODO: limit history length
|
// TODO: limit history length
|
||||||
return wallet.getHistory();
|
return wallet.getHistory();
|
||||||
},
|
},
|
||||||
|
["get-offer"]: function (detail, sender) {
|
||||||
|
return wallet.getOffer(detail.offerId);
|
||||||
|
},
|
||||||
["get-exchanges"]: function (detail, sender) {
|
["get-exchanges"]: function (detail, sender) {
|
||||||
return wallet.getExchanges();
|
return wallet.getExchanges();
|
||||||
},
|
},
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
import {substituteFulfillmentUrl} from "../lib/wallet/helpers";
|
import {substituteFulfillmentUrl} from "../lib/wallet/helpers";
|
||||||
import {Contract, AmountJson, IExchangeInfo} from "../lib/wallet/types";
|
import {Contract, AmountJson, IExchangeInfo} from "../lib/wallet/types";
|
||||||
|
import {Offer} from "../lib/wallet/wallet";
|
||||||
import {renderContract, prettyAmount} from "../lib/wallet/renderHtml";
|
import {renderContract, prettyAmount} from "../lib/wallet/renderHtml";
|
||||||
"use strict";
|
"use strict";
|
||||||
import {getExchanges} from "../lib/wallet/wxApi";
|
import {getExchanges} from "../lib/wallet/wxApi";
|
||||||
@ -43,20 +44,17 @@ interface DetailProps {
|
|||||||
class Details extends React.Component<DetailProps, DetailState> {
|
class Details extends React.Component<DetailProps, DetailState> {
|
||||||
constructor(props: DetailProps) {
|
constructor(props: DetailProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.setState({
|
console.log("new Details component created");
|
||||||
|
this.state = {
|
||||||
collapsed: props.collapsed,
|
collapsed: props.collapsed,
|
||||||
exchanges: null
|
exchanges: null
|
||||||
});
|
};
|
||||||
|
|
||||||
console.log("initial state:", this.state);
|
console.log("initial state:", this.state);
|
||||||
|
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(props: DetailProps) {
|
|
||||||
this.setState({collapsed: props.collapsed} as any);
|
|
||||||
}
|
|
||||||
|
|
||||||
async update() {
|
async update() {
|
||||||
let exchanges = await getExchanges();
|
let exchanges = await getExchanges();
|
||||||
this.setState({exchanges} as any);
|
this.setState({exchanges} as any);
|
||||||
@ -100,10 +98,11 @@ class Details extends React.Component<DetailProps, DetailState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ContractPromptProps {
|
interface ContractPromptProps {
|
||||||
offer: any;
|
offerId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ContractPromptState {
|
interface ContractPromptState {
|
||||||
|
offer: any;
|
||||||
error: string|null;
|
error: string|null;
|
||||||
payDisabled: boolean;
|
payDisabled: boolean;
|
||||||
}
|
}
|
||||||
@ -112,12 +111,14 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
|
offer: undefined,
|
||||||
error: null,
|
error: null,
|
||||||
payDisabled: true,
|
payDisabled: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
|
this.update();
|
||||||
this.checkPayment();
|
this.checkPayment();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,11 +126,31 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
|
|||||||
// FIXME: abort running ops
|
// FIXME: abort running ops
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async update() {
|
||||||
|
let offer = await this.getOffer();
|
||||||
|
this.setState({offer} as any);
|
||||||
|
this.checkPayment();
|
||||||
|
}
|
||||||
|
|
||||||
|
getOffer(): Promise<Offer> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let msg = {
|
||||||
|
type: 'get-offer',
|
||||||
|
detail: {
|
||||||
|
offerId: this.props.offerId
|
||||||
|
}
|
||||||
|
};
|
||||||
|
chrome.runtime.sendMessage(msg, (resp) => {
|
||||||
|
resolve(resp);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
checkPayment() {
|
checkPayment() {
|
||||||
let msg = {
|
let msg = {
|
||||||
type: 'check-pay',
|
type: 'check-pay',
|
||||||
detail: {
|
detail: {
|
||||||
offer: this.props.offer
|
offer: this.state.offer
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
chrome.runtime.sendMessage(msg, (resp) => {
|
chrome.runtime.sendMessage(msg, (resp) => {
|
||||||
@ -149,12 +170,12 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
|
|||||||
this.state.error = null;
|
this.state.error = null;
|
||||||
}
|
}
|
||||||
this.setState({} as any);
|
this.setState({} as any);
|
||||||
window.setTimeout(() => this.checkPayment(), 300);
|
window.setTimeout(() => this.checkPayment(), 500);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
doPayment() {
|
doPayment() {
|
||||||
let d = {offer: this.props.offer};
|
let d = {offer: this.state.offer};
|
||||||
chrome.runtime.sendMessage({type: 'confirm-pay', detail: d}, (resp) => {
|
chrome.runtime.sendMessage({type: 'confirm-pay', detail: d}, (resp) => {
|
||||||
if (resp.error) {
|
if (resp.error) {
|
||||||
console.log("confirm-pay error", JSON.stringify(resp));
|
console.log("confirm-pay error", JSON.stringify(resp));
|
||||||
@ -173,22 +194,29 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
|
|||||||
let c = d.offer.contract;
|
let c = d.offer.contract;
|
||||||
console.log("contract", c);
|
console.log("contract", c);
|
||||||
document.location.href = substituteFulfillmentUrl(c.fulfillment_url,
|
document.location.href = substituteFulfillmentUrl(c.fulfillment_url,
|
||||||
this.props.offer);
|
this.state.offer);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let c = this.props.offer.contract;
|
if (!this.state.offer) {
|
||||||
|
return <span>...</span>;
|
||||||
|
}
|
||||||
|
let c = this.state.offer.contract;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{renderContract(c)}
|
<div>
|
||||||
|
{renderContract(c)}
|
||||||
|
</div>
|
||||||
<button onClick={() => this.doPayment()}
|
<button onClick={() => this.doPayment()}
|
||||||
disabled={this.state.payDisabled}
|
disabled={this.state.payDisabled}
|
||||||
className="accept">
|
className="accept">
|
||||||
Confirm payment
|
Confirm payment
|
||||||
</button>
|
</button>
|
||||||
{(this.state.error ? <p className="errorbox">{this.state.error}</p> : <p />)}
|
<div>
|
||||||
|
{(this.state.error ? <p className="errorbox">{this.state.error}</p> : <p />)}
|
||||||
|
</div>
|
||||||
<Details contract={c} collapsed={!this.state.error}/>
|
<Details contract={c} collapsed={!this.state.error}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -199,10 +227,8 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt
|
|||||||
export function main() {
|
export function main() {
|
||||||
let url = URI(document.location.href);
|
let url = URI(document.location.href);
|
||||||
let query: any = URI.parseQuery(url.query());
|
let query: any = URI.parseQuery(url.query());
|
||||||
let offer = JSON.parse(query.offer);
|
let offerId = JSON.parse(query.offerId);
|
||||||
console.dir(offer);
|
|
||||||
let contract = offer.contract;
|
|
||||||
|
|
||||||
ReactDOM.render(<ContractPrompt offer={offer}/>, document.getElementById(
|
ReactDOM.render(<ContractPrompt offerId={offerId}/>, document.getElementById(
|
||||||
"contract")!);
|
"contract")!);
|
||||||
}
|
}
|
||||||
|
@ -30,4 +30,7 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="container"></div>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -358,7 +358,7 @@ class ExchangeView extends React.Component<ExchangeProps, void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ExchangesListState {
|
interface ExchangesListState {
|
||||||
exchanges: IExchangeInfo[];
|
exchanges?: IExchangeInfo[];
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExchangesList extends React.Component<any, ExchangesListState> {
|
class ExchangesList extends React.Component<any, ExchangesListState> {
|
||||||
@ -371,8 +371,8 @@ class ExchangesList extends React.Component<any, ExchangesListState> {
|
|||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.update();
|
this.update();
|
||||||
|
this.state = {} as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
async update() {
|
async update() {
|
||||||
@ -382,18 +382,19 @@ class ExchangesList extends React.Component<any, ExchangesListState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render(): JSX.Element {
|
render(): JSX.Element {
|
||||||
if (!this.state.exchanges) {
|
let exchanges = this.state.exchanges;
|
||||||
|
if (!exchanges) {
|
||||||
return <span>...</span>;
|
return <span>...</span>;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="tree-item">
|
<div className="tree-item">
|
||||||
Exchanges ({this.state.exchanges.length.toString()}):
|
Exchanges ({exchanges.length.toString()}):
|
||||||
{this.state.exchanges.map(e => <ExchangeView exchange={e} />)}
|
{exchanges.map(e => <ExchangeView exchange={e} />)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
ReactDOM.render(<ExchangesList />, document.body);
|
ReactDOM.render(<ExchangesList />, document.getElementById("container")!);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user