Files
AAS_NewGeneration/html/webpage/assets/js/script.js
2025-09-09 15:54:42 +07:00

1261 lines
49 KiB
JavaScript

/**
* @typedef {Object} SoundBank
* @property {number} index
* @property {string} description
* @property {string} tag
* @property {string} category
* @property {string} language
* @property {string} voiceType
* @property {string} path
*/
/**
* @typedef {Object} MessageBank
* @property {number} index
* @property {string} description
* @property {string} language
* @property {number} aNN_ID
* @property {string} voice_Type
* @property {string} message_Detail
* @property {string} message_TAGS
*/
/**
* @typedef {Object} LanguageBank
* @property {number} index
* @property {string} tag
* @property {string} language
* @
*/
/**
* @typedef {Object} ScheduleBank
* @property {number} index
* @property {string} description
* @property {string} day
* @property {string} time
* @property {string} soundpath
* @property {number} repeat
* @property {boolean} enable
* @property {string} broadcastZones
* @property {string} language
*/
/**
* @typedef {Object} Log
* @property {number} index
* @property {string} datenya
* @property {string} timenya
* @property {string} machine
* @property {string} description
*/
/**
* @typedef {Object} Select2item
* @property {number} id
* @property {string} text
*/
/**
* List of Soundbank data loaded from server
* @type {SoundBank[]}
*/
let soundbankdata = [];
/**
* Currently selected soundbank row in the table
* @type {JQuery<HTMLElement>|null}
*/
let selectedsoundrow = null;
/**
* List of Messagebank data loaded from server
* @type {MessageBank[]}
*/
let messagebankdata = [];
/**
* Currently selected messagebank row in the table
* @type {JQuery<HTMLElement>|null}
*/
let selectedmessagerow = null;
/** List of Languagebank data loaded from server
* @type {LanguageBank[]}
*/
let languagebankdata = [];
/**
* Currently selected languagebank row in the table
* @type {JQuery<HTMLElement>|null}
*/
let selectedlanguagerow = null;
/** List of Schedulebank data loaded from server
* @type {ScheduleBank[]}
*/
let schedulebankdata = [];
/**
* Currently selected schedulebank row in the table
* @type {JQuery<HTMLElement>|null}
*/
let selectedschedulerow = null;
/** List of Log data loaded from server
* @type {Log[]}
*/
let logdata = [];
/**
* List of sound files in the soundbank directory, that ends with .wav or .mp3
* @type {string[]}
*/
let soundbankfiles = [];
/**
* Select2 data source
* See https://select2.org/data-sources/formats
* @type {Object}
* @property {Select2item[]} results
*/
let select2results = {
results: []
};
/**
* List of voice types available
* @type {string[]}
*/
let voiceTypes = [];
/**
* List of categories available
* @type {string[]}
*/
let categories = [];
/**
* List of languages available
* @type {string[]}
*/
let languages = [];
/**
* List of scheduled days available
* @type {string[]}
*/
let scheduledays = []
/**
* Fill soundbank table body with values
* @param {SoundBank[]} vv values to fill
*/
function fill_soundbanktablebody(vv) {
$('#soundbanktablebody').empty();
if (!Array.isArray(vv) || vv.length === 0) return;
vv.forEach(item => {
const row = `<tr>
<td>${item.index}</td>
<td>${item.description}</td>
<td>${item.tag}</td>
<td>${item.category}</td>
<td>${item.language}</td>
<td>${item.voiceType}</td>
<td>${item.path}</td>
</tr>`;
$('#soundbanktablebody').append(row);
let $addedrow = $('#soundbanktablebody tr:last');
$addedrow.on('click', function () {
if (selectedsoundrow) {
selectedsoundrow.find('td').css('background-color', '');
if (selectedsoundrow.is($(this))) {
selectedsoundrow = null;
$('#btnRemove').prop('disabled', true);
$('#btnEdit').prop('disabled', true);
return;
}
}
$(this).find('td').css('background-color', '#ffeeba');
selectedsoundrow = $(this);
$('#btnRemove').prop('disabled', false);
$('#btnEdit').prop('disabled', false);
});
});
$('#tablesize').text("Table Size: " + vv.length);
}
/**
* Fill messagebank table body with values
* @param {MessageBank[]} vv values to fill
*/
function fill_messagebanktablebody(vv) {
$('#messagebanktablebody').empty();
if (!Array.isArray(vv) || vv.length === 0) return;
vv.forEach(item => {
const row = `<tr>
<td>${item.index}</td>
<td>${item.description}</td>
<td>${item.language}</td>
<td>${item.aNN_ID}</td>
<td>${item.voice_Type}</td>
<td>${item.message_Detail}</td>
<td>${item.message_TAGS}</td>
</tr>`;
$('#messagebanktablebody').append(row);
let $addedrow = $('#messagebanktablebody tr:last');
$addedrow.click(function () {
if (selectedmessagerow) {
selectedmessagerow.find('td').css('background-color', '');
if (selectedmessagerow.is($(this))) {
selectedmessagerow = null;
$('#btnRemove').prop('disabled', true);
$('#btnEdit').prop('disabled', true);
return;
}
}
$addedrow.find('td').css('background-color', '#ffeeba');
selectedmessagerow = $addedrow;
$('#btnRemove').prop('disabled', false);
$('#btnEdit').prop('disabled', false);
});
});
console.log("loaded " + vv.length + " messagebank items");
}
/**
* Fill languagebank table body with values
* @param {LanguageBank[]} vv values to fill
*/
function fill_languagebanktablebody(vv) {
$('#languagebanktablebody').empty();
if (!Array.isArray(vv) || vv.length === 0) return;
vv.forEach(item => {
const row = `<tr>
<td>${item.index}</td>
<td>${item.tag}</td>
<td>${item.language}</td>
</tr>`;
$('#languagebanktablebody').append(row);
let $addedrow = $('#languagebanktablebody tr:last');
$addedrow.click(function () {
if (selectedlanguagerow) {
selectedlanguagerow.find('td').css('background-color', '');
if (selectedlanguagerow.is($(this))) {
selectedlanguagerow = null;
$('#btnRemove').prop('disabled', true);
$('#btnEdit').prop('disabled', true);
return;
}
}
$addedrow.find('td').css('background-color', '#ffeeba');
selectedlanguagerow = $addedrow;
$('#btnRemove').prop('disabled', false);
$('#btnEdit').prop('disabled', false);
});
});
console.log("loaded " + vv.length + " languagebank items");
}
/**
* Fill schedulebank table body with values
* @param {ScheduleBank[]} vv values to fill
*/
function fill_schedulebanktablebody(vv) {
$('#schedulebanktablebody').empty();
if (!Array.isArray(vv) || vv.length === 0) return;
vv.forEach(item => {
const row = `<tr>
<td>${item.index}</td>
<td>${item.description}</td>
<td>${item.day}</td>
<td>${item.time}</td>
<td>${item.soundpath}</td>
<td>${item.repeat}</td>
<td>${item.enable}</td>
<td>${item.broadcastZones}</td>
<td>${item.language}</td>
</tr>`;
$('#schedulebanktablebody').append(row);
let $addedrow = $('#schedulebanktablebody tr:last');
$addedrow.click(function () {
if (selectedschedulerow) {
selectedschedulerow.find('td').css('background-color', '');
if (selectedschedulerow.is($(this))) {
selectedschedulerow = null;
$('#btnRemove').prop('disabled', true);
$('#btnEdit').prop('disabled', true);
return;
}
}
$addedrow.find('td').css('background-color', '#ffeeba');
selectedschedulerow = $addedrow;
$('#btnRemove').prop('disabled', false);
$('#btnEdit').prop('disabled', false);
});
});
console.log("loaded " + vv.length + " schedulebank items");
}
/**
* Fill log table body with values
* @param {Log[]} vv values to fill
*/
function fill_logtablebody(vv) {
$('#logtablebody').empty();
if (!Array.isArray(vv) || vv.length === 0) return;
vv.forEach(item => {
const row = `<tr>
<td>${item.index}</td>
<td>${item.datenya}</td>
<td>${item.timenya}</td>
<td>${item.machine}</td>
<td>${item.description}</td>
</tr>`;
$('#logtablebody').append(row);
});
console.log("loaded " + vv.length + " log items");
}
/**
* WebSocket connection
* @type {WebSocket}
*/
let ws = null;
/**
* Send a command to the WebSocket server.
* @param {String} command command to send
* @param {String} data data to send
*/
function sendCommand(command, data) {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ command, data }));
} else {
console.error('WebSocket is not open');
}
}
/**
* Fetch API helper function
* @param {string} endpoint Endpoint URL
* @param {string} method Method (GET, POST, etc.)
* @param {Object} headers Headers to include in the request
* @param {Object} body Body of the request
* @param {Function} cbOK Callback function for successful response
* @param {Function} cbError Callback function for error response
*/
function fetchAPI(endpoint, method, headers = {}, body = null, cbOK, cbError) {
let url = window.location.origin + "/api/" + endpoint;
let options = {
method: method,
headers: headers
}
if (body !== null) {
options.body = JSON.stringify(body);
if (!options.headers['Content-Type']) {
options.headers['Content-Type'] = 'application/json';
}
}
console.log("About to fetch from " + url + " with options", options);
fetch(url, options)
.then(response => {
console.log("fetchAPI: received response", response);
if (!response.ok) {
throw new Error('Network response was not ok ' + response.statusText);
}
return response.json();
})
.then(data => {
console.log("fetchAPI: received data", data);
cbOK(data);
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
cbError(error);
});
}
/**
* Reload sound bank from server
* @param {String} APIURL API URL endpoint
*/
function reloadSoundBank(APIURL) {
soundbankdata = [];
console.log("reloadSoundBank: fetching from " + APIURL + "List");
fetchAPI(APIURL + "List", "GET", {}, null, (okdata) => {
console.log("reloadSoundBank: received data", okdata);
if (Array.isArray(okdata)) {
soundbankdata = okdata;
selectedsoundrow = null;
fill_soundbanktablebody(soundbankdata);
}
}, (errdata) => {
alert("Error loading soundbank: " + errdata.message);
});
}
/**
* Reload message bank from server
* @param {string} APIURL API URL endpoint
*/
function reloadMessageBank(APIURL) {
messagebankdata = [];
fetchAPI(APIURL + "List", "GET", {}, null, (okdata) => {
if (Array.isArray(okdata)) {
messagebankdata = okdata;
selectedmessagerow = null;
fill_messagebanktablebody(messagebankdata);
}
}, (errdata) => {
alert("Error loading messagebank: " + errdata.message);
});
}
/**
* Reload language bank from server
* @param {string} APIURL API URL endpoint
*/
function reloadLanguageBank(APIURL) {
languagebankdata = [];
fetchAPI(APIURL + "List", "GET", {}, null, (okdata) => {
if (Array.isArray(okdata)) {
languagebankdata = okdata;
selectedlanguagerow = null;
fill_languagebanktablebody(languagebankdata);
}
}, (errdata) => {
alert("Error loading languagebank: " + errdata.message);
});
}
/**
* Reload timer bank from server
* @param {string} APIURL API URL endpoint
*/
function reloadTimerBank(APIURL) {
schedulebankdata = [];
fetchAPI(APIURL + "List", "GET", {}, null, (okdata) => {
if (Array.isArray(okdata)) {
schedulebankdata = okdata.data;
selectedschedulerow = null;
fill_schedulebanktablebody(schedulebankdata);
}
}, (errdata) => {
alert("Error loading schedulebank: " + errdata.message);
});
}
/**
* Reload logs from server with date and filter
* @param {String} APIURL API URL endpoint
* @param {String} date date in format dd/MM/yyyy
* @param {String} filter log filter text
*/
function reloadLogs(APIURL, date, filter) {
fetchAPI(APIURL + "List/" + date + "/" + filter, "GET", {}, null, (okdata) => {
$('#logcontent').val(okdata.data);
}, (errdata) => {
alert("Error loading logs: " + errdata.message);
});
}
/**
* Reload soundbank files from server
* @param {String} APIURL API URL endpoint (default "SoundBank/")
*/
function regetSoundbankFiles(APIURL = "SoundBank/") {
soundbankfiles = [];
fetchAPI(APIURL + "ListFiles", "GET", {}, null, (okdata) => {
// okdata is a string contains elements separated by semicolon ;
if (Array.isArray(okdata)) {
soundbankfiles = okdata.filter(item => item.trim().length > 0);
//console.log("Loaded " + soundbankfiles.length + " sound files : " + soundbankfiles.join(", ") );
// refill select2results
select2results.results = soundbankfiles.map((item, index) => ({ id: index + 1, text: item }));
} else console.log("regetSoundbankFiles: okdata is not array");
}, (errdata) => {
alert("Error loading soundbank files: " + errdata.message);
});
}
/**
* Reload voice types from server
*/
function getVoiceTypes() {
voiceTypes = [];
fetchAPI("VoiceType", "GET", {}, null, (okdata) => {
// okdata is a string contains elements separated by semicolon ;
if (Array.isArray(okdata)) {
voiceTypes = okdata.filter(item => item.trim().length > 0);
//console.log("Loaded " + voiceTypes.length + " voice types : " + voiceTypes.join(", "));
} else console.log("getVoiceTypes: okdata is not array");
}, (errdata) => {
alert("Error loading voice types: " + errdata.message);
});
}
/**
* Reload categories from server
*/
function getCategories() {
categories = [];
fetchAPI("Category", "GET", {}, null, (okdata) => {
// okdata is a string contains elements separated by semicolon ;
if (Array.isArray(okdata)) {
categories = okdata.filter(item => item.trim().length > 0);
//console.log("Loaded " + categories.length + " categories : " + categories.join(", "));
} else console.log("getCategories: okdata is not array");
}, (errdata) => {
alert("Error loading categories: " + errdata.message);
});
}
/**
* Reload languages from server
*/
function getLanguages() {
languages = [];
fetchAPI("Language", "GET", {}, null, (okdata) => {
// okdata is a string contains elements separated by semicolon ;
if (Array.isArray(okdata)) {
languages = okdata.filter(item => item.trim().length > 0);
//console.log("Loaded " + languages.length + " languages : " + languages.join(", ") );
} else console.log("getLanguages: okdata is not array");
}, (errdata) => {
alert("Error loading languages: " + errdata.message);
});
}
/**
* Reload scheduled days from server
*/
function getScheduledDays() {
scheduledays = [];
fetchAPI("ScheduleDay", "GET", {}, null, (okdata) => {
// okdata is a string contains elements separated by semicolon ;
if (Array.isArray(okdata)) {
scheduledays = okdata.filter(item => item.trim().length > 0);
//console.log("Loaded " + scheduledays.length + " scheduled days : " + scheduledays.join(", ") );
} else console.log("getScheduledDays: okdata is not array");
}, (errdata) => {
alert("Error loading scheduled days: " + errdata.message);
});
}
/**
* Export mechanism to XLSX file
* @param {String} APIURL API URL endpoint
* @param {String} filename target filename
*/
function DoExport(APIURL, filename) {
// send GET request to APIURL + "ExportXLSX"
// reply Content-Type is application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
// reply Content-Disposition: attachment; filename=filename
// Use fetch to download the XLSX file as a blob and trigger download
fetch("/api/" + APIURL + "ExportXLSX", {
method: "GET",
headers: {}
})
.then(response => {
if (!response.ok) throw new Error('Network response was not ok ' + response.statusText);
return response.blob();
})
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
})
.catch(error => {
alert("Error export to " + filename + ": " + error.message);
});
return; // prevent the rest of the function from running
}
/**
* Import mechanism from XLSX file
* @param {String} APIURL API URL endpoint
* @param {Function<Object>} cbOK function that accept object data
* @param {Function<Error>} cbError function that accept error object
*/
function DoImport(APIURL, cbOK, cbError) {
// Open file selection dialog that accepts only .xlsx files
// then upload to server using fetchAPI at "api/ImportXLSX" with POST method
let fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = '.xlsx';
fileInput.onchange = e => {
let file = e.target.files[0];
if (file) {
let formData = new FormData();
formData.append('file', file);
fetch("/api/" + APIURL + "ImportXLSX", { method: 'POST', body: formData })
.then(response => {
if (!response.ok) { throw new Error('Network response was not ok ' + response.statusText); }
return response.json();
})
.then(data => {
cbOK(data);
})
.catch(error => {
cbError(error);
});
} else {
cbError(new Error("No file selected"));
}
};
fileInput.click();
fileInput.remove();
}
/**
* App entry point
*/
$(document).ready(function () {
document.title = "Automatic Announcement System"
$('#onlineindicator').attr('src', '/assets/img/red_circle.png');
getVoiceTypes();
getCategories();
getLanguages();
getScheduledDays();
regetSoundbankFiles();
// Initialize WebSocket connection
ws = new WebSocket(window.location.pathname + '/ws');
ws.onopen = () => {
console.log('WebSocket connection established');
$('#onlineindicator').attr('src', '/assets/img/green_circle.png');
};
ws.onmessage = (event) => {
let rep = JSON.parse(event.data);
let cmd = rep.reply
let data = rep.data;
if (cmd && cmd.length > 0) {
switch (cmd) {
case "getCPUStatus":
$('#cpustatus').text("CPU Usage: " + data)
break;
case "getMemoryStatus":
$('#ramstatus').text("Memory Usage: " + data)
break;
case "getDiskStatus":
$('#diskstatus').text("Disk Usage: " + data)
break;
case "getNetworkStatus":
$('#networkstatus').text("Network Usage: " + data)
break;
case "getSystemTime":
$('#datetimetext').text(data)
break;
}
}
};
ws.onclose = () => {
console.log('WebSocket connection closed');
$('#onlineindicator').attr('src', '/assets/img/red_circle.png');
};
// ws.onerror = (error) => {
// console.error('WebSocket error:', error);
// };
setInterval(() => {
sendCommand("getCPUStatus", "")
sendCommand("getMemoryStatus", "")
sendCommand("getDiskStatus", "")
sendCommand("getNetworkStatus", "")
sendCommand("getSystemTime", "")
}, 1000)
let sidemenu = new bootstrap.Offcanvas('#offcanvas-menu');
$('#showmenu').click(() => { sidemenu.show(); })
$('#homelink').click(() => {
sidemenu.hide();
$('#content').load('overview.html', function (response, status, xhr) {
if (status === "success") {
console.log("Overview content loaded successfully");
}
});
});
$('#soundbanklink').click(() => {
sidemenu.hide();
$('#content').load('soundbank.html', function (response, status, xhr) {
if (status === "success") {
console.log("Soundbank content loaded successfully");
// initialize first state of buttons and text input
$('#soundbanktablebody').empty();
selectedsoundrow = null;
let $btnClear = $('#btnClear');
let $btnAdd = $('#btnAdd');
let $btnRemove = $('#btnRemove');
let $btnEdit = $('#btnEdit');
let $btnExport = $('#btnExport');
let $btnImport = $('#btnImport');
let $modal = $('#soundbankmodal');
$btnRemove.prop('disabled', true);
$btnEdit.prop('disabled', true);
let APIURL = "SoundBank/";
reloadSoundBank(APIURL);
$btnClear.click(() => {
if (confirm(`Are you sure want to clear Soundbank ? This procedure is not reversible`)) {
fetchAPI(APIURL + "List", "DELETE", {}, null, (okdata) => {
alert("Success clear soundbank" + okdata.message);
soundbankdata = []
selectedsoundrow = null;
fill_soundbanktablebody(soundbankdata);
}, (errdata) => {
alert("Error clear soundbank: " + errdata.message);
});
}
});
$btnAdd.click(() => {
$('.js-example-basic-single').select2({
placeholder: 'Select a sound file',
closeOnSelect: true,
data: select2results,
});
$modal.modal('show');
// event on Click save button
$modal.off('click.soundbanksave').on('click.soundbanksave', '#soundbanksave', function () {
$modal.modal('hide');
});
// event on Click close button
$modal.off('click.soundbankclose').on('click.soundbankclose', '#soundbankclose', function () {
$modal.modal('hide');
});
});
$btnRemove.click(() => {
if (selectedsoundrow) {
let cells = selectedsoundrow.find('td');
/** @type {SoundBank} */
let sb = {
index: cells.eq(0).text(),
description: cells.eq(1).text(),
tag: cells.eq(2).text(),
category: cells.eq(3).text(),
language: cells.eq(4).text(),
voiceType: cells.eq(5).text(),
path: cells.eq(6).text()
}
if (confirm(`Are you sure to delete soundbank [${sb.index}] Description=${sb.description} Tag=${sb.tag}?`)) {
fetchAPI(APIURL + "DeleteByIndex/" + sb.index, "DELETE", {}, null, (okdata) => {
alert("Success delete soundbank" + okdata.message);
soundbankdata = soundbankdata.filter(item => item.index !== sb.index);
selectedsoundrow = null;
fill_soundbanktablebody(soundbankdata);
}, (errdata) => {
alert("Error delete soundbank: " + errdata.message);
});
}
}
});
$btnEdit.click(() => {
if (selectedsoundrow) {
let cells = selectedsoundrow.find('td');
/** @type {SoundBank} */
let sb = {
index: cells.eq(0).text(),
description: cells.eq(1).text(),
tag: cells.eq(2).text(),
category: cells.eq(3).text(),
language: cells.eq(4).text(),
voiceType: cells.eq(5).text(),
path: cells.eq(6).text()
}
if (confirm(`Are you sure to edit soundbank [${sb.index}] Description=${sb.description} Tag=${sb.tag}?`)) {
$modal.modal('show');
$modal.off('hidden.bs.modal').on('hidden.bs.modal', function () {
const desc = $('#description').val();
console.log('Description input value:', desc);
// You can use desc here (e.g., send to server)
});
}
}
});
$btnExport.click(() => {
DoExport(APIURL, "soundbank.xlsx");
});
$btnImport.click(() => {
DoImport(APIURL, (okdata) => {
reloadSoundBank(APIURL);
}, (errdata) => {
alert("Error importing soundbank from XLSX: " + errdata.message);
});
});
} else {
console.error("Error loading soundbank content:", xhr.status, xhr.statusText);
}
});
})
$('#messagebanklink').click(() => {
sidemenu.hide();
$('#content').load('messagebank.html', function (response, status, xhr) {
if (status === "success") {
console.log("Messagebank content loaded successfully");
// initialize first state of buttons and text input
$('#messagebanktablebody').empty();
selectedmessagerow = null;
let $btnClear = $('#btnClear');
let $btnAdd = $('#btnAdd');
let $btnRemove = $('#btnRemove');
let $btnEdit = $('#btnEdit');
let $btnExport = $('#btnExport');
let $btnImport = $('#btnImport');
$btnRemove.prop('disabled', true);
$btnEdit.prop('disabled', true);
let APIURL = "MessageBank/";
reloadMessageBank(APIURL);
$btnClear.click(() => {
if (confirm(`Are you sure want to clear Messagebank ? This procedure is not reversible`)) {
fetchAPI(APIURL + "List", "DELETE", {}, null, (okdata) => {
alert("Success clear messagebank" + okdata.message);
messagebankdata = []
selectedmessagerow = null;
fill_messagebanktablebody(messagebankdata);
}, (errdata) => {
alert("Error clear messagebank: " + errdata.message);
});
}
});
$btnAdd.click(() => {
let $modal = $('#messagebankmodal');
$modal.modal('show');
$modal.off('click.messagebanksave').on('click.messagebanksave', '#messagebanksave', function () {
const index = $('#messageindex').val();
const description = $('#messagedescription').val();
const language = $('#messagelanguage').val();
const ann_id = parseInt($('#messageannid').val());
const voice_type = $('#messagevoicetype').val();
$modal.modal('hide');
});
$modal.off('click.messagebankclose').on('click.messagebankclose', '#messagebankclose', function () {
$modal.modal('hide');
});
});
$btnRemove.click(() => {
if (selectedmessagerow) {
let cells = selectedmessagerow.find('td');
/** @type {MessageBank} */
let mb = {
index: cells.eq(0).text(),
description: cells.eq(1).text(),
language: cells.eq(2).text(),
aNN_ID: parseInt(cells.eq(3).text()),
voice_Type: cells.eq(4).text(),
message_Detail: cells.eq(5).text(),
message_TAGS: cells.eq(6).text()
}
if (confirm(`Are you sure to delete messagebank [${mb.index}] Description=${mb.description}? ANN_ID=${mb.aNN_ID} Language=${mb.language} Voice_Type=${mb.voice_Type} `)) {
fetchAPI(APIURL + "DeleteByIndex/" + mb.index, "DELETE", {}, null, (okdata) => {
alert("Success delete messagebank" + okdata.message);
messagebankdata = messagebankdata.filter(item => item.index !== mb.index);
selectedmessagerow = null;
fill_messagebanktablebody(messagebankdata);
}, (errdata) => {
alert("Error delete messagebank: " + errdata.message);
});
}
}
});
$btnEdit.click(() => {
if (selectedmessagerow) {
let cells = selectedmessagerow.find('td');
/** @type {MessageBank} */
let mb = {
index: cells.eq(0).text(),
description: cells.eq(1).text(),
language: cells.eq(2).text(),
aNN_ID: parseInt(cells.eq(3).text()),
voice_Type: cells.eq(4).text(),
message_Detail: cells.eq(5).text(),
message_TAGS: cells.eq(6).text()
}
if (confirm(`Are you sure to edit messagebank [${mb.index}] Description=${mb.description} ANN_ID=${mb.aNN_ID} Language=${mb.language} Voice_Type=${mb.voice_Type} `)) {
//TODO send edit command
}
}
});
$btnExport.click(() => {
DoExport(APIURL, "messagebank.xlsx");
});
$btnImport.click(() => {
DoImport(APIURL, (okdata) => {
reloadMessageBank(APIURL);
}, (errdata) => {
alert("Error importing messagebank from XLSX: " + errdata.message);
});
});
} else {
console.error("Error loading messagebank content:", xhr.status, xhr.statusText);
}
});
})
$('#languagelink').click(() => {
sidemenu.hide();
$('#content').load('language.html', function (response, status, xhr) {
if (status === "success") {
console.log("Language content loaded successfully");
// initialize first state of buttons and text input
$('#languagebanktablebody').empty();
selectedlanguagerow = null;
let $btnClear = $('#btnClear');
let $btnAdd = $('#btnAdd');
let $btnRemove = $('#btnRemove');
let $btnEdit = $('#btnEdit');
let $btnExport = $('#btnExport');
let $btnImport = $('#btnImport');
$btnRemove.prop('disabled', true);
$btnEdit.prop('disabled', true);
let APIURL = "LanguageBank/";
reloadLanguageBank(APIURL);
$btnClear.click(() => {
if (confirm(`Are you sure want to clear Languagebank ? This procedure is not reversible`)) {
fetchAPI(APIURL + "List", "DELETE", {}, null, (okdata) => {
alert("Success clear languagebank" + okdata.message);
languagebankdata = []
selectedlanguagerow = null;
fill_languagebanktablebody(languagebankdata);
}, (errdata) => {
alert("Error clear languagebank: " + errdata.message);
});
}
});
$btnAdd.click(() => {
// show modal with id 'languagemodal'
let $modal = $('#languagemodal');
$modal.modal('show');
// save button click event
$modal.off('click.languagelinksave').on('click.languagelinksave', '#languagelinksave', function () {
const tag = $('#languagelinktag').val();
const langs = [];
if ($('#langID').is(':checked')) langs.push('INDONESIA');
if ($('#langLocal').is(':checked')) langs.push('LOCAL');
if ($('#langEN').is(':checked')) langs.push('ENGLISH');
if ($('#langARB').is(':checked')) langs.push('ARABIC');
if ($('#langJAP').is(':checked')) langs.push('JAPANESE');
if ($('#langCHI').is(':checked')) langs.push('CHINESE');
if (tag.length === 0) {
alert("Tag cannot be empty");
return;
}
if (langs.length === 0) {
alert("At least one language must be selected");
return;
}
const langString = langs.join(';');
let ll = {
tag: tag,
language: langString
}
fetchAPI(APIURL + "Add", "POST", {}, ll, (okdata) => {
alert("Success add language" + okdata.message);
reloadLanguageBank(APIURL);
}, (errdata) => {
alert("Error add language: " + errdata.message);
});
$modal.modal('hide');
});
// close button click event
$modal.off('click.languagelinkclose').on('click.languagelinkclose', '#languagelinkclose', function () {
$modal.modal('hide');
});
});
$btnRemove.click(() => {
if (selectedlanguagerow) {
let cells = selectedlanguagerow.find('td');
/** @type {Language} */
let ll = {
index: cells.eq(0).text(),
tag: cells.eq(1).text(),
language: cells.eq(2).text()
}
if (confirm(`Are you sure to delete language [${ll.index}] Tag=${ll.tag} Language=${ll.language}?`)) {
fetchAPI(APIURL + "DeleteByIndex/" + ll.index, "DELETE", {}, null, (okdata) => {
alert("Success delete language" + okdata.message);
languagebankdata = languagebankdata.filter(item => item.index !== ll.index);
selectedlanguagerow = null;
fill_languagebanktablebody(languagebankdata);
}, (errdata) => {
alert("Error delete language: " + errdata.message);
});
}
}
});
$btnEdit.click(() => {
if (selectedlanguagerow) {
let cells = selectedlanguagerow.find('td');
/** @type {Language} */
let ll = {
index: cells.eq(0).text(),
tag: cells.eq(1).text(),
language: cells.eq(2).text()
}
if (confirm(`Are you sure to edit language [${ll.index}] Tag=${ll.tag} Language=${ll.language}?`)) {
let $modal = $('#languagemodal');
$modal.find('#languagelinkindex').val(ll.index);
$modal.find('#languagelinktag').val(ll.tag);
let langs = ll.language.split(';');
$modal.find('#langID').prop('checked', langs.includes('INDONESIA'));
$modal.find('#langLocal').prop('checked', langs.includes('LOCAL'));
$modal.find('#langEN').prop('checked', langs.includes('ENGLISH'));
$modal.find('#langARB').prop('checked', langs.includes('ARABIC'));
$modal.find('#langJAP').prop('checked', langs.includes('JAPANESE'));
$modal.find('#langCHI').prop('checked', langs.includes('CHINESE'));
$modal.modal('show');
// save button click event
$modal.off('click.languagelinksave').on('click.languagelinksave', '#languagelinksave', function () {
const tag = $('#languagelinktag').val();
const langs = [];
if ($('#langID').is(':checked')) langs.push('INDONESIA');
if ($('#langLocal').is(':checked')) langs.push('LOCAL');
if ($('#langEN').is(':checked')) langs.push('ENGLISH');
if ($('#langARB').is(':checked')) langs.push('ARABIC');
if ($('#langJAP').is(':checked')) langs.push('JAPANESE');
if ($('#langCHI').is(':checked')) langs.push('CHINESE');
if (tag.length === 0) {
alert("Tag cannot be empty");
return;
}
if (langs.length === 0) {
alert("At least one language must be selected");
return;
}
const langString = langs.join(';');
if (ll.tag === tag && ll.language === langString) {
alert("No changes detected");
$modal.modal('hide');
return;
}
ll.tag = tag;
ll.language = langString;
fetchAPI(APIURL + "UpdateByIndex/" + ll.index, "PATCH", {}, ll, (okdata) => {
alert("Success edit language" + okdata.message);
reloadLanguageBank(APIURL);
}, (errdata) => {
alert("Error edit language: " + errdata.message);
});
$modal.modal('hide');
});
// close button click event
$modal.off('click.languagelinkclose').on('click.languagelinkclose', '#languagelinkclose', function () {
$modal.modal('hide');
});
}
}
});
$btnExport.click(() => {
DoExport(APIURL, "languagebank.xlsx");
});
$btnImport.click(() => {
DoImport(APIURL, (okdata) => {
reloadLanguageBank(APIURL);
}, (errdata) => {
alert("Error importing languagebank from XLSX: " + errdata.message);
});
});
} else {
console.error("Error loading language content:", xhr.status, xhr.statusText);
}
});
})
$('#timerlink').click(() => {
sidemenu.hide();
$('#content').load('timer.html', function (response, status, xhr) {
if (status === "success") {
console.log("Timer content loaded successfully");
// initialize first state of buttons and text input
$('#schedulebanktablebody').empty();
selectedschedulerow = null;
let $btnClear = $('#btnClear');
let $btnAdd = $('#btnAdd');
let $btnEdit = $('#btnEdit');
let $btnRemove = $('#btnRemove');
let $btnExport = $('#btnExport');
let $btnImport = $('#btnImport');
$btnEdit.prop('disabled', true);
$btnRemove.prop('disabled', true);
let APIURL = "ScheduleBank/";
reloadTimerBank(APIURL);
$btnClear.click(() => {
if (confirm(`Are you sure want to clear Timerbank ? This procedure is not reversible`)) {
fetchAPI(APIURL + "List", "DELETE", {}, null, (okdata) => {
alert("Success clear schedulebank" + okdata.message);
schedulebankdata = []
selectedschedulerow = null;
fill_schedulebanktablebody(schedulebankdata);
}, (errdata) => {
alert("Error clear schedulebank: " + errdata.message);
});
}
});
$btnAdd.click(() => {
//TODO form add timer
});
$btnRemove.click(() => {
if (selectedtimerow) {
let cells = selectedtimerow.find('td');
/** @type {ScheduleBank} */
let sr = {
index: cells.eq(0).text(),
description: cells.eq(1).text(),
day: cells.eq(2).text(),
time: cells.eq(3).text(),
soundpath: cells.eq(4).text(),
repeat: cells.eq(5).text(),
enable: cells.eq(6).text(),
broadcastZones: cells.eq(7).text(),
language: cells.eq(8).text()
}
if (confirm(`Are you sure to delete schedule [${sr.index}] Description=${sr.description}?`)) {
fetchAPI(APIURL + "DeleteByIndex/" + sr.index, "DELETE", {}, null, (okdata) => {
alert("Success delete schedule" + okdata.message);
schedulebankdata = schedulebankdata.filter(item => item.index !== sr.index);
selectedtimerow = null;
fill_schedulebanktablebody(schedulebankdata);
}, (errdata) => {
alert("Error delete schedule: " + errdata.message);
});
}
}
});
$btnEdit.click(() => {
if (selectedtimerow) {
let cells = selectedtimerow.find('td');
/** @type {ScheduleBank} */
let sr = {
index: cells.eq(0).text(),
description: cells.eq(1).text(),
day: cells.eq(2).text(),
time: cells.eq(3).text(),
soundpath: cells.eq(4).text(),
repeat: cells.eq(5).text(),
enable: cells.eq(6).text(),
broadcastZones: cells.eq(7).text(),
language: cells.eq(8).text()
}
if (confirm(`Are you sure to edit schedule [${sr.index}] Description=${sr.description}?`)) {
//TODO send edit command
}
}
});
$btnExport.click(() => {
DoExport(APIURL, "schedulebank.xlsx");
});
$btnImport.click(() => {
DoImport(APIURL, (okdata) => {
reloadTimerBank(APIURL);
}, (errdata) => {
alert("Error importing schedulebank from XLSX: " + errdata.message);
});
});
} else {
console.error("Error loading timer content:", xhr.status, xhr.statusText);
}
});
})
$('#loglink').click(() => {
sidemenu.hide();
$('#content').load('log.html', function (response, status, xhr) {
if (status === "success") {
console.log("Log content loaded successfully");
const $logdate = $('#logdate');
const $searchfilter = $('#searchfilter');
let selectedlogdate = "";
let logfilter = "";
let APIURL = "/api/Logs/";
if (!$logdate.val()) {
const today = new Date();
const dd = String(today.getDate()).padStart(2, '0');
const mm = String(today.getMonth() + 1).padStart(2, '0');
const yyyy = today.getFullYear();
$logdate.val(`${yyyy}-${mm}-${dd}`);
selectedlogdate = `${dd}/${mm}/${yyyy}`;
}
$logdate.off('change').on('change', function () {
const selected = $(this).val();
if (selected) {
const [year, month, day] = selected.split('-');
selectedlogdate = `${day}/${month}/${year}`;
reloadLogs(APIURL, selectedlogdate, logfilter);
}
});
$searchfilter.off('input').on('input', function () {
logfilter = $(this).val();
reloadLogs(APIURL, selectedlogdate, logfilter);
});
} else {
console.error("Error loading log content:", xhr.status, xhr.statusText);
}
});
})
$('#settinglink').click(() => {
sidemenu.hide();
$('#content').load('setting.html', function (response, status, xhr) {
if (status === "success") {
console.log("Setting content loaded successfully");
//sendCommand("getSetting", "");
} else {
console.error("Error loading setting content:", xhr.status, xhr.statusText);
}
});
})
$('#logoutlink').click(() => {
window.location.href = "login.html"
})
/**
* Create log Request Data
* @param {String} logdate in format dd/mm/yyyy
* @param {String} logfilter
* @returns JSON string of log Request data
*/
function logRequstData(logdate, logfilter) {
if (logdate && logdate.length > 0) {
const dateRegex = /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/\d{4}$/;
if (dateRegex.test(logdate)) {
// logdate is valid
return JSON.stringify({
date: logdate,
filter: logfilter
})
}
}
return ""
}
});