diff --git a/public/ajquery.js b/public/ajquery.js new file mode 100644 index 0000000..c2575e4 --- /dev/null +++ b/public/ajquery.js @@ -0,0 +1,13 @@ +'use strict'; + +var $ = function(sel, el) { + return (el || window.document).querySelector(sel); +}; +$.create = function(html) { + var div = document.createElement('div'); + div.innerHTML = html; + return div; +}; +var $$ = function(sel, el) { + return (el || window.document).querySelectorAll(sel); +}; diff --git a/public/hooks.js b/public/hooks.js new file mode 100644 index 0000000..d5391e0 --- /dev/null +++ b/public/hooks.js @@ -0,0 +1,301 @@ +(function() { + 'use strict'; + + // AJ Query + var $ = window.$; + var $$ = window.$$; + + var state = {}; + + var $grantTpl; + var $devTpl; + var $updateTpl; + var $headerTpl; + var $webhookTpl; + var $webhookHeaderTpl; + + // TODO add offset based on date selected (i.e. MDT -0500) + var tzdb = [ + 'America/New_York', + 'America/Chicago', + 'America/Denver', + 'America/Phoenix', + 'America/Los_Angeles', + 'America/Sao_Paulo', + 'Europe/London', + 'Europe/Berlin', + 'Europe/Moscow', + 'Asia/Dubai', + 'Asia/Kolkata', + 'Asia/Hong_Kong', + 'Asia/Tokyo', + 'Pacific/Auckland', + 'Australia/Sydney' + ]; + + function run() { + $headerTpl = $('.js-new-webhook .js-header').outerHTML; + + $webhookHeaderTpl = $('.js-schedule .js-webhook .js-header').outerHTML; + $('.js-schedule .js-webhooks .js-headers').innerHTML = ''; + $webhookTpl = $('.js-schedule .js-webhook').outerHTML; + $('.js-schedule .js-webhooks').innerHTML = ''; + + // after blanking all inner templates + $devTpl = $('.js-schedule').outerHTML; + + console.log('hello'); + + $('body').addEventListener('click', function(ev) { + if (ev.target.matches('.js-new-header')) { + newWebhookHeader(ev.target); + } else if (ev.target.matches('.js-rm-header')) { + rmWebhookHeader(ev.target); + } else if ( + ev.target.matches('.js-delete') && + ev.target.closest('.js-grant') + ) { + deleteGrant(ev.target.closest('.js-grant')); + } else if ( + ev.target.matches('.js-delete') && + ev.target.closest('.js-webhook') + ) { + deleteWebhook(ev.target.closest('.js-webhook')); + } else { + return; + } + ev.preventDefault(); + ev.stopPropagation(); + }); + + $('body').addEventListener('submit', function(ev) { + if (ev.target.matches('.js-new-schedule')) { + newSchedule(ev.target); + } else { + return; + } + ev.preventDefault(); + ev.stopPropagation(); + }); + } + + function newSchedule() { + var $hook = $('.js-new-webhook'); + var deviceId = $hook.closest('.js-schedule').querySelector('.js-id').value; + var hook = { + comment: $('.js-comment', $hook).value, + method: $('.js-method', $hook).value, + url: $('.js-url', $hook).value, + headers: {} + }; + $$('.js-header', $hook).forEach(function($head) { + var key = $('.js-key', $head).value; + var val = $('.js-value', $head).value; + if (key && val) { + hook.headers[key] = val; + } + }); + hook.body = $('.js-body-template', $hook).value; + // TODO update on template change and show preview + + var opts = { + method: 'POST', + headers: { + Accept: 'application/json', + Authorization: JSON.parse(localStorage.getItem('session')).access_token, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(hook), + cors: true + }; + + /* + state.account.devices + .filter(function(d) { + return d.accessToken == deviceId; + })[0] + .webhooks.push(hook); + + displayAccount(state.account); + return; + */ + + window + .fetch('/api/iot/devices/' + deviceId + '/webhooks', opts) + .then(function(resp) { + return resp + .json() + .then(function(data) { + if (!data.webhook) { + throw new Error('something bad happened'); + return; + } + + state.account.devices + .filter(function(d) { + return d.accessToken == deviceId; + })[0] + .webhooks.push(resp.data.webhook); + + displayAccount(state.account); + }) + .catch(function(e) { + window.alert(e.message); + }); + }); + } + + function newWebhookHeader($newHeader) { + var $hs = $newHeader.closest('.js-headers'); + var $h = $newHeader.closest('.js-header'); + var $div = document.createElement('div'); + $div.innerHTML = $headerTpl; + $hs.append($('.js-header', $div)); + $newHeader.hidden = true; + $('.js-rm-header', $h).hidden = false; + $('.js-key', $h).required = 'required'; + $('.js-value', $h).required = 'required'; + } + + function rmWebhookHeader($rmHeader) { + var $h = $rmHeader.closest('.js-header'); + $h.parentElement.removeChild($h); + } + function deleteWebhook($hook) { + var deviceId = $hook.closest('.js-schedule').querySelector('.js-id').value; + var id = $('.js-id', $hook).innerText; + var opts = { + method: 'DELETE', + headers: { + Accept: 'application/json', + Authorization: JSON.parse(localStorage.getItem('session')).access_token + }, + cors: true + }; + window + .fetch('/api/iot/devices/' + deviceId + '/webhooks/' + id, opts) + .then(function(resp) { + return resp.json().then(function(result) { + if (!result.webhook) { + console.error(result); + window.alert('something went wrong: ' + JSON.stringify(result)); + return; + } + var index = -1; + var dev = state.account.devices.filter(function(d, i) { + return d.accessToken == deviceId; + })[0]; + dev.webhooks.some(function(g, i) { + if (g.id === id) { + index = i; + return true; + } + }); + if (index > -1) { + dev.webhooks.splice(index, 1); + displayAccount(state.account); + } + }); + }); + } + + function displayAccount(data) { + state.account = data; + console.log('[debug] Display Account:'); + console.log(data); + var $devs = $('.js-schedules'); + $devs.innerHTML = ''; + data.devices.forEach(function(d) { + var $dev = $.create($devTpl); + $('.js-ieme', $dev).innerText = d.id; + $('.js-id', $dev).value = d.accessToken; + $('.js-update-url', $dev).innerText = d.updateUrl; + d.webhooks.forEach(function(h) { + var $hook = $.create($webhookTpl); + $('.js-id', $hook).innerText = h.id; + $('.js-comment', $hook).innerText = h.comment; + $('.js-method', $hook).innerText = h.method; + $('.js-url', $hook).innerText = h.url; + Object.keys(h.headers).forEach(function(k) { + var $header = $.create($webhookHeaderTpl); + var v = h.headers[k]; + $('.js-key', $header).innerText = k; + $('.js-value', $header).innerText = v; + $('.js-headers', $hook).innerHTML += $header.innerHTML; + }); + $('.js-body-template', $hook).innerText = h.body; + $('.js-webhooks', $dev).innerHTML += $hook.innerHTML; + }); + d.grants.forEach(function(g) { + var $grant = $.create($grantTpl); + $('.js-id', $grant).innerText = g.id; + $('.js-comment', $grant).innerText = g.comment; + $('.js-token', $grant).innerText = g.token; + //TODO Math.floor(Date.now() / 1000); + var url = + 'https://test.therootcompany.com/api/v1/devices/' + + d.accessToken + + '/updates?since=' + + 0; + $('.js-example-curl .js-example-url', $grant).innerText = url; + $('.js-example-curl .js-example-token', $grant).innerText = g.token; + $('.js-example-js .js-example-url', $grant).innerText = url; + $('.js-example-js .js-example-id', $grant).innerText = d.accessToken; + $('.js-example-js .js-example-token', $grant).innerText = g.token; + $('.js-grants', $dev).innerHTML += $grant.innerHTML; + }); + d.updates.slice(0, 10).forEach(function(u) { + var $update = $.create($updateTpl); + $('.js-update-details', $update).innerText = JSON.stringify(u); + $('.js-updates', $dev).innerHTML += $update.innerHTML; + }); + $devs.innerHTML += $dev.innerHTML; + }); + } + + console.info('[tzdb] requesting'); + window.fetch('./tzdb.json').then(function(resp) { + return resp.json().then(function(tzdb) { + console.info('[tzdb] received'); + var tz = Intl.DateTimeFormat().resolvedOptions().timeZone; + var options = $$('.js-schedule-tz option'); + var valOpt = options[0].outerHTML; // UTC + var spaceOpt = options[1].outerHTML; // ---- + var innerHTML = $('.js-schedule-tz').innerHTML; + innerHTML = + '' + + spaceOpt + + innerHTML.replace(/>UTC/, '> UTC'); + //$('.js-schedule-tz').innerHTML += spaceOpt; + //$('.js-schedule-tz').innerHTML += valOpt.replace(/UTC/g, 'custom'); + Object.keys(tzdb) + .sort() + .forEach(function(k) { + var parts = k.split(' '); + //var sep = '── ' + parts[0]; + var sep = parts[0]; + if (parts[0] !== parts[1]) { + sep += ' / ' + parts[1] + ' (DST)'; + } + //innerHTML += ''; + innerHTML += ''; + }); + $('.js-schedule-tz').innerHTML = innerHTML; + + console.info('[tzdb] loaded'); + run(); + }); + }); + //window.addEventListener('load', run); +})(); diff --git a/public/index.html b/public/index.html index 600e744..e31ace4 100644 --- a/public/index.html +++ b/public/index.html @@ -4,7 +4,9 @@
+
+
+
+