go-again/public/app.js

359 lines
10 KiB
JavaScript

(function() {
'use strict';
// AJ Query
var $ = window.$;
var $$ = window.$$;
var state = { account: { schedules: [] } };
var $grantTpl;
var $devTpl;
var $updateTpl;
var $headerTpl;
var $webhookTpl;
var $webhookHeaderTpl;
function pad(i) {
i = String(i);
while (i.length < 2) {
i = '0' + i;
}
return i;
}
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;
// Pick a date and time on an even number
// between 10 and 15 minutes in the future
var d = new Date(Date.now() + 10 * 60 * 1000);
var minutes = d.getMinutes() + (5 - (d.getMinutes() % 5)) - d.getMinutes();
d = new Date(d.valueOf() + minutes * 60 * 1000);
$('.js-date').value = d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate());
$('.js-time').value = pad(d.getHours()) + ':' + pad(d.getMinutes());
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('change', function(ev) {
var $hook = ev.target.closest('.js-new-webhook');
if (ev.target.matches('.js-url') && $hook) {
if (!$('.js-comment', $hook).value) {
$('.js-comment', $hook).value = ev.target.value.replace(/https:\/\//, '').replace(/\/.*/, '');
}
}
});
$('body').addEventListener('submit', function(ev) {
if (ev.target.matches('.js-new-schedule')) {
newSchedule(ev.target);
} else if (ev.target.matches('.js-schedules-list')) {
doLogin();
} else if (ev.target.matches('.js-schedules-new')) {
scheduleTask();
} else {
return;
}
ev.preventDefault();
ev.stopPropagation();
});
}
function newSchedule() {
var $hook = $('.js-schedule');
//var deviceId = $hook.closest('.js-schedule').querySelector('.js-id').value;
var schedule = {
schedule: {
date: $('.js-date', $hook).value,
time: $('.js-time', $hook).value,
tz: $('.js-tz', $hook).value
},
webhooks: []
};
var hook = {
comment: $('.js-comment', $hook).value,
method: $('.js-method', $hook).value,
url: $('.js-url', $hook).value,
headers: {}
};
schedule.webhooks.push(hook);
console.log('schedule:', schedule);
$$('.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: getToken(),
'Content-Type': 'application/json'
},
body: JSON.stringify(schedule),
cors: true
};
/*
state.account.devices
.filter(function(d) {
return d.accessToken == deviceId;
})[0]
.webhooks.push(hook);
displayAccount(state.account);
return;
*/
window.fetch('/api/v0/schedules', opts).then(function(resp) {
return resp
.json()
.then(function(data) {
if (!data.schedule) {
throw new Error('something bad happened');
}
state.account.schedules.webhooks.push(resp.data.schedule);
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: getToken()
},
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-tz option');
var valOpt = options[0].outerHTML; // UTC
var spaceOpt = options[1].outerHTML; // ----
var innerHTML = $('.js-tz').innerHTML;
/*
innerHTML =
'<option selected value="' +
tz +
'">&nbsp;&nbsp;&nbsp;&nbsp;' +
tz +
'</option>' +
spaceOpt +
innerHTML.replace(/>UTC/, '>&nbsp;&nbsp;&nbsp;&nbsp;UTC');
*/
//$('.js-tz').innerHTML += spaceOpt;
//$('.js-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 += '<option disabled>' + sep + '</option>';
innerHTML += '<optgroup label="' + sep + '">';
var areas = tzdb[k];
areas.forEach(function(_tz) {
if (tz !== _tz) {
innerHTML += valOpt.replace(/UTC/g, _tz);
} else {
innerHTML += '<option selected value="' + tz + '">' + tz + '</option>';
}
});
innerHTML += '</optgroup>';
});
$('.js-tz').innerHTML = innerHTML;
console.info('[tzdb] loaded');
run();
});
});
var allSchedules = [];
function getToken() {
return JSON.parse(localStorage.getItem('session')).access_token;
}
function doLogin() {
localStorage.setItem(
'session',
JSON.stringify({
access_token: $('.js-auth-token').value
})
);
$('.js-schedules-list').hidden = true;
$('.js-schedules').hidden = false;
return window
.fetch('/api/v0/schedules', {
headers: { Authorization: getToken() }
})
.then(function(resp) {
return resp.json().then(function(schedules) {
allSchedules = schedules;
renderSchedules(schedules);
});
});
}
function renderSchedules(schedules) {
document.querySelector('.js-schedules-output').innerText = JSON.stringify(schedules, null, 2);
}
function scheduleTask() {
return window
.fetch('/api/v0/schedules/new', {
method: 'POST',
headers: {
Authorization: getToken(),
'Content-Type': 'application/json'
},
body: JSON.stringify(task)
})
.then(function(resp) {
return resp.json().then(function(schedule) {
console.log('New Schedule:', schedule);
allSchedules.push(schedule);
renderSchedules(allSchedules);
});
});
}
//window.addEventListener('load', run);
})();