From 0a898f853727a8600ecc57617b006af0f9694502 Mon Sep 17 00:00:00 2001 From: Humberto Alfonso Díaz Date: Thu, 20 Jun 2019 12:52:29 +0200 Subject: FUNCT Add support to load apps from AGL --- package.json | 3 +- src/config.xml | 2 +- src/images/noicon.svg | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/index.html | 47 +++------- src/index.js | 2 + src/js/AFB.js | 215 ++++++++++++++++++++++++++++++++++++++++++++ src/js/app.js | 59 ++++++++++++ src/styles/main.scss | 20 +++++ webpack.config.js | 7 +- 9 files changed, 560 insertions(+), 39 deletions(-) create mode 100644 src/images/noicon.svg create mode 100644 src/js/AFB.js create mode 100644 src/js/app.js diff --git a/package.json b/package.json index e23d95a..056455a 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "zip-webpack-plugin": "^3.0.0" }, "dependencies": { - "@iconfu/svg-inject": "^1.2.3" + "@iconfu/svg-inject": "^1.2.3", + "mustache": "^3.0.1" } } diff --git a/src/config.xml b/src/config.xml index 1f409f6..b3a885d 100644 --- a/src/config.xml +++ b/src/config.xml @@ -1,7 +1,7 @@ HTML5 Homescreen - + HTML5 Homescreen demo Igalia, S.L. diff --git a/src/images/noicon.svg b/src/images/noicon.svg new file mode 100644 index 0000000..6e1f9d3 --- /dev/null +++ b/src/images/noicon.svg @@ -0,0 +1,244 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/index.html b/src/index.html index 971ba8d..f280ebe 100644 --- a/src/index.html +++ b/src/index.html @@ -6,43 +6,18 @@ -
-
- -
- DASHBOARD +
+ +
+
+
\ No newline at end of file diff --git a/src/index.js b/src/index.js index 406ef65..1d569d6 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,6 @@ import '@iconfu/svg-inject'; +import './js/AFB.js'; +import './js/app.js'; console.log('Arrancada la aplicación compilando CSS y SaSS'); diff --git a/src/js/AFB.js b/src/js/AFB.js new file mode 100644 index 0000000..d6e6bfa --- /dev/null +++ b/src/js/AFB.js @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2017, 2018 "IoT.bzh" + * Author: José Bollo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +AFB = function(base, initialtoken){ + +if (typeof base != "object") + base = { base: base, token: initialtoken }; + +var initial = { + base: base.base || "api", + token: base.token || initialtoken || "HELLO", + host: base.host || window.location.host, + url: base.url || undefined +}; + +var urlws = initial.url || "ws://"+initial.host+"/"+initial.base; + +/*********************************************/ +/**** ****/ +/**** AFB_context ****/ +/**** ****/ +/*********************************************/ +var AFB_context; +{ + var UUID = undefined; + var TOKEN = initial.token; + + var context = function(token, uuid) { + this.token = token; + this.uuid = uuid; + } + + context.prototype = { + get token() {return TOKEN;}, + set token(tok) {if(tok) TOKEN=tok;}, + get uuid() {return UUID;}, + set uuid(id) {if(id) UUID=id;} + }; + + AFB_context = new context(); +} +/*********************************************/ +/**** ****/ +/**** AFB_websocket ****/ +/**** ****/ +/*********************************************/ +var AFB_websocket; +{ + var CALL = 2; + var RETOK = 3; + var RETERR = 4; + var EVENT = 5; + + var PROTO1 = "x-afb-ws-json1"; + + AFB_websocket = function(on_open, on_abort) { + var u = urlws, p = '?'; + if (AFB_context.token) { + u = u + '?x-afb-token=' + AFB_context.token; + p = '&'; + } + if (AFB_context.uuid) + u = u + p + 'x-afb-uuid=' + AFB_context.uuid; + this.ws = new WebSocket(u, [ PROTO1 ]); + this.url = u; + this.pendings = {}; + this.awaitens = {}; + this.counter = 0; + this.ws.onopen = onopen.bind(this); + this.ws.onerror = onerror.bind(this); + this.ws.onclose = onclose.bind(this); + this.ws.onmessage = onmessage.bind(this); + this.onopen = on_open; + this.onabort = on_abort; + } + + function onerror(event) { + var f = this.onabort; + if (f) { + delete this.onopen; + delete this.onabort; + f && f(this); + } + this.onerror && this.onerror(this); + } + + function onopen(event) { + var f = this.onopen; + delete this.onopen; + delete this.onabort; + f && f(this); + } + + function onclose(event) { + var err = { + jtype: 'afb-reply', + request: { + status: 'disconnected', + info: 'server hung up' + } + }; + 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 += '
'+smgs+'
'; +} + +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