+ } + }; + for (var id in this.pendings) { + try { this.pendings[id][1](err); } catch (x) {/*NOTHING*/} + } + this.pendings = {}; + this.onclose && this.onclose(); + } + + function fire(awaitens, name, data) { + var a = awaitens[name]; + if (a) + a.forEach(function(handler){handler(data);}); + var i = name.indexOf("/"); + if (i >= 0) { + a = awaitens[name.substring(0,i)]; + if (a) + a.forEach(function(handler){handler(data);}); + } + a = awaitens["*"]; + if (a) + a.forEach(function(handler){handler(data);}); + } + + function reply(pendings, id, ans, offset) { + if (id in pendings) { + var p = pendings[id]; + delete pendings[id]; + try { p[offset](ans); } catch (x) {/*TODO?*/} + } + } + + function onmessage(event) { + var obj = JSON.parse(event.data); + var code = obj[0]; + var id = obj[1]; + var ans = obj[2]; + AFB_context.token = obj[3]; + switch (code) { + case RETOK: + reply(this.pendings, id, ans, 0); + break; + case RETERR: + reply(this.pendings, id, ans, 1); + break; + case EVENT: + default: + fire(this.awaitens, id, ans); + break; + } + } + + function close() { + this.ws.close(); + this.ws.onopen = + this.ws.onerror = + this.ws.onclose = + this.ws.onmessage = + this.onopen = + this.onabort = function(){}; + } + + function call(method, request, callid) { + return new Promise((function(resolve, reject){ + var id, arr; + if (callid) { + id = String(callid); + if (id in this.pendings) + throw new Error("pending callid("+id+") exists"); + } else { + do { + id = String(this.counter = 4095 & (this.counter + 1)); + } while (id in this.pendings); + } + this.pendings[id] = [ resolve, reject ]; + arr = [CALL, id, method, request ]; + if (AFB_context.token) arr.push(AFB_context.token); + this.ws.send(JSON.stringify(arr)); + }).bind(this)); + } + + function onevent(name, handler) { + var id = name; + var list = this.awaitens[id] || (this.awaitens[id] = []); + list.push(handler); + } + + AFB_websocket.prototype = { + close: close, + call: call, + onevent: onevent + }; +} +/*********************************************/ +/**** ****/ +/**** ****/ +/**** ****/ +/*********************************************/ +return { + context: AFB_context, + ws: AFB_websocket +}; +}; diff --git a/src/js/app.js b/src/js/app.js new file mode 100644 index 0000000..fccf04e --- /dev/null +++ b/ src/js/app.js@@ -0,0 +1,59 @@ +import Mustache from 'mustache'; + +var host = document.location.hostname; +var port = document.location.port; +var args = new URLSearchParams(document.location.search.substring(1)); +var token = args.get("x-afb-token") || args.get("token") || "HELLO"; +var afb; +var template; + +function log(smgs) { + document.getElementById('log').innerHTML += '<div>'+smgs+'</div>'; +} + +function getIcon(app) { + if( app.icon.match(/^.*\.svg$/) ) { + return '/icons/'+app.id; + } else { + return '/images/noicon.svg'; + } +} + +function display_applications(apps) { + var appContainer = document.getElementById('AppContainer'); + for( var i=0; i<apps.length; i++) { + apps[i].icon = getIcon(apps[i]); + appContainer.innerHTML += Mustache.render(template, apps[i]); + } +} + +function load_application_list() { + var ws = new afb.ws(function() { + var api_verb = "afm-main/runnables"; + ws.call(api_verb, {}).then( + function(obj) { + display_applications(obj.response); + }, + function(obj) { + //TODO Manage errors + log("failure"); + } + ); + }, + function() { + //TODO manage errors + log("ws aborted"); + }); +} + +function init() { + template = document.getElementById('item-template').innerHTML; + Mustache.parse(template); + afb = new AFB({ + host: "raspberrypi3.local:31022", + token: token + }); + load_application_list(); +} + +document.addEventListener('DOMContentLoaded', init);
\ No newline at end of file |