suggest mint based on currency (stub)
This commit is contained in:
parent
c34a6612ec
commit
526e88695f
@ -44,6 +44,8 @@ var TalerNotify;
|
|||||||
var params = {
|
var params = {
|
||||||
amount: JSON.stringify(e.detail.amount),
|
amount: JSON.stringify(e.detail.amount),
|
||||||
callback_url: URI(e.detail.callback_url).absoluteTo(document.location.href),
|
callback_url: URI(e.detail.callback_url).absoluteTo(document.location.href),
|
||||||
|
bank_url: document.location.href,
|
||||||
|
suggested_mint: e.detail.suggested_mint,
|
||||||
};
|
};
|
||||||
var uri = URI(chrome.extension.getURL("pages/confirm-create-reserve.html"));
|
var uri = URI(chrome.extension.getURL("pages/confirm-create-reserve.html"));
|
||||||
document.location.href = uri.query(params).href();
|
document.location.href = uri.query(params).href();
|
||||||
|
@ -53,6 +53,8 @@ namespace TalerNotify {
|
|||||||
let params = {
|
let params = {
|
||||||
amount: JSON.stringify(e.detail.amount),
|
amount: JSON.stringify(e.detail.amount),
|
||||||
callback_url: URI(e.detail.callback_url).absoluteTo(document.location.href),
|
callback_url: URI(e.detail.callback_url).absoluteTo(document.location.href),
|
||||||
|
bank_url: document.location.href,
|
||||||
|
suggested_mint: e.detail.suggested_mint,
|
||||||
};
|
};
|
||||||
let uri = URI(chrome.extension.getURL("pages/confirm-create-reserve.html"));
|
let uri = URI(chrome.extension.getURL("pages/confirm-create-reserve.html"));
|
||||||
document.location.href = uri.query(params).href();
|
document.location.href = uri.query(params).href();
|
||||||
|
111
extension/lib/decl/mithril.d.ts
vendored
111
extension/lib/decl/mithril.d.ts
vendored
@ -3,7 +3,8 @@
|
|||||||
/**
|
/**
|
||||||
* This is the module containing all the types/declarations/etc. for Mithril
|
* This is the module containing all the types/declarations/etc. for Mithril
|
||||||
*/
|
*/
|
||||||
declare interface MithrilStatic {
|
declare module _mithril {
|
||||||
|
interface MithrilStatic {
|
||||||
/**
|
/**
|
||||||
* Creates a virtual element for use with m.render, m.mount, etc.
|
* Creates a virtual element for use with m.render, m.mount, etc.
|
||||||
*
|
*
|
||||||
@ -19,11 +20,13 @@ declare interface MithrilStatic {
|
|||||||
* @see m.mount
|
* @see m.mount
|
||||||
* @see m.component
|
* @see m.component
|
||||||
*/
|
*/
|
||||||
<T extends MithrilController>(selector: string,
|
<T extends MithrilController>(
|
||||||
|
selector: string,
|
||||||
attributes: MithrilAttributes,
|
attributes: MithrilAttributes,
|
||||||
...children: Array<string |
|
...children: Array<string |
|
||||||
MithrilVirtualElement<T> |
|
MithrilVirtualElement<T> |
|
||||||
MithrilComponent<T>>): MithrilVirtualElement<T>;
|
MithrilComponent<T>>
|
||||||
|
): MithrilVirtualElement<T>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a component for use with m.render, m.mount, etc.
|
* Initializes a component for use with m.render, m.mount, etc.
|
||||||
@ -36,8 +39,10 @@ declare interface MithrilStatic {
|
|||||||
* @see m.mount
|
* @see m.mount
|
||||||
* @see m
|
* @see m
|
||||||
*/
|
*/
|
||||||
<T extends MithrilController>(component: MithrilComponent<T>,
|
<T extends MithrilController>(
|
||||||
...args: any[]): MithrilComponent<T>;
|
component: MithrilComponent<T>,
|
||||||
|
...args: any[]
|
||||||
|
): MithrilComponent<T>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a virtual element for use with m.render, m.mount, etc.
|
* Creates a virtual element for use with m.render, m.mount, etc.
|
||||||
@ -51,10 +56,12 @@ declare interface MithrilStatic {
|
|||||||
* @see m.mount
|
* @see m.mount
|
||||||
* @see m.component
|
* @see m.component
|
||||||
*/
|
*/
|
||||||
<T extends MithrilController>(selector: string,
|
<T extends MithrilController>(
|
||||||
|
selector: string,
|
||||||
...children: Array<string |
|
...children: Array<string |
|
||||||
MithrilVirtualElement<T> |
|
MithrilVirtualElement<T> |
|
||||||
MithrilComponent<T>>): MithrilVirtualElement<T>;
|
MithrilComponent<T>>
|
||||||
|
): MithrilVirtualElement<T>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a component for use with m.render, m.mount, etc.
|
* Initializes a component for use with m.render, m.mount, etc.
|
||||||
@ -68,8 +75,10 @@ declare interface MithrilStatic {
|
|||||||
* @see m.mount
|
* @see m.mount
|
||||||
* @see m.component
|
* @see m.component
|
||||||
*/
|
*/
|
||||||
<T extends MithrilController>(component: MithrilComponent<T>,
|
<T extends MithrilController>(
|
||||||
...args: any[]): MithrilComponent<T>;
|
component: MithrilComponent<T>,
|
||||||
|
...args: any[]
|
||||||
|
): MithrilComponent<T>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a getter-setter function that wraps a Mithril promise. Useful
|
* Creates a getter-setter function that wraps a Mithril promise. Useful
|
||||||
@ -112,15 +121,32 @@ declare interface MithrilStatic {
|
|||||||
* @param callback The handler to use the value from the event.
|
* @param callback The handler to use the value from the event.
|
||||||
* @return A function suitable for listening to an event.
|
* @return A function suitable for listening to an event.
|
||||||
*/
|
*/
|
||||||
withAttr(property: string,
|
withAttr(
|
||||||
|
property: string,
|
||||||
callback: (value: any) => void,
|
callback: (value: any) => void,
|
||||||
callbackThis: any): (e: Event) => any;
|
callbackThis: any
|
||||||
|
): (e: Event) => any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a event handler that can be bound to an element, firing with
|
||||||
|
* the specified property.
|
||||||
|
*
|
||||||
|
* @param attributeName Name of the element's attribute to bind to.
|
||||||
|
* @param property The property to bind.
|
||||||
|
* @return A function suitable for listening to an event.
|
||||||
|
*/
|
||||||
|
withAttr<T>(
|
||||||
|
attributeName: string,
|
||||||
|
property: MithrilBasicProperty<T>
|
||||||
|
) : (e: Event) => any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use m.mount instead
|
* @deprecated Use m.mount instead
|
||||||
*/
|
*/
|
||||||
module<T extends MithrilController>(rootElement: Node,
|
module<T extends MithrilController>(
|
||||||
component: MithrilComponent<T>): T;
|
rootElement: Node,
|
||||||
|
component: MithrilComponent<T>
|
||||||
|
): T;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mounts a component to a base DOM node.
|
* Mounts a component to a base DOM node.
|
||||||
@ -129,8 +155,10 @@ declare interface MithrilStatic {
|
|||||||
* @param component The component to mount.
|
* @param component The component to mount.
|
||||||
* @return An instance of the top-level component's controller
|
* @return An instance of the top-level component's controller
|
||||||
*/
|
*/
|
||||||
mount<T extends MithrilController>(rootElement: Node,
|
mount<T extends MithrilController>(
|
||||||
component: MithrilComponent<T>): T;
|
rootElement: Node,
|
||||||
|
component: MithrilComponent<T>
|
||||||
|
): T;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a component for use with m.render, m.mount, etc.
|
* Initializes a component for use with m.render, m.mount, etc.
|
||||||
@ -143,8 +171,10 @@ declare interface MithrilStatic {
|
|||||||
* @see m.mount
|
* @see m.mount
|
||||||
* @see m
|
* @see m
|
||||||
*/
|
*/
|
||||||
component<T extends MithrilController>(component: MithrilComponent<T>,
|
component<T extends MithrilController>(
|
||||||
...args: any[]): MithrilComponent<T>;
|
component: MithrilComponent<T>,
|
||||||
|
...args: any[]
|
||||||
|
): MithrilComponent<T>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trust this string of HTML.
|
* Trust this string of HTML.
|
||||||
@ -163,9 +193,11 @@ declare interface MithrilStatic {
|
|||||||
* @param forceRecreation If true, overwrite the entire tree without
|
* @param forceRecreation If true, overwrite the entire tree without
|
||||||
* diffing against it.
|
* diffing against it.
|
||||||
*/
|
*/
|
||||||
render<T extends MithrilController>(rootElement: Element,
|
render<T extends MithrilController>(
|
||||||
|
rootElement: Element,
|
||||||
children: MithrilVirtualElement<T>|MithrilVirtualElement<T>[],
|
children: MithrilVirtualElement<T>|MithrilVirtualElement<T>[],
|
||||||
forceRecreation?: boolean): void;
|
forceRecreation?: boolean
|
||||||
|
): void;
|
||||||
|
|
||||||
redraw: {
|
redraw: {
|
||||||
/**
|
/**
|
||||||
@ -228,9 +260,11 @@ declare interface MithrilStatic {
|
|||||||
* @param defaultRoute The route to start with.
|
* @param defaultRoute The route to start with.
|
||||||
* @param routes A key-value mapping of pathname to controller.
|
* @param routes A key-value mapping of pathname to controller.
|
||||||
*/
|
*/
|
||||||
<T extends MithrilController>(rootElement: Element,
|
<T extends MithrilController>(
|
||||||
|
rootElement: Element,
|
||||||
defaultRoute: string,
|
defaultRoute: string,
|
||||||
routes: MithrilRoutes): void;
|
routes: MithrilRoutes
|
||||||
|
): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This allows m.route to be used as the `config` attribute for a
|
* This allows m.route to be used as the `config` attribute for a
|
||||||
@ -242,10 +276,12 @@ declare interface MithrilStatic {
|
|||||||
* m("a[href='/dashboard/alicesmith']", {config: m.route});
|
* m("a[href='/dashboard/alicesmith']", {config: m.route});
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
<T extends MithrilController>(element: Element,
|
<T extends MithrilController>(
|
||||||
|
element: Element,
|
||||||
isInitialized: boolean,
|
isInitialized: boolean,
|
||||||
context?: MithrilContext,
|
context?: MithrilContext,
|
||||||
vdom?: MithrilVirtualElement<T>): void;
|
vdom?: MithrilVirtualElement<T>
|
||||||
|
): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Programmatically redirect to another route.
|
* Programmatically redirect to another route.
|
||||||
@ -479,10 +515,12 @@ interface MithrilElementConfig {
|
|||||||
* @param context The associated context for this element.
|
* @param context The associated context for this element.
|
||||||
* @param vdom The associated virtual element.
|
* @param vdom The associated virtual element.
|
||||||
*/
|
*/
|
||||||
<T extends MithrilController>(element: Element,
|
<T extends MithrilController>(
|
||||||
|
element: Element,
|
||||||
isInitialized: boolean,
|
isInitialized: boolean,
|
||||||
context: MithrilContext,
|
context: MithrilContext,
|
||||||
vdom: MithrilVirtualElement<T>): void;
|
vdom: MithrilVirtualElement<T>
|
||||||
|
): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -536,7 +574,7 @@ interface MithrilController {
|
|||||||
* @see MithrilControllerConstructor
|
* @see MithrilControllerConstructor
|
||||||
*/
|
*/
|
||||||
interface MithrilControllerFunction<T extends MithrilController> {
|
interface MithrilControllerFunction<T extends MithrilController> {
|
||||||
(): T;
|
(opts?: any): T;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -570,7 +608,7 @@ interface MithrilComponent<T extends MithrilController> {
|
|||||||
*
|
*
|
||||||
* @see m.component
|
* @see m.component
|
||||||
*/
|
*/
|
||||||
controller?: MithrilControllerFunction<T> |
|
controller: MithrilControllerFunction<T> |
|
||||||
MithrilControllerConstructor<T>;
|
MithrilControllerConstructor<T>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -578,7 +616,7 @@ interface MithrilComponent<T extends MithrilController> {
|
|||||||
*
|
*
|
||||||
* @see m.component
|
* @see m.component
|
||||||
*/
|
*/
|
||||||
view(ctrl: T): MithrilVirtualElement<T>;
|
view(ctrl?: T, opts?: any): MithrilVirtualElement<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -702,8 +740,7 @@ interface MithrilErrorCallback<T> {
|
|||||||
*/
|
*/
|
||||||
interface Thennable<T> {
|
interface Thennable<T> {
|
||||||
then<U>(success: (value: T) => U): Thennable<U>;
|
then<U>(success: (value: T) => U): Thennable<U>;
|
||||||
then<U,V>(success: (value: T) => U,
|
then<U,V>(success: (value: T) => U, error: (value: Error) => V): Thennable<U>|Thennable<V>;
|
||||||
error: (value: Error) => V): Thennable<U>|Thennable<V>;
|
|
||||||
catch?: <U>(error: (value: Error) => U) => Thennable<U>;
|
catch?: <U>(error: (value: Error) => U) => Thennable<U>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -728,8 +765,10 @@ interface MithrilPromise<T> extends Thennable<T>, MithrilProperty<MithrilPromise
|
|||||||
* @param error The callback to call when the promise is rejected.
|
* @param error The callback to call when the promise is rejected.
|
||||||
* @return The chained promise.
|
* @return The chained promise.
|
||||||
*/
|
*/
|
||||||
then<U, V>(success: MithrilSuccessCallback<T, U>,
|
then<U, V>(
|
||||||
error: MithrilErrorCallback<V>): MithrilPromise<U> | MithrilPromise<V>;
|
success: MithrilSuccessCallback<T, U>,
|
||||||
|
error: MithrilErrorCallback<V>
|
||||||
|
): MithrilPromise<U> | MithrilPromise<V>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chain this promise with a single error callback, without propogating
|
* Chain this promise with a single error callback, without propogating
|
||||||
@ -877,3 +916,11 @@ interface MithrilXHROptions<T> {
|
|||||||
*/
|
*/
|
||||||
callbackKey?: string;
|
callbackKey?: string;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare var Mithril: _mithril.MithrilStatic;
|
||||||
|
declare var m: _mithril.MithrilStatic;
|
||||||
|
|
||||||
|
declare module "mithril" {
|
||||||
|
export = m;
|
||||||
|
}
|
||||||
|
@ -30,6 +30,16 @@ System.config({
|
|||||||
defaultJSExtensions: true,
|
defaultJSExtensions: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Register mithril as a module,
|
||||||
|
// but only if it is ambient.
|
||||||
|
if (m) {
|
||||||
|
let mod = System.newModule({default: m});
|
||||||
|
let modName = "mithril";
|
||||||
|
System.set(modName, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let me = window.location.protocol
|
let me = window.location.protocol
|
||||||
+ "//" + window.location.host
|
+ "//" + window.location.host
|
||||||
+ window.location.pathname.replace(/[.]html$/, ".js");
|
+ window.location.pathname.replace(/[.]html$/, ".js");
|
||||||
|
2496
extension/lib/vendor/mithril.js
vendored
2496
extension/lib/vendor/mithril.js
vendored
File diff suppressed because it is too large
Load Diff
@ -144,6 +144,7 @@ System.register(["./wallet", "./db", "./http"], function(exports_1, context_1) {
|
|||||||
return handlers[req.type](db, req.detail, onresponse);
|
return handlers[req.type](db, req.detail, onresponse);
|
||||||
}
|
}
|
||||||
console.error("Request type " + JSON.stringify(req) + " unknown, req " + req.type);
|
console.error("Request type " + JSON.stringify(req) + " unknown, req " + req.type);
|
||||||
|
onresponse({ error: "request unknown" });
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -29,6 +29,7 @@ import {BrowserHttpLib} from "./http";
|
|||||||
* @author Florian Dold
|
* @author Florian Dold
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
function makeHandlers(wallet: Wallet) {
|
function makeHandlers(wallet: Wallet) {
|
||||||
return {
|
return {
|
||||||
["balances"]: function(db, detail, sendResponse) {
|
["balances"]: function(db, detail, sendResponse) {
|
||||||
@ -162,6 +163,7 @@ export function wxMain() {
|
|||||||
return handlers[req.type](db, req.detail, onresponse);
|
return handlers[req.type](db, req.detail, onresponse);
|
||||||
}
|
}
|
||||||
console.error(`Request type ${JSON.stringify(req)} unknown, req ${req.type}`);
|
console.error(`Request type ${JSON.stringify(req)} unknown, req ${req.type}`);
|
||||||
|
onresponse({error: "request unknown"});
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<section id="main">
|
<section id="main">
|
||||||
|
|
||||||
<article>
|
<article>
|
||||||
<div id="mint-selection"></div>
|
<div class="fade" id="mint-selection"></div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
@ -13,46 +13,71 @@
|
|||||||
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, If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
System.register(["../lib/wallet/helpers", "../lib/wallet/types"], function(exports_1, context_1) {
|
System.register(["../lib/wallet/helpers", "../lib/wallet/types", "mithril"], function(exports_1, context_1) {
|
||||||
"use strict";
|
"use strict";
|
||||||
var __moduleName = context_1 && context_1.id;
|
var __moduleName = context_1 && context_1.id;
|
||||||
var helpers_1, types_1;
|
var helpers_1, types_1, mithril_1;
|
||||||
var DelayTimer, Controller;
|
var DelayTimer, Controller;
|
||||||
|
function view(ctrl) {
|
||||||
|
var controls = [];
|
||||||
|
var mx = function (x) {
|
||||||
|
var args = [];
|
||||||
|
for (var _i = 1; _i < arguments.length; _i++) {
|
||||||
|
args[_i - 1] = arguments[_i];
|
||||||
|
}
|
||||||
|
return controls.push(mithril_1.default.apply(void 0, [x].concat(args)));
|
||||||
|
};
|
||||||
|
mx("p", (_a = ["The bank wants to create a reserve over ", "."], _a.raw = ["The bank wants to create a reserve over ", "."], i18n(_a, helpers_1.amountToPretty(ctrl.amount))));
|
||||||
|
mx("input", {
|
||||||
|
className: "url",
|
||||||
|
type: "text",
|
||||||
|
spellcheck: false,
|
||||||
|
value: ctrl.url(),
|
||||||
|
oninput: mithril_1.default.withAttr("value", ctrl.onUrlChanged.bind(ctrl)),
|
||||||
|
});
|
||||||
|
mx("button", {
|
||||||
|
onclick: function () { return ctrl.confirmReserve(ctrl.url(), ctrl.amount, ctrl.callbackUrl); },
|
||||||
|
disabled: !ctrl.isValidMint
|
||||||
|
}, "Confirm mint selection");
|
||||||
|
if (ctrl.statusString) {
|
||||||
|
mx("p", ctrl.statusString);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mx("p", "Checking URL, please wait ...");
|
||||||
|
}
|
||||||
|
return mithril_1.default("div", controls);
|
||||||
|
var _a;
|
||||||
|
}
|
||||||
|
function getSuggestedMint(currency) {
|
||||||
|
// TODO: make this request go to the wallet backend
|
||||||
|
// Right now, this is a stub.
|
||||||
|
var defaultMint = {
|
||||||
|
"KUDOS": "http://mint.test.taler.net"
|
||||||
|
};
|
||||||
|
var mint = defaultMint[currency];
|
||||||
|
if (!mint) {
|
||||||
|
mint = "";
|
||||||
|
}
|
||||||
|
return Promise.resolve(mint);
|
||||||
|
}
|
||||||
function main() {
|
function main() {
|
||||||
var url = URI(document.location.href);
|
var url = URI(document.location.href);
|
||||||
var query = URI.parseQuery(url.query());
|
var query = URI.parseQuery(url.query());
|
||||||
var amount = types_1.AmountJson.checked(JSON.parse(query.amount));
|
var amount = types_1.AmountJson.checked(JSON.parse(query.amount));
|
||||||
var callback_url = query.callback_url;
|
var callback_url = query.callback_url;
|
||||||
var MintSelection = {
|
var bank_url = query.bank_url;
|
||||||
controller: function () { return new Controller(); },
|
getSuggestedMint(amount.currency)
|
||||||
view: function (ctrl) {
|
.then(function (suggestedMintUrl) {
|
||||||
var controls = [];
|
var controller = function () { return new Controller(suggestedMintUrl, amount, callback_url); };
|
||||||
var mx = function () {
|
var MintSelection = { controller: controller, view: view };
|
||||||
var args = [];
|
mithril_1.default.mount(document.getElementById("mint-selection"), MintSelection);
|
||||||
for (var _i = 0; _i < arguments.length; _i++) {
|
})
|
||||||
args[_i - 0] = arguments[_i];
|
.catch(function (e) {
|
||||||
}
|
// TODO: provide more context information, maybe factor it out into a
|
||||||
return controls.push(m.apply(void 0, args));
|
// TODO:generic error reporting function or component.
|
||||||
};
|
document.body.innerText = "Fatal error: \"" + e.message + "\".";
|
||||||
mx("p", (_a = ["The bank wants to create a reserve over ", "."], _a.raw = ["The bank wants to create a reserve over ", "."], i18n(_a, helpers_1.amountToPretty(amount))));
|
console.error("got backend error \"" + e.message + "\"");
|
||||||
mx("input.url", {
|
|
||||||
type: "text",
|
|
||||||
spellcheck: false,
|
|
||||||
oninput: m.withAttr("value", ctrl.onUrlChanged.bind(ctrl)),
|
|
||||||
});
|
});
|
||||||
if (ctrl.isValidMint) {
|
|
||||||
mx("button", {
|
|
||||||
onclick: function () { return ctrl.confirmReserve(ctrl.url, amount, callback_url); }
|
|
||||||
}, "Confirm mint selection");
|
|
||||||
}
|
|
||||||
if (ctrl.errorString) {
|
|
||||||
mx("p", ctrl.errorString);
|
|
||||||
}
|
|
||||||
return m("div", controls);
|
|
||||||
var _a;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
m.mount(document.getElementById("mint-selection"), MintSelection);
|
|
||||||
}
|
}
|
||||||
exports_1("main", main);
|
exports_1("main", main);
|
||||||
return {
|
return {
|
||||||
@ -62,6 +87,9 @@ System.register(["../lib/wallet/helpers", "../lib/wallet/types"], function(expor
|
|||||||
},
|
},
|
||||||
function (types_1_1) {
|
function (types_1_1) {
|
||||||
types_1 = types_1_1;
|
types_1 = types_1_1;
|
||||||
|
},
|
||||||
|
function (mithril_1_1) {
|
||||||
|
mithril_1 = mithril_1_1;
|
||||||
}],
|
}],
|
||||||
execute: function() {
|
execute: function() {
|
||||||
"use strict";
|
"use strict";
|
||||||
@ -77,39 +105,48 @@ System.register(["../lib/wallet/helpers", "../lib/wallet/types"], function(expor
|
|||||||
}
|
}
|
||||||
DelayTimer.prototype.bump = function () {
|
DelayTimer.prototype.bump = function () {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
if (this.timerId !== null) {
|
this.stop();
|
||||||
window.clearTimeout(this.timerId);
|
|
||||||
}
|
|
||||||
var handler = function () {
|
var handler = function () {
|
||||||
_this.f();
|
_this.f();
|
||||||
};
|
};
|
||||||
this.timerId = window.setTimeout(handler, this.ms);
|
this.timerId = window.setTimeout(handler, this.ms);
|
||||||
};
|
};
|
||||||
|
DelayTimer.prototype.stop = function () {
|
||||||
|
if (this.timerId !== null) {
|
||||||
|
window.clearTimeout(this.timerId);
|
||||||
|
}
|
||||||
|
};
|
||||||
return DelayTimer;
|
return DelayTimer;
|
||||||
}());
|
}());
|
||||||
Controller = (function () {
|
Controller = (function () {
|
||||||
function Controller() {
|
function Controller(initialMintUrl, amount, callbackUrl) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
this.url = null;
|
this.url = mithril_1.default.prop();
|
||||||
this.errorString = null;
|
this.statusString = null;
|
||||||
this.isValidMint = false;
|
this.isValidMint = false;
|
||||||
this.update();
|
this.amount = amount;
|
||||||
|
this.callbackUrl = callbackUrl;
|
||||||
this.timer = new DelayTimer(800, function () { return _this.update(); });
|
this.timer = new DelayTimer(800, function () { return _this.update(); });
|
||||||
|
this.url(initialMintUrl);
|
||||||
|
this.update();
|
||||||
}
|
}
|
||||||
Controller.prototype.update = function () {
|
Controller.prototype.update = function () {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
|
this.timer.stop();
|
||||||
var doUpdate = function () {
|
var doUpdate = function () {
|
||||||
if (!_this.url) {
|
if (!_this.url()) {
|
||||||
_this.errorString = (_a = ["Please enter a URL"], _a.raw = ["Please enter a URL"], i18n(_a));
|
_this.statusString = (_a = ["Please enter a URL"], _a.raw = ["Please enter a URL"], i18n(_a));
|
||||||
|
mithril_1.default.endComputation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_this.errorString = null;
|
_this.statusString = null;
|
||||||
var parsedUrl = URI(_this.url);
|
var parsedUrl = URI(_this.url());
|
||||||
if (parsedUrl.is("relative")) {
|
if (parsedUrl.is("relative")) {
|
||||||
_this.errorString = (_b = ["The URL you've entered is not valid (must be absolute)"], _b.raw = ["The URL you've entered is not valid (must be absolute)"], i18n(_b));
|
_this.statusString = (_b = ["The URL you've entered is not valid (must be absolute)"], _b.raw = ["The URL you've entered is not valid (must be absolute)"], i18n(_b));
|
||||||
|
mithril_1.default.endComputation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var keysUrl = URI("/keys").absoluteTo(helpers_1.canonicalizeBaseUrl(_this.url));
|
var keysUrl = URI("/keys").absoluteTo(helpers_1.canonicalizeBaseUrl(_this.url()));
|
||||||
console.log("requesting keys from '" + keysUrl + "'");
|
console.log("requesting keys from '" + keysUrl + "'");
|
||||||
_this.request = new XMLHttpRequest();
|
_this.request = new XMLHttpRequest();
|
||||||
_this.request.onreadystatechange = function () {
|
_this.request.onreadystatechange = function () {
|
||||||
@ -117,33 +154,33 @@ System.register(["../lib/wallet/helpers", "../lib/wallet/types"], function(expor
|
|||||||
switch (_this.request.status) {
|
switch (_this.request.status) {
|
||||||
case 200:
|
case 200:
|
||||||
_this.isValidMint = true;
|
_this.isValidMint = true;
|
||||||
|
_this.statusString = "The mint base URL is valid!";
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
_this.errorString = "unknown request error";
|
_this.statusString = "unknown request error";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
_this.errorString = "request failed with status " + _this.request.status;
|
_this.statusString = "request failed with status " + _this.request.status;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
m.redraw();
|
|
||||||
}
|
}
|
||||||
|
mithril_1.default.endComputation();
|
||||||
};
|
};
|
||||||
_this.request.open("get", keysUrl.href());
|
_this.request.open("get", keysUrl.href());
|
||||||
_this.request.send();
|
_this.request.send();
|
||||||
var _a, _b;
|
var _a, _b;
|
||||||
};
|
};
|
||||||
|
mithril_1.default.startComputation();
|
||||||
doUpdate();
|
doUpdate();
|
||||||
m.redraw();
|
|
||||||
console.log("got update");
|
console.log("got update");
|
||||||
};
|
};
|
||||||
Controller.prototype.reset = function () {
|
Controller.prototype.reset = function () {
|
||||||
this.isValidMint = false;
|
this.isValidMint = false;
|
||||||
this.errorString = null;
|
this.statusString = null;
|
||||||
if (this.request) {
|
if (this.request) {
|
||||||
this.request.abort();
|
this.request.abort();
|
||||||
this.request = null;
|
this.request = null;
|
||||||
}
|
}
|
||||||
m.redraw();
|
|
||||||
};
|
};
|
||||||
Controller.prototype.confirmReserve = function (mint, amount, callback_url) {
|
Controller.prototype.confirmReserve = function (mint, amount, callback_url) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
@ -170,7 +207,7 @@ System.register(["../lib/wallet/helpers", "../lib/wallet/types"], function(expor
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_this.reset();
|
_this.reset();
|
||||||
_this.errorString = ("Oops, something went wrong." +
|
_this.statusString = ("Oops, something went wrong." +
|
||||||
("The wallet responded with error status (" + rawResp.error + ")."));
|
("The wallet responded with error status (" + rawResp.error + ")."));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -178,7 +215,7 @@ System.register(["../lib/wallet/helpers", "../lib/wallet/types"], function(expor
|
|||||||
};
|
};
|
||||||
Controller.prototype.onUrlChanged = function (url) {
|
Controller.prototype.onUrlChanged = function (url) {
|
||||||
this.reset();
|
this.reset();
|
||||||
this.url = url;
|
this.url(url);
|
||||||
this.timer.bump();
|
this.timer.bump();
|
||||||
};
|
};
|
||||||
return Controller;
|
return Controller;
|
||||||
|
@ -14,14 +14,14 @@
|
|||||||
TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// <reference path="../lib/decl/mithril.d.ts" />
|
||||||
|
|
||||||
import {amountToPretty, canonicalizeBaseUrl} from "../lib/wallet/helpers";
|
import {amountToPretty, canonicalizeBaseUrl} from "../lib/wallet/helpers";
|
||||||
import {AmountJson, CreateReserveResponse} from "../lib/wallet/types";
|
import {AmountJson, CreateReserveResponse} from "../lib/wallet/types";
|
||||||
|
import m from "mithril";
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
declare var m: any;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute something after a delay, with the possibility
|
* Execute something after a delay, with the possibility
|
||||||
* to reset the delay.
|
* to reset the delay.
|
||||||
@ -37,43 +37,55 @@ class DelayTimer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bump() {
|
bump() {
|
||||||
if (this.timerId !== null) {
|
this.stop();
|
||||||
window.clearTimeout(this.timerId);
|
|
||||||
}
|
|
||||||
const handler = () => {
|
const handler = () => {
|
||||||
this.f();
|
this.f();
|
||||||
};
|
};
|
||||||
this.timerId = window.setTimeout(handler, this.ms);
|
this.timerId = window.setTimeout(handler, this.ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
if (this.timerId !== null) {
|
||||||
|
window.clearTimeout(this.timerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
url = null;
|
url = m.prop<string>();
|
||||||
errorString = null;
|
statusString = null;
|
||||||
isValidMint = false;
|
isValidMint = false;
|
||||||
private timer: DelayTimer;
|
private timer: DelayTimer;
|
||||||
private request: XMLHttpRequest;
|
private request: XMLHttpRequest;
|
||||||
|
amount: AmountJson;
|
||||||
|
callbackUrl: string;
|
||||||
|
|
||||||
constructor() {
|
constructor(initialMintUrl: string, amount: AmountJson, callbackUrl: string) {
|
||||||
this.update();
|
this.amount = amount;
|
||||||
|
this.callbackUrl = callbackUrl;
|
||||||
this.timer = new DelayTimer(800, () => this.update());
|
this.timer = new DelayTimer(800, () => this.update());
|
||||||
|
this.url(initialMintUrl);
|
||||||
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
private update() {
|
||||||
|
this.timer.stop();
|
||||||
const doUpdate = () => {
|
const doUpdate = () => {
|
||||||
if (!this.url) {
|
if (!this.url()) {
|
||||||
this.errorString = i18n`Please enter a URL`;
|
this.statusString = i18n`Please enter a URL`;
|
||||||
|
m.endComputation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.errorString = null;
|
this.statusString = null;
|
||||||
let parsedUrl = URI(this.url);
|
let parsedUrl = URI(this.url());
|
||||||
if (parsedUrl.is("relative")) {
|
if (parsedUrl.is("relative")) {
|
||||||
this.errorString = i18n`The URL you've entered is not valid (must be absolute)`;
|
this.statusString = i18n`The URL you've entered is not valid (must be absolute)`;
|
||||||
|
m.endComputation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const keysUrl = URI("/keys").absoluteTo(canonicalizeBaseUrl(this.url));
|
const keysUrl = URI("/keys").absoluteTo(canonicalizeBaseUrl(this.url()));
|
||||||
|
|
||||||
console.log(`requesting keys from '${keysUrl}'`);
|
console.log(`requesting keys from '${keysUrl}'`);
|
||||||
|
|
||||||
@ -83,34 +95,36 @@ class Controller {
|
|||||||
switch (this.request.status) {
|
switch (this.request.status) {
|
||||||
case 200:
|
case 200:
|
||||||
this.isValidMint = true;
|
this.isValidMint = true;
|
||||||
|
this.statusString = "The mint base URL is valid!";
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
this.errorString = `unknown request error`;
|
this.statusString = `unknown request error`;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.errorString = `request failed with status ${this.request.status}`;
|
this.statusString = `request failed with status ${this.request.status}`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
m.redraw();
|
|
||||||
}
|
}
|
||||||
|
m.endComputation();
|
||||||
};
|
};
|
||||||
this.request.open("get", keysUrl.href());
|
this.request.open("get", keysUrl.href());
|
||||||
this.request.send();
|
this.request.send();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
m.startComputation();
|
||||||
doUpdate();
|
doUpdate();
|
||||||
m.redraw();
|
|
||||||
|
|
||||||
console.log("got update");
|
console.log("got update");
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
this.isValidMint = false;
|
this.isValidMint = false;
|
||||||
this.errorString = null;
|
this.statusString = null;
|
||||||
if (this.request) {
|
if (this.request) {
|
||||||
this.request.abort();
|
this.request.abort();
|
||||||
this.request = null;
|
this.request = null;
|
||||||
}
|
}
|
||||||
m.redraw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmReserve(mint: string, amount: AmountJson, callback_url: string) {
|
confirmReserve(mint: string, amount: AmountJson, callback_url: string) {
|
||||||
@ -136,7 +150,7 @@ class Controller {
|
|||||||
document.location.href = url.href();
|
document.location.href = url.href();
|
||||||
} else {
|
} else {
|
||||||
this.reset();
|
this.reset();
|
||||||
this.errorString = (
|
this.statusString = (
|
||||||
`Oops, something went wrong.` +
|
`Oops, something went wrong.` +
|
||||||
`The wallet responded with error status (${rawResp.error}).`);
|
`The wallet responded with error status (${rawResp.error}).`);
|
||||||
}
|
}
|
||||||
@ -146,50 +160,80 @@ class Controller {
|
|||||||
|
|
||||||
onUrlChanged(url: string) {
|
onUrlChanged(url: string) {
|
||||||
this.reset();
|
this.reset();
|
||||||
this.url = url;
|
this.url(url);
|
||||||
this.timer.bump();
|
this.timer.bump();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function view(ctrl: Controller) {
|
||||||
|
let controls = [];
|
||||||
|
let mx = (x: string, ...args) => controls.push(m(x, ...args));
|
||||||
|
|
||||||
|
mx("p",
|
||||||
|
i18n`The bank wants to create a reserve over ${amountToPretty(
|
||||||
|
ctrl.amount)}.`);
|
||||||
|
mx("input",
|
||||||
|
{
|
||||||
|
className: "url",
|
||||||
|
type: "text",
|
||||||
|
spellcheck: false,
|
||||||
|
value: ctrl.url(),
|
||||||
|
oninput: m.withAttr("value", ctrl.onUrlChanged.bind(ctrl)),
|
||||||
|
});
|
||||||
|
|
||||||
|
mx("button", {
|
||||||
|
onclick: () => ctrl.confirmReserve(ctrl.url(),
|
||||||
|
ctrl.amount,
|
||||||
|
ctrl.callbackUrl),
|
||||||
|
disabled: !ctrl.isValidMint
|
||||||
|
},
|
||||||
|
"Confirm mint selection");
|
||||||
|
|
||||||
|
if (ctrl.statusString) {
|
||||||
|
mx("p", ctrl.statusString);
|
||||||
|
} else {
|
||||||
|
mx("p", "Checking URL, please wait ...");
|
||||||
|
}
|
||||||
|
|
||||||
|
return m("div", controls);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getSuggestedMint(currency: string): Promise<string> {
|
||||||
|
// TODO: make this request go to the wallet backend
|
||||||
|
// Right now, this is a stub.
|
||||||
|
const defaultMint = {
|
||||||
|
"KUDOS": "http://mint.test.taler.net"
|
||||||
|
};
|
||||||
|
|
||||||
|
let mint = defaultMint[currency];
|
||||||
|
|
||||||
|
if (!mint) {
|
||||||
|
mint = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(mint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
const url = URI(document.location.href);
|
const url = URI(document.location.href);
|
||||||
const query: any = URI.parseQuery(url.query());
|
const query: any = URI.parseQuery(url.query());
|
||||||
const amount = AmountJson.checked(JSON.parse(query.amount));
|
const amount = AmountJson.checked(JSON.parse(query.amount));
|
||||||
const callback_url = query.callback_url;
|
const callback_url = query.callback_url;
|
||||||
|
const bank_url = query.bank_url;
|
||||||
|
|
||||||
var MintSelection = {
|
getSuggestedMint(amount.currency)
|
||||||
controller: () => new Controller(),
|
.then((suggestedMintUrl) => {
|
||||||
view(ctrl: Controller) {
|
const controller = () => new Controller(suggestedMintUrl, amount, callback_url);
|
||||||
let controls = [];
|
var MintSelection = {controller, view};
|
||||||
let mx = (...args) => controls.push(m(...args));
|
|
||||||
|
|
||||||
mx("p",
|
|
||||||
i18n`The bank wants to create a reserve over ${amountToPretty(
|
|
||||||
amount)}.`);
|
|
||||||
mx("input.url",
|
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
spellcheck: false,
|
|
||||||
oninput: m.withAttr("value", ctrl.onUrlChanged.bind(ctrl)),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (ctrl.isValidMint) {
|
|
||||||
mx("button", {
|
|
||||||
onclick: () => ctrl.confirmReserve(ctrl.url,
|
|
||||||
amount,
|
|
||||||
callback_url)
|
|
||||||
},
|
|
||||||
"Confirm mint selection");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctrl.errorString) {
|
|
||||||
mx("p", ctrl.errorString);
|
|
||||||
}
|
|
||||||
|
|
||||||
return m("div", controls);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
m.mount(document.getElementById("mint-selection"), MintSelection);
|
m.mount(document.getElementById("mint-selection"), MintSelection);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
// TODO: provide more context information, maybe factor it out into a
|
||||||
|
// TODO:generic error reporting function or component.
|
||||||
|
document.body.innerText = `Fatal error: "${e.message}".`;
|
||||||
|
console.error(`got backend error "${e.message}"`);
|
||||||
|
});
|
||||||
}
|
}
|
@ -101,3 +101,19 @@ button {
|
|||||||
font-size: 120%;
|
font-size: 120%;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We use fading to hide slower DOM updates */
|
||||||
|
.fade {
|
||||||
|
-webkit-animation: fade 0.7s;
|
||||||
|
animation: fade 0.7s;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes fade {
|
||||||
|
from {opacity: 0}
|
||||||
|
to {opacity: 1}
|
||||||
|
}
|
||||||
|
@keyframes fade {
|
||||||
|
from {opacity: 0}
|
||||||
|
to {opacity: 1}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user