diff --git a/gui/dashboard/app.svelte b/gui/dashboard/app.svelte index c7f1244..526fb3c 100644 --- a/gui/dashboard/app.svelte +++ b/gui/dashboard/app.svelte @@ -3,7 +3,7 @@ import TileRawValue from './tile-rawvalue.svelte'; import Settings from './settings.svelte'; import { flip } from 'svelte/animate'; - import { shuffle } from './lib'; + import { shuffle, ringBell } from './lib'; const [ send, receive ] = shuffle; const size = 3 * 4 - 1; @@ -43,29 +43,38 @@ ws.onmessage = async evt => { const data = JSON.parse(evt.data || '""'); - if (data.cmd === 'data') { - let servicesTemp = []; - const { servicesUp, servicesDown, servicesUnknown, total } = data; - const upOrUnknown = [ ...servicesUp, ...servicesUnknown ]; - servicesTemp = servicesDown.slice(0, size); + switch (data.cmd) { + case 'data': + let servicesTemp = []; + const { servicesUp, servicesDown, servicesUnknown, total } = data; + const upOrUnknown = [ ...servicesUp, ...servicesUnknown ]; + servicesTemp = servicesDown.slice(0, size); - if (pageNum === -1 || total >= size) { - pageNum++; + if (pageNum === -1 || total >= size) { + pageNum++; - if (pageNum > Math.ceil(upOrUnknown.length / size)) { - pageNum = 0; + if (pageNum > Math.ceil(upOrUnknown.length / size)) { + pageNum = 0; + } } - } - const placesLeft = size - servicesTemp.length; - const offset = placesLeft * pageNum; - if (placesLeft > 0) { - servicesTemp.push( - ...upOrUnknown.slice(offset, placesLeft + offset) - ); - } + const placesLeft = size - servicesTemp.length; + const offset = placesLeft * pageNum; + if (placesLeft > 0) { + servicesTemp.push( + ...upOrUnknown.slice(offset, placesLeft + offset) + ); + } - tiles = servicesTemp; + tiles = servicesTemp; + break; + + case 'bell': + ringBell(); + break; + + default: + break; } } diff --git a/gui/dashboard/lib.js b/gui/dashboard/lib.js index 9a72cf6..d19ccfd 100644 --- a/gui/dashboard/lib.js +++ b/gui/dashboard/lib.js @@ -34,3 +34,10 @@ export const shuffle = crossfade({ }; }, }); + +//export const ringBell = bell.play; + +export function ringBell() { + const bell = new Audio('http://__SERVER__/statusdashboard/sound'); + bell.addEventListener('canplaythrough', () => bell.play()); +} diff --git a/gui/sounds/bell.wav b/gui/sounds/bell.wav new file mode 100644 index 0000000..00dff80 Binary files /dev/null and b/gui/sounds/bell.wav differ diff --git a/index.js b/index.js index 2f167b2..c4e83f2 100644 --- a/index.js +++ b/index.js @@ -569,6 +569,14 @@ module.exports = { }, }, + { route: '/statusdashboard/sound', + method: 'get', + handler: (req, res) => { + res.headers['content-type'] = 'audio/x-wav'; + res.sendFile(__dirname + '/gui/sounds/bell.wav'); + }, + }, + ], }; diff --git a/lib/dashboard/socket.js b/lib/dashboard/socket.js index e9df140..7d34758 100644 --- a/lib/dashboard/socket.js +++ b/lib/dashboard/socket.js @@ -4,6 +4,8 @@ const { makeId } = require('core/makeid'); const decoder = new TextDecoder('utf-8'); let uws; +let downIdsBefore = []; +let downIdsAfter = []; const mapService = (s, beat) => ({ id: s.id, @@ -30,7 +32,7 @@ async function createDashboardSocket(server) { const servicesUp = []; const servicesDown = []; const servicesUnknown = []; - console.log(heartbeats); + downIdsAfter = []; for (let service of services) { const beat = heartbeats.find(b => b.webservice === service.id); @@ -41,6 +43,7 @@ async function createDashboardSocket(server) { } else if (beat.down) { servicesDown.push(service); + downIdsAfter.push(service.id); } else { servicesUp.push(service); @@ -53,7 +56,19 @@ async function createDashboardSocket(server) { ...servicesUnknown, ].length; + let newOutage = false; + for (const id of downIdsAfter) { + if (!downIdsBefore.includes(id)) { + newOutage = true; + } + } + downIdsBefore = JSON.parse(JSON.stringify(downIdsAfter)); + try { + if (newOutage) { + ws.send(JSON.stringify({ cmd: 'bell' })); + } + ws.send(JSON.stringify({ cmd: 'data', servicesUp,