Files
AAS_NewGeneration/html/webpage/assets/js/messagebank.js
2026-02-04 16:41:13 +07:00

475 lines
20 KiB
JavaScript

/**
* Currently selected messagebank row in the table
* @type {JQuery<HTMLElement>|null}
*/
window.selectedmessagerow = null;
dtMessageBank = null;
/**
* Fill messagebank table body with values
* @param {MessageBank[]} vv values to fill
*/
function fill_messagebanktablebody(vv) {
dtMessageBank.clear();
if (!Array.isArray(vv) || vv.length === 0) return;
dtMessageBank.rows.add(vv);
dtMessageBank.draw();
$('#messagebanktable tbody').off('click').on('click', 'tr', function () {
// if no data
if (!dtMessageBank) return;
// if user click an empty row
if (!dtMessageBank.data().any()) return;
const selected = dtMessageBank.row(this)
// toggle behaviour - unselect if already selected
if ($(this).hasClass('row-selected')) {
$(this).removeClass('row-selected').find('td').css('background-color', '');
window.selectedmessagerow = null;
$('#btnRemove').prop('disabled', true);
$('#btnEdit').prop('disabled', true);
return;
}
// unselect previously selected row
$('#messagebanktable tbody tr.row-selected').removeClass('row-selected').find('td').css('background-color', '');
$(this).addClass('row-selected').find('td').css('background-color', '#ffeeba');
window.selectedmessagerow = selected.data();
$('#btnRemove').prop('disabled', false);
$('#btnEdit').prop('disabled', false);
})
$('#tablesize').text("Table Size: " + vv.length);
}
/**
* @typedef {Object} MessageBank
* @property {string} Description - Description of the messagebank entry
* @property {string} Language - Language code
* @property {number} ANN_ID - ANN ID (1-100)
* @property {string} Voice_Type - Voice type
* @property {string} Message_Detail - Detailed message constructed from categories and phrases
* @property {string} Message_TAGS - Tags associated with the message
*/
$(document).ready(function () {
console.log("messagebank.js loaded");
window.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/";
let $findmessage = $('#findmessage');
if (dtMessageBank === null) {
dtMessageBank = new DataTable('#messagebanktable', {
data: [],
pageLength: 25,
columns: [
{ title: "Index", data: "index" },
{ title: "Description", data: "description" },
{ title: "Language", data: "language" },
{ title: "ANN ID", data: "aNN_ID" },
{ title: "Type", data: "voice_Type" },
{ title: "Message Details", data: "message_Detail" },
{ title: "Message TAGS", data: "message_TAGS" }
]
});
}
// modal for add / edit messagebank
let $modal = $('#messagebankmodal');
// text input, disabled by default
let $messageindex = $modal.find('#messageindex');
// text input
let $messagedescription = $modal.find('#messagedescription');
// select input, options loaded from languages[]
let $messagelanguage = $modal.find('#messagelanguage');
// number input from 1 to 100
let $messageannid = $modal.find('#messageannid');
// select input, options loaded from voiceTypes[]
let $messagevoicetype = $modal.find('#messagevoicetype');
// list <ul> of available categories and phrases
let $messageavailablevariables = $modal.find('#messageavailablevariables');
// list <ul> of selected categories and phrases
let $messageselectedvariables = $modal.find('#messageselectedvariables');
// for clearing messageselectedvariables
let $btnclearlist = $modal.find('#btnclearlist');
// for removing selected item from messageselectedvariables
let $btnremovefromlist = $modal.find('#btnremovefromlist');
// for adding selected item from messageavailablevariables to messageselectedvariables
let $btnaddtolist = $modal.find('#btnaddtolist');
/**
* Create <option> element
* @param {string} value value assigned to this <option>
* @param {string} text text assigned to this <option>
* @param {string} title text displayed when mouse hover on this <option>
* @returns {JQuery<HTMLOptionElement>} jQuery object representing the created <option> element
*/
function create_option(value, text, title) {
return $('<option>', { value: value, text: text, title: title });
}
/**
* Refill messageavailablevariables options from categories[]
* and soundbankdata with category "Phrase" if messagelanguage and messagevoicetype are selected
* @param {Function} cbLoaded - callback function when phrases are loaded
*/
function refill_messageavailablevariables(cbLoaded) {
$messageavailablevariables.empty();
categories.forEach(cat => {
if ("Phrase" === cat) return; // skip Phrase category
if ("Airline_Code" === cat) cat = "Flight_Number"; // revisi 15012026 karena inconsistensi penamaan tag
if ("Gate" === cat) cat = "GateNumber"; // revisi 03202026 karena inconsistensi penamaan tag
let displayCat = `[${cat}]`.toUpperCase();
$messageavailablevariables.append(create_option(displayCat, displayCat, displayCat));
});
// tambah [ETAD], [BCB] revisi 19012026
$messageavailablevariables.append(create_option('[ETAD]', '[ETAD]', '[ETAD]'));
$messageavailablevariables.append(create_option('[BCB]', '[BCB]', '[BCB]'));
let lang = $messagelanguage.val();
let vt = $messagevoicetype.val();
if (lang && lang.length > 0 && vt && vt.length > 0) {
fetchAPI(`SoundBank/GetPhrases/${lang}/${vt}`, "GET", {}, null, (okdata) => {
if (Array.isArray(okdata) && okdata.length > 0) {
console.log(`Loaded ${okdata.length} phrases from soundbank for language=${lang} and voiceType=${vt}`);
//console.log(JSON.stringify(okdata));
okdata.forEach(sb => {
if (sb.description && sb.description.length > 0) {
let v1 = sb.tag.toUpperCase();
let t1 = sb.description + ` [${v1}]`;
let t2 = sb.description;
$messageavailablevariables.append(create_option(v1, t1, t2));
}
});
if (cbLoaded && typeof cbLoaded === 'function') {
cbLoaded();
}
}
}, (errdata) => {
//alert("Error loading phrases from soundbank : " + errdata.message);
if (cbLoaded && typeof cbLoaded === 'function') {
cbLoaded();
}
});
} else {
if (cbLoaded && typeof cbLoaded === 'function') {
cbLoaded();
}
}
}
/**
* Get data from modal inputs and return as MessageBank object
* @returns {MessageBank} messagebank object or null if validation fails
*/
function GetDataFromModal() {
let description = $messagedescription.val().trim();
let language = $messagelanguage.val();
let annid = parseInt($messageannid.val());
let voicetype = $messagevoicetype.val();
let messagedetail = "";
let messagetags = "";
// iterate messageselectedvariables children
$messageselectedvariables.children().each(function () {
// text got from title
// value got from value
let text = $(this).prop('title').trim();
let value = $(this).val().trim();
console.log('selected text:' + text + ', value:' + value);
if (text.length > 0) {
if (value.length > 0) {
messagetags += (messagetags.length > 0 ? " " : "") + value;
messagedetail += (messagedetail.length > 0 ? " " : "") + text;
}
}
});
if (description.length === 0) {
alert("Description cannot be empty");
return null;
}
if (!language) {
alert("Language cannot be empty");
return null;
}
if (isNaN(annid) || annid < 1 || annid > 100) {
alert("ANN_ID must be a number between 1 and 100");
return null;
}
if (!voicetype) {
alert("Voice Type cannot be empty");
return null;
}
if (messagedetail.length === 0 || messagetags.length === 0) {
alert("Message haven't been constructed, please add categories and phrases");
return null;
}
let mb = {
Description: description,
Language: language,
ANN_ID: annid,
Voice_Type: voicetype,
Message_Detail: messagedetail,
Message_TAGS: messagetags
};
console.log("Constructed MessageBank object:", mb);
return mb;
}
/**
* Clear message modal to default state
*/
function clearMessageModal() {
$messageindex.val('').prop('disabled', true);
$messagedescription.val('').prop('disabled', false);
// fill messagelanguage options from languages[]
$messagelanguage.empty().prop('disabled', false);
window.languages.forEach(lang => {
$messagelanguage.append(new Option(lang, lang));
});
$messagelanguage.val(null).prop('disabled', false);
$messagelanguage.on('change', function () {
refill_messageavailablevariables();
});
// set default annid to 1
$messageannid.val(1).prop('disabled', false);
// fill messagevoicetype options from voiceTypes[]
$messagevoicetype.empty().prop('disabled', false);
window.voiceTypes.forEach(vt => {
$messagevoicetype.append(new Option(vt, vt));
});
$messagevoicetype.val(null).prop('disabled', false);
$messagevoicetype.on('change', function () {
refill_messageavailablevariables();
});
refill_messageavailablevariables();
$messageselectedvariables.empty();
// event on btnclearlist
$btnclearlist.off('click').on('click', function () {
if ($messageselectedvariables.children().length > 0) {
if (confirm("Are you sure want to clear selected variables list?")) {
$messageselectedvariables.empty();
}
}
});
// event on btnremovefromlist
$btnremovefromlist.off('click').on('click', function () {
let $selected = $messageselectedvariables.find('option:selected');
if ($selected.length > 0) {
$selected.remove();
}
});
// event on btnaddtolist
$btnaddtolist.off('click').on('click', function () {
let $selected = $messageavailablevariables.find('option:selected');
if ($selected.length > 0) {
$selected.each(function () {
$messageselectedvariables.append($(this).clone());
});
}
});
}
// $findmessage.on('input', function () {
// let searchTerm = $findmessage.val().toLowerCase();
// if (searchTerm.length > 0) {
// window.selectedmessagerow = null;
// let filtered = window.messagebankdata.filter(item => item.description.toLowerCase().includes(searchTerm) || item.message_Detail.toLowerCase().includes(searchTerm) || item.message_TAGS.toLowerCase().includes(searchTerm));
// fill_messagebanktablebody(filtered);
// } else {
// window.selectedmessagerow = null;
// fill_messagebanktablebody(window.messagebankdata);
// }
// });
reloadMessageBank(APIURL, () => fill_messagebanktablebody(window.messagebankdata));
$btnClear.click(() => {
DoClear(APIURL, "Messagebank", (okdata) => {
reloadMessageBank(APIURL, () => fill_messagebanktablebody(window.messagebankdata));
alert("Success clear messagebank : " + okdata.message);
}, (errdata) => {
alert("Error clear messagebank : " + errdata.message);
});
});
$btnAdd.click(() => {
$modal.modal('show');
clearMessageModal();
$('#closemodalbutton').off('click').on('click', function () {
console.log('Close button clicked')
$modal.modal('hide');
});
$('#savemodalbutton').off('click').on('click', function () {
console.log('Save button clicked')
let mb = GetDataFromModal();
if (!mb) {
return;
}
// send to server using fetchAPI
fetchAPI(APIURL + "Add", "POST", {}, mb, (okdata) => {
reloadMessageBank(APIURL, () => fill_messagebanktablebody(window.messagebankdata));
alert("Success add new messagebank : " + okdata.message);
}, (errdata) => {
alert("Error add new messagebank : " + errdata.message);
});
$modal.modal('hide');
});
});
$btnRemove.click(() => {
if (window.selectedmessagerow) {
/** @type {MessageBank} */
let mb = {
index: window.selectedmessagerow.index,
description: window.selectedmessagerow.description,
language: window.selectedmessagerow.language,
aNN_ID: window.selectedmessagerow.aNN_ID,
voice_Type: window.selectedmessagerow.voice_Type,
message_Detail: window.selectedmessagerow.message_Detail,
message_TAGS: window.selectedmessagerow.message_TAGS
}
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) => {
reloadMessageBank(APIURL, () => fill_messagebanktablebody(window.messagebankdata));
alert("Success delete messagebank : " + okdata.message);
}, (errdata) => {
alert("Error delete messagebank : " + errdata.message);
});
}
}
});
$btnEdit.click(() => {
if (window.selectedmessagerow) {
/** @type {MessageBank} */
let mb = {
index: window.selectedmessagerow.index,
description: window.selectedmessagerow.description,
language: window.selectedmessagerow.language,
aNN_ID: window.selectedmessagerow.aNN_ID,
voice_Type: window.selectedmessagerow.voice_Type,
message_Detail: window.selectedmessagerow.message_Detail,
message_TAGS: window.selectedmessagerow.message_TAGS
}
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} `)) {
$modal.modal('show');
clearMessageModal();
// Fill modal fields with selected messagebank data
$messageindex.val(mb.index).prop('disabled', true);
// Edit mode cant change description, language, voicetype, annid
$messagedescription.val(mb.description).prop('disabled', true);
$messagelanguage.val(mb.language).prop('disabled', true);
$messagevoicetype.val(mb.voice_Type).prop('disabled', true);
$messageannid.val(mb.aNN_ID).prop('disabled', true);
// Refill message available variables
refill_messageavailablevariables(() => {
// Fill messageselectedvariables from message_Detail and message_TAGS
$messageselectedvariables.empty();
if (mb.message_Detail && mb.message_Detail.length > 0) {
if (mb.message_TAGS && mb.message_TAGS.length > 0) {
let tags = mb.message_TAGS.split(" ");
tags.forEach((tag, idx) => {
//console.log(`Restoring tag[${idx}]: ${tag}`);
let tagLower = tag.toLowerCase();
let isfound = false;
if (tagLower === "[airline_code]") {
tagLower = "[flight_number]";
}
// revisi 03022026 karena malah bikin kacau di semi auto
// if (tagLower === "[gatenumber]") {
// tagLower = "[gate]";
// }
// find <option> in messageavailablevariables with value=tag
$messageavailablevariables.find('option').each(function () {
let valx = $(this).val().toLowerCase();
//console.log(`Available option value: ${valx}`);
if (valx === tagLower) {
isfound = true;
//console.log(`Found matching option for tag: ${tag}`);
$messageselectedvariables.append($(this).clone());
}
});
// if (isfound) {
// console.log(`Appended tag to selected variables: ${tag}`);
// } else {
// console.log(`Tag not found in available variables: ${tag}`);
// }
});
}
}
});
// Save button event
$('#savemodalbutton').off('click').on('click', function () {
console.log('Save button clicked')
let mbUpdate = GetDataFromModal();
if (!mbUpdate) {
return;
}
fetchAPI(APIURL + "UpdateByIndex/" + mb.index, "PATCH", {}, mbUpdate, (okdata) => {
reloadMessageBank(APIURL, () => fill_messagebanktablebody(window.messagebankdata));
alert("Success edit messagebank : " + okdata.message);
}, (errdata) => {
alert("Error edit messagebank : " + errdata.message);
});
$modal.modal('hide');
});
$('#closemodalbutton').off('click').on('click', function () {
console.log('Close button clicked')
$modal.modal('hide');
});
}
}
});
$btnExport.click(() => {
DoExport(APIURL, "messagebank.xlsx", {});
});
$btnImport.click(() => {
DoImport(APIURL, (okdata) => {
reloadMessageBank(APIURL, () => fill_messagebanktablebody(window.messagebankdata));
alert("Success import messagebank : " + okdata.message);
}, (errdata) => {
alert("Error importing messagebank from XLSX : " + errdata.message);
});
});
});