hugvey/www/js/hugvey_timeline.js

251 lines
7.4 KiB
JavaScript
Raw Normal View History

var ws = new ReconnectingWebSocket( window.location.origin.replace('http', 'ws') +'/ws', null, { debug: false, reconnectInterval: 3000 } );
2019-04-25 17:08:27 +00:00
var seeme = true;
var tl ;
var error_audio = new Audio('siren.wav');
var playSoundOnError = true;
var checkbox_sound = document.getElementById('play_sound_on_error')
2019-11-12 08:54:55 +00:00
if(checkbox_sound != null) {
checkbox_sound.addEventListener('change', (event) => {
if (event.target.checked) {
playSoundOnError = true;
} else {
playSoundOnError = false;
}
})
}
2019-08-29 08:15:33 +00:00
2019-04-25 17:08:27 +00:00
//request close before unloading
window.addEventListener('beforeunload', function(){
ws.close();
});
ws.addEventListener( 'close', function( e ) {
console.log( 'Closed connection' );
} );
class Timeline{
constructor(ws, el, nr) {
this.ws = ws;
this.el = el;
this.count = nr;
this.eventDataSet = new vis.DataSet([
{content: '.', start: new Date(), type: 'point', group: 1}
]);
2019-05-15 14:03:51 +00:00
// console.log('init timeline');
this.lightMap = {};
2019-05-11 13:23:55 +00:00
2019-04-25 17:08:27 +00:00
let groups = [];
for(let hid = 1; hid<=this.count; hid++) {
groups.push({id: parseInt(hid), content: 'Hugvey #'+hid});
this.eventDataSet.add({content: 'initiate', start: new Date(), type: 'point', group: parseInt(hid)})
}
2019-05-11 13:23:55 +00:00
2019-05-15 14:03:51 +00:00
this.dataGroups = new vis.DataSet(groups);
2019-04-25 17:08:27 +00:00
let options = {
2019-05-16 14:16:44 +00:00
maxHeight: '100%',
2019-05-18 11:14:58 +00:00
height: '100%',
2019-05-16 14:16:44 +00:00
margin : {
item: {
horizontal: 0,
vertical: 5
}
},
zoomMax: 3600000 // 1 h
2019-04-25 17:08:27 +00:00
// 'rollingMode': {'follow': true, 'offset': .8 }
};
2019-05-15 14:03:51 +00:00
// console.log('groups', this.dataGroups, groups, options);
2019-05-11 13:23:55 +00:00
2019-05-15 14:03:51 +00:00
this.timeline = new vis.Timeline(this.el, this.eventDataSet, this.dataGroups, options);
2019-05-11 13:23:55 +00:00
2019-04-25 17:08:27 +00:00
let tl = this.timeline;
let startDate = new Date();
startDate.setMinutes(startDate.getMinutes()-1);
let endDate = new Date();
endDate.setMinutes(endDate.getMinutes()+20);
//follow the timeline or not if checkbox is checked
setTimeout(function(){
tl.setWindow(startDate, endDate);
}, 500);
2019-04-25 17:08:27 +00:00
this.moveInterval = setInterval(function(){
// skip movement if not visible
tl.moveTo(new Date());
}, 1000);
var checkbox = document.getElementById('follow_checkbox')
checkbox.addEventListener('change', (event) => {
if (event.target.checked) {
this.moveInterval = setInterval(function(){
// skip movement if not visible
tl.moveTo(new Date());
}, 1000);
} else {
clearInterval(this.moveInterval)
}
});
2019-05-11 13:23:55 +00:00
2019-04-25 17:08:27 +00:00
ws.addEventListener( 'message', this);
}
2019-05-11 13:23:55 +00:00
2019-04-25 17:08:27 +00:00
handleEvent(e) {
2019-05-15 14:03:51 +00:00
// console.log('handle it', e, this);
2019-04-25 17:08:27 +00:00
if(e.type == 'message') {
this.wsOnMessage(e)
}
}
2019-05-11 13:23:55 +00:00
2019-04-25 17:08:27 +00:00
wsOnMessage(e) {
let msg = JSON.parse( e.data );
2019-05-11 13:23:55 +00:00
2019-04-25 17:08:27 +00:00
if ( typeof msg['action'] === 'undefined' ) {
console.error( "not a valid message: " + e.data );
return;
}
2019-05-18 11:14:58 +00:00
2019-05-15 14:03:51 +00:00
if(msg['action'] == 'status') {
// reconstruct mapping of lights to hugveys
this.lightMap = {}
for(let hv of msg['hugveys']){
if(!this.lightMap.hasOwnProperty(hv['light_id'])) {
this.lightMap[hv['light_id']] = [];
}
this.lightMap[hv['light_id']].push(hv['id']);
}
// loop over statusses of hugveys and show them at the appropriate lights
2019-05-15 14:03:51 +00:00
for(let hv of msg['hugveys']){
// console.log(hv['language'], hv['status']);
let evenOdd = parseInt(hv['light_id'])%2 ? 'odd': 'even';
2019-11-13 22:43:02 +00:00
let availableClass = hv['available'] ? 'is-available' : 'is-not-available';
let realHugveyId = "";
if(this.lightMap[hv['light_id']].length > 1 || this.lightMap[hv['light_id']][0] != hv['light_id']) {
realHugveyId = '(#' + this.lightMap[hv['light_id']].join(' #') + ')';
}
this.dataGroups.update({id: parseInt(hv['light_id']), content: `<div class='title'>Hugvey ${hv['light_id']} ${realHugveyId}</div><div class='times'><span class='${hv['time_since_hugvey_spoke_state']}'>${hv['time_since_hugvey_spoke']}</span><span class='${hv['time_since_visitor_spoke_state']}'>${hv['time_since_visitor_spoke']}</span></div>`, className: `status-${hv['status']} ${availableClass} lang-${hv['language']} ${evenOdd}`})
2019-05-15 14:03:51 +00:00
}
}
2019-05-11 13:23:55 +00:00
2019-04-25 17:08:27 +00:00
if(msg['action'] != 'log') {
return;
}
2019-05-11 13:23:55 +00:00
// let hv_id = parseInt(msg['id']);
let hv_machine_id = parseInt(msg['id']);
// map to light id:
let hv_id = Object.keys(this.lightMap).find(key => this.lightMap[key].indexOf(hv_machine_id) >= 0);
console.debug(msg, hv_id);
2019-04-25 17:08:27 +00:00
// {'action': 'log', 'id':hugvey_id, 'type': items[0], 'info', 'args'}
let d, parts;
switch(msg['type']){
case 'message':
// info: en-njsm8bwbd "Are you up for a conversation?"
parts = msg['info'].trim().split(' ');
let msgId = parts.shift();
let msgUuid = parts.shift();
let msgEvent = parts.shift();
let msgContent = parts.join(' ');
let mId = 'm-'+msgUuid+'-'+hv_id;
d = this.eventDataSet.get(mId);
// console.log(msgId, msgEvent, msgContent);
2019-04-25 17:08:27 +00:00
if(d !== null && msgEvent == 'done'){
d['end'] = new Date();
this.eventDataSet.update(d);
// console.log('update', d);
2019-04-25 17:08:27 +00:00
} else {
this.eventDataSet.add({id: mId, content: msgContent, title: `${msgContent} (${msgId})`, start: new Date(), end: new Date(Date.now()+5000), group: hv_id, 'className': 'message'});
2019-04-25 17:08:27 +00:00
}
break;
case 'speaking':
// start/content/end
parts = msg['info'].trim().split(' ');
let info = parts.shift();
let id = parts.shift();
let content = parts.join(' ');
let scId = 'sc-'+id+'-'+hv_id;
2019-05-11 13:23:55 +00:00
2019-04-25 17:08:27 +00:00
if(info.startsWith('start')){
this.eventDataSet.add({content: info, start: new Date(), end: new Date(Date.now() + 1000), type: 'point', group: hv_id, 'className': 'speech'});
2019-04-25 17:08:27 +00:00
}
if(info.startsWith('content')){
d = this.eventDataSet.get(scId);
if(d !== null){
// console.log('alter');
2019-04-25 17:08:27 +00:00
d['content'] = content;
d['end']= new Date();
d['title'] = content;
this.eventDataSet.update(d);
} else {
// console.log('add');
this.eventDataSet.add({id: scId, content: content, title: content, start: new Date(), end: new Date(Date.now() + 1000), group: hv_id, 'className': 'speech'});
2019-04-25 17:08:27 +00:00
}
}
if(info.startsWith('end')){
d = this.eventDataSet.get(scId);
if(d !== null){
d['end'] = new Date();
this.eventDataSet.update(d);
}
}
2019-05-11 13:23:55 +00:00
2019-04-25 17:08:27 +00:00
break;
case 'story':
// 'info': 'start'/'finished'
2019-04-27 14:39:20 +00:00
this.eventDataSet.add({
2019-11-12 08:54:55 +00:00
title: msg['type'] +': ' + msg['info'] + (msg.hasOwnProperty('args')? ': '+msg['args'] : ""),
2019-04-27 14:39:20 +00:00
start: new Date(), type: 'point', group: hv_id, 'className': 'story'});
2019-04-25 17:08:27 +00:00
break;
case 'condition':
case 'direction':
// don't draw these :-0
break;
default:
2019-04-27 14:39:20 +00:00
this.eventDataSet.add({
2019-11-12 08:54:55 +00:00
title: msg['type'] +': ' + msg['info'] + (msg.hasOwnProperty('args')? ': '+msg['args'] : ""),
2019-04-27 14:39:20 +00:00
start: new Date(), type: 'point', group: hv_id, 'className': msg['lvlname']});
if (msg['lvlname'] == 'CRITICAL' && playSoundOnError) {
// error_audio.play();
}
2019-04-25 17:08:27 +00:00
break;
}
}
}
let req = new Request('/count');
fetch(req).then(response => response.json()).then(function(data) {
tl = new Timeline(ws, document.getElementById('line'), data.length);
});
2019-08-29 08:15:33 +00:00
window.addEventListener('keypress', function(e){
// console.log(e.keyCode)
2019-08-29 08:15:33 +00:00
if(e.keyCode==46){
if(seeme){
seeme = false;
let options = {
showTooltips: false
};
tl.timeline.setOptions(options)
}
else{
seeme = true;
let options = {
showTooltips: true
};
tl.timeline.setOptions(options)
}
}
});