Files
AAS_NewGeneration/html/webpage/assets/js/overview.js
2025-10-28 15:42:40 +07:00

360 lines
14 KiB
JavaScript

/**
* @typedef {Object} StreamerOutputData
* @property {number} index - The index of the Barix connection.
* @property {string} channel - The channel name of the Barix connection.
* @property {string} ipaddress - The IP address of the Barix connection.
* @property {number} bufferRemain - The remaining buffer size of the Barix connection.
* @property {boolean} isPlaying - true = playback started, false = playback stopped
* @property {number} vu - The VU level of the Barix connection, 0 to 100.
*/
/**
* @typedef {Object} PagingQueue
* @property {number} index - The index of the paging queue item.
* @property {string} Date_Time - The date and time of the paging queue item.
* @property {string} Source - The source of the paging queue item.
* @property {string} Type - The type of the paging queue item.
* @property {string} Message - The message of the paging queue item.
* @property {string} BroadcastZones - The broadcast zones of the paging queue item.
*/
/**
* @typedef {Object} StreamerCard
* @property {JQuery<HTMLElement> | null} title - The jQuery result should be <h4> element.
* @property {JQuery<HTMLElement> | null} ip - The jQuery result should be <h6> element.
* @property {JQuery<HTMLElement> | null} buffer - The jQuery result should be <h6> element.
* @property {JQuery<HTMLElement> | null} status - The jQuery result should be <p> element.
* @property {JQuery<HTMLElement> | null} vu - The jQuery result should be <progress-bar> element.
*/
function getCardByIndex(index) {
let obj = {
// title is <h4> element wiht id `streamertitle${index}`, with index as two digit number, e.g. 01, 02, 03
title: $(`#streamertitle${index.toString().padStart(2, '0')}`),
// ip is <h6> element with id `streamerip${index}`, with index as two digit number, e.g. 01, 02, 03
ip: $(`#streamerip${index.toString().padStart(2, '0')}`),
// buffer is <h6> element with id `streamerbuffer${index}`, with index as two digit number, e.g. 01, 02, 03
buffer: $(`#streamerbuffer${index.toString().padStart(2, '0')}`),
// status is <p> element with id `streamerstatus${index}`, with index as two digit number, e.g. 01, 02, 03
status: $(`#streamerstatus${index.toString().padStart(2, '0')}`),
// vu is <progress-bar> element with id `streamervu${index}`, with index as two digit number, e.g. 01, 02, 03
vu: $(`#streamervu${index.toString().padStart(2, '0')} .progress-bar`),
}
return obj;
}
/**
* Updates the streamer card with the provided values.
* @param {StreamerOutputData[]} values
*/
function UpdateStreamerCard(values) {
if (!Array.isArray(values) || values.length === 0) return;
function setProgress(index, $bar, value, max = 100) {
const v = Number(value ?? 0);
const pct = Math.max(0, Math.min(100, Math.round((v / max) * 100)));
//if (index!==1) return; // only update index 1 for testing
//console.log(`setProgress: index=${index}, value=${v}, pct=${pct}`);
$bar
.attr('aria-valuenow', v) // semantic value
.css('width', pct + '%') // visual width
.text(pct); // optional label
}
for (let i = 1; i <= 64; i++) {
let vv = values.find(v => v.index === i);
let card = getCardByIndex(i);
if (vv) {
// there is value for this index
if (card.title) card.title.text(vv.channel ? vv.channel : `Channel ${i.toString().padStart(2, '0')}`);
if (card.ip) card.ip.text(`IP Address: ${vv.ipaddress ? vv.ipaddress : 'N/A'}`);
if (card.buffer) card.buffer.text(`Buffer: ${vv.bufferRemain !== undefined && vv.bufferRemain !== null ? vv.bufferRemain.toString() : 'N/A'}`);
if (card.status) card.status.text(`Status: ${vv.isPlaying ? 'Playing' : 'Idle'}`);
if (card.vu) {
setProgress(i, card.vu, vv.vu, 100);
}
} else {
// no value for this index, disable the card
if (card.title) card.title.text(`Channel ${i.toString().padStart(2, '0')}`);
if (card.ip) card.ip.text(`IP Address: N/A`);
if (card.buffer) card.buffer.text(`Buffer: N/A`);
if (card.status) card.status.text(`Status: Disconnected`);
if (card.vu) {
setProgress(i, card.vu, 0, 100);
}
}
}
}
/**
* @type {PagingQueue[]}
*/
window.PagingQueue = [];
/**
* @type {JQuery<HTMLElement> | null}
*/
window.selectedpagingrow = null;
/**
* @typedef {Object} QueueTable
* @property {number} index - The index of the automatic queue item.
* @property {string} Date_Time - The date and time of the automatic queue item.
* @property {string} Source - The source of the automatic queue item.
* @property {string} Type - The type of the automatic queue item.
* @property {string} Message - The message of the automatic queue item.
* @property {string} SB_TAGS - The SB_TAGS of the automatic queue item.
* @property {string} BroadcastZones - The broadcast zones of the automatic queue item.
* @property {number} Repeat - The repeat count of the automatic queue item.
* @property {string} Language - The language of the automatic queue item.
*/
/**
* @type {QueueTable[]}
*/
window.QueueTable = [];
/**
* @type {JQuery<HTMLElement> | null}
*/
window.selectedautomaticrow = null;
/**
* Fills the paging queue table body with the provided data.
* @param {PagingQueue[]} vv array of PagingQueue objects
* @returns
*/
function fill_pagingqueuetablebody(vv) {
$('#pagingqueuetable').empty();
if (!Array.isArray(vv) || vv.length === 0) return;
vv.forEach(item => {
// fill index and description columns using item properties
$('#pagingqueuetable').append(`<tr>
<td>${item.index}</td>
<td>${item.date_Time}</td>
<td>${item.source}</td>
<td>${item.type}</td>
<td>${item.message}</td>
<td>${item.broadcastZones}</td>
</tr>`);
let $addedrow = $('#pagingqueuetable tr:last');
$addedrow.off('click').on('click', function () {
if (window.selectedpagingrow) {
window.selectedpagingrow.find('td').css('background-color', '');
if (window.selectedpagingrow.is($(this))) {
window.selectedpagingrow = null;
$('#removepagingqueue').prop('disabled', true);
return;
}
}
window.selectedpagingrow = $(this);
window.selectedpagingrow.find('td').css('background-color', 'lightblue');
$('#removepagingqueue').prop('disabled', false);
});
});
}
/**
* Fills the automatic queue table body with the provided data.
* @param {QueueTable[]} vv array of QueueTable objects
* @returns
*/
function fill_automaticqueuetablebody(vv) {
$('#automaticqueuetable').empty();
if (!Array.isArray(vv) || vv.length === 0) return;
vv.forEach(item => {
// fill index and description columns using item properties
//console.log("fill_automaticqueuetablebody: item", item);
$('#automaticqueuetable').append(`<tr>
<td>${item.index}</td>
<td>${item.date_Time}</td>
<td>${item.source}</td>
<td>${item.type}</td>
<td>${item.message}</td>
<td>${item.broadcastZones}</td>
</tr>`);
let $addedrow = $('#automaticqueuetable tr:last');
$addedrow.off('click').on('click', function () {
if (window.selectedautomaticrow) {
window.selectedautomaticrow.find('td').css('background-color', '');
if (window.selectedautomaticrow.is($(this))) {
window.selectedautomaticrow = null;
$('#removeautomatictable').prop('disabled', true);
return;
}
}
window.selectedautomaticrow = $(this);
window.selectedautomaticrow.find('td').css('background-color', 'lightblue');
$('#removeautomatictable').prop('disabled', false);
});
});
}
function reloadPagingQueue(APIURL = "QueuePaging/") {
window.PagingQueue = [];
fetchAPI(APIURL + "List", "GET", {}, null, (okdata) => {
if (Array.isArray(okdata) && okdata.length > 0) {
window.PagingQueue.push(...okdata);
fill_pagingqueuetablebody(window.PagingQueue);
} else {
console.log("reloadPagingQueue: okdata is not array");
}
}, (errdata) => {
console.log("reloadPagingQueue: errdata", errdata);
});
}
function reloadAutomaticQueue(APIURL = "QueueTable/") {
window.QueueTable = [];
fetchAPI(APIURL + "List", "GET", {}, null, (okdata) => {
if (Array.isArray(okdata) && okdata.length > 0) {
window.QueueTable.push(...okdata);
fill_automaticqueuetablebody(window.QueueTable);
} else {
console.log("reloadAutomaticQueue: okdata is not array");
}
}, (errdata) => {
console.log("reloadAutomaticQueue: errdata", errdata);
});
}
function RemovePagingQueueByIndex(index, APIURL = "QueuePaging/") {
fetchAPI(APIURL + "DeleteByIndex/" + index, "DELETE", {}, null, (okdata) => {
console.log("RemovePagingQueueByIndex: okdata", okdata);
reloadPagingQueue(APIURL);
}, (errdata) => {
console.log("RemovePagingQueueByIndex: errdata", errdata);
});
}
function RemoveAutomaticQueueByIndex(index, APIURL = "QueueTable/") {
fetchAPI(APIURL + "DeleteByIndex/" + index, "DELETE", {}, null, (okdata) => {
console.log("RemoveAutomaticQueueByIndex: okdata", okdata);
reloadAutomaticQueue(APIURL);
}, (errdata) => {
console.log("RemoveAutomaticQueueByIndex: errdata", errdata);
});
}
$(document).ready(function () {
console.log("overview.js loaded");
$('#clearpagingqueue').off('click').on('click', function () {
DoClear("QueuePaging/", "Paging Queue", (okdata) => {
reloadPagingQueue();
alert("Success clear Paging Queue: " + okdata.message);
}, (errdata) => {
alert("Error clear Paging Queue: " + errdata.message);
});
});
$('#removepagingqueue').off('click').on('click', function () {
if (window.selectedpagingrow) {
let cells = window.selectedpagingrow.find('td');
let index = Number(cells.eq(0).text());
let description = cells.eq(1).text();
if (!isNaN(index) && description && description.length > 0) {
if (confirm(`Are you sure to remove Paging Queue Index: ${index} Description: ${description} ?`)) {
RemovePagingQueueByIndex(index);
window.selectedpagingrow = null;
$('#removepagingqueue').prop('disabled', true);
}
}
}
});
$('#clearautomatictable').off('click').on('click', function () {
DoClear("QueueTable/", "Automatic Queue", (okdata) => {
reloadAutomaticQueue();
alert("Success clear Automatic Queue: " + okdata.message);
}, (errdata) => {
alert("Error clear Automatic Queue: " + errdata.message);
});
});
$('#removeautomatictable').off('click').on('click', function () {
if (window.selectedautomaticrow) {
let cells = window.selectedautomaticrow.find('td');
let index = Number(cells.eq(0).text());
let description = cells.eq(1).text();
if (!isNaN(index) && description && description.length > 0) {
if (confirm(`Are you sure to remove Automatic Queue Index: ${index} Description: ${description} ?`)) {
RemoveAutomaticQueueByIndex(index);
window.selectedautomaticrow = null;
$('#removeautomatictable').prop('disabled', true);
}
}
}
});
let intervaljob1 = null;
let intervaljob2 = null;
function runIntervalJob() {
if (intervaljob1) clearInterval(intervaljob1);
intervaljob1 = setInterval(() => {
sendCommand("getStreamerOutputs", "");
}, 100);
if (intervaljob2) clearInterval(intervaljob2);
intervaljob2 = setInterval(() => {
sendCommand("getPagingQueue", "");
sendCommand("getAASQueue", "");
}, 2000);
console.log("overview.js interval job started");
}
runIntervalJob();
window.addEventListener('ws_connected', () => {
console.log("overview.js ws_connected event triggered");
runIntervalJob();
});
window.addEventListener('ws_disconnected', () => {
console.log("overview.js ws_disconnected event triggered");
if (intervaljob) clearInterval(intervaljob);
intervaljob = null;
});
window.addEventListener('ws_message', (event) => {
let rep = event.detail;
let cmd = rep.reply;
let data = rep.data;
if (cmd && cmd.length > 0) {
switch (cmd) {
case "getPagingQueue":
let pq = JSON.parse(data);
//console.log("getPagingQueue:", pq);
window.PagingQueue = [];
if (Array.isArray(pq) && pq.length > 0) {
window.PagingQueue.push(...pq);
}
fill_pagingqueuetablebody(window.PagingQueue);
break;
case "getAASQueue":
let aq = JSON.parse(data);
//console.log("getAASQueue:", aq);
window.QueueTable = [];
if (Array.isArray(aq) && aq.length > 0) {
window.QueueTable.push(...aq);
}
fill_automaticqueuetablebody(window.QueueTable);
break;
case "getStreamerOutputs":
/**
* @type {StreamerOutputData[]}
*/
let so = JSON.parse(data);
UpdateStreamerCard(so);
break;
}
}
});
$(window).on('beforeunload', function () {
console.log("overview.js beforeunload event triggered");
clearInterval(intervaljob1);
clearInterval(intervaljob2);
intervaljob1 = null;
intervaljob2 = null;
});
});