commit 18/09/2025
This commit is contained in:
452
html/webpage/assets/js/messagebank.js
Normal file
452
html/webpage/assets/js/messagebank.js
Normal file
@@ -0,0 +1,452 @@
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
});
|
||||
});
|
||||
|
||||
$('#tablesize').text("Table Size: " + vv.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload message bank from server
|
||||
* @param {string} APIURL API URL endpoint, default "MessageBank/"
|
||||
*/
|
||||
function reloadMessageBank(APIURL = "MessageBank/") {
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
console.log("messagebank.js loaded");
|
||||
$('#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/";
|
||||
let $findmessage = $('#findmessage');
|
||||
|
||||
// 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');
|
||||
|
||||
/**
|
||||
* Refill messageavailablevariables options from categories[]
|
||||
* and soundbankdata with category "Phrase" if messagelanguage and messagevoicetype are selected
|
||||
*/
|
||||
function refill_messageavailablevariables() {
|
||||
$messageavailablevariables.empty();
|
||||
categories.forEach(cat => {
|
||||
$messageavailablevariables.append(ListItem(`{${cat}}`));
|
||||
});
|
||||
if ($messagelanguage.val() && $messagevoicetype.val()) {
|
||||
soundbankdata
|
||||
.filter(sb => sb.language.toLowerCase() === $messagelanguage.val().toLowerCase())
|
||||
.filter(sb => sb.voiceType.toLowerCase() === $messagevoicetype.val().toLowerCase())
|
||||
.filter(sb => sb.category.toLowerCase() === "phrase")
|
||||
.forEach(sb => {
|
||||
$messageavailablevariables.append(ListItem(`[${sb.Description}]`));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear message modal to default state
|
||||
*/
|
||||
function clearMessageModal() {
|
||||
$messageindex.val('').prop('disabled', true);
|
||||
$messagedescription.val('');
|
||||
// fill messagelanguage options from languages[]
|
||||
$messagelanguage.empty();
|
||||
languages.forEach(lang => {
|
||||
$messagelanguage.append(new Option(lang, lang));
|
||||
});
|
||||
$messagelanguage.val(null);
|
||||
$messagelanguage.on('change', function () {
|
||||
refill_messageavailablevariables();
|
||||
});
|
||||
// set default annid to 1
|
||||
$messageannid.val(1);
|
||||
// fill messagevoicetype options from voiceTypes[]
|
||||
$messagevoicetype.empty();
|
||||
voiceTypes.forEach(vt => {
|
||||
$messagevoicetype.append(new Option(vt, vt));
|
||||
});
|
||||
$messagevoicetype.val(null);
|
||||
$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) {
|
||||
selectedmessagerow = null;
|
||||
let filtered = messagebankdata.filter(item => item.description.toLowerCase().includes(searchTerm) || item.message_Detail.toLowerCase().includes(searchTerm) || item.message_TAGS.toLowerCase().includes(searchTerm));
|
||||
fill_messagebanktablebody(filtered);
|
||||
} else {
|
||||
selectedmessagerow = null;
|
||||
fill_messagebanktablebody(messagebankdata);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
reloadMessageBank(APIURL);
|
||||
$btnClear.click(() => {
|
||||
DoClear(APIURL, "Messagebank", (okdata) => {
|
||||
reloadMessageBank(APIURL);
|
||||
alert("Success clear messagebank : " + okdata.message);
|
||||
}, (errdata) => {
|
||||
alert("Error clear messagebank : " + errdata.message);
|
||||
});
|
||||
|
||||
});
|
||||
$btnAdd.click(() => {
|
||||
|
||||
$modal.modal('show');
|
||||
clearMessageModal();
|
||||
|
||||
// event on Click save button
|
||||
$modal.off('click.messagebanksave').on('click.messagebanksave', '#messagebanksave', function () {
|
||||
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 () {
|
||||
let val = $(this).text().trim();
|
||||
if (val.length > 0) {
|
||||
if (val.startsWith('[') && val.endsWith(']')) {
|
||||
// categories
|
||||
messagetags += (messagetags.length > 0 ? " " : "") + val;
|
||||
messagedetail += (messagedetail.length > 0 ? " " : "") + val;
|
||||
} else {
|
||||
// phrases
|
||||
// find in soundbankdata by description with specified language and voicetype
|
||||
let sb = soundbankdata
|
||||
.filter(sb => sb.language.toLowerCase() === language.toLowerCase())
|
||||
.filter(sb => sb.voiceType.toLowerCase() === voicetype.toLowerCase())
|
||||
.find(sb => sb.Description.toLowerCase() === val.toLowerCase());
|
||||
if (sb) {
|
||||
messagedetail += (messagedetail.length > 0 ? " " : "") + sb.Description;
|
||||
messagetags += (messagetags.length > 0 ? " " : "") + sb.tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (description.length === 0) {
|
||||
alert("Description cannot be empty");
|
||||
return;
|
||||
}
|
||||
if (!language) {
|
||||
alert("Language cannot be empty");
|
||||
return;
|
||||
}
|
||||
if (isNaN(annid) || annid < 1 || annid > 100) {
|
||||
alert("ANN_ID must be a number between 1 and 100");
|
||||
return;
|
||||
}
|
||||
if (!voicetype) {
|
||||
alert("Voice Type cannot be empty");
|
||||
return;
|
||||
}
|
||||
if (messagedetail.length === 0 || messagetags.length === 0) {
|
||||
alert("Message haven't been constructed, please add categories and phrases");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let mb = {
|
||||
Description: description,
|
||||
Language: language,
|
||||
ANN_ID: annid,
|
||||
Voice_Type: voicetype,
|
||||
Message_Detail: messagedetail,
|
||||
Message_TAGS: messagetags
|
||||
};
|
||||
// send to server using fetchAPI
|
||||
fetchAPI(APIURL + "Add", "POST", mb, null, (okdata) => {
|
||||
reloadMessageBank(APIURL);
|
||||
alert("Success add new messagebank : " + okdata.message);
|
||||
}, (errdata) => {
|
||||
alert("Error add new messagebank : " + errdata.message);
|
||||
});
|
||||
|
||||
$modal.modal('hide');
|
||||
});
|
||||
// event on Click close button
|
||||
$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) => {
|
||||
reloadMessageBank(APIURL);
|
||||
alert("Success delete messagebank : " + okdata.message);
|
||||
}, (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} `)) {
|
||||
$modal.modal('show');
|
||||
|
||||
clearMessageModal();
|
||||
// Fill modal fields with selected messagebank data
|
||||
$messageindex.val(mb.index).prop('disabled', true);
|
||||
$messagedescription.val(mb.description);
|
||||
// Fill messagelanguage options and select current
|
||||
$messagelanguage.empty();
|
||||
languages.forEach(lang => {
|
||||
$messagelanguage.append(new Option(lang, lang));
|
||||
});
|
||||
$messagelanguage.val(mb.language);
|
||||
// Fill messagevoicetype options and select current
|
||||
$messagevoicetype.empty();
|
||||
voiceTypes.forEach(vt => {
|
||||
$messagevoicetype.append(new Option(vt, vt));
|
||||
});
|
||||
$messagevoicetype.val(mb.voice_Type);
|
||||
// Set annid
|
||||
$messageannid.val(mb.aNN_ID);
|
||||
// Refill message available variables
|
||||
refill_messageavailablevariables();
|
||||
// Fill messageselectedvariables from message_Detail and message_TAGS
|
||||
$messageselectedvariables.empty();
|
||||
if (mb.message_Detail) {
|
||||
mb.message_Detail.split(' ').forEach(val => {
|
||||
$messageselectedvariables.append(ListItem(val));
|
||||
});
|
||||
}
|
||||
|
||||
// Save button event
|
||||
$modal.off('click.messagebanksave').on('click.messagebanksave', '#messagebanksave', function () {
|
||||
let description = $messagedescription.val().trim();
|
||||
let language = $messagelanguage.val();
|
||||
let annid = parseInt($messageannid.val());
|
||||
let voicetype = $messagevoicetype.val();
|
||||
let messagedetail = "";
|
||||
let messagetags = "";
|
||||
$messageselectedvariables.children().each(function () {
|
||||
let val = $(this).text().trim();
|
||||
if (val.length > 0) {
|
||||
if (val.startsWith('[') && val.endsWith(']')) {
|
||||
messagetags += (messagetags.length > 0 ? " " : "") + val;
|
||||
messagedetail += (messagedetail.length > 0 ? " " : "") + val;
|
||||
} else {
|
||||
let sb = soundbankdata
|
||||
.filter(sb => sb.language.toLowerCase() === language.toLowerCase())
|
||||
.filter(sb => sb.voiceType.toLowerCase() === voicetype.toLowerCase())
|
||||
.find(sb => sb.Description && sb.Description.toLowerCase() === val.toLowerCase());
|
||||
if (sb) {
|
||||
messagedetail += (messagedetail.length > 0 ? " " : "") + sb.Description;
|
||||
messagetags += (messagetags.length > 0 ? " " : "") + sb.tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (description.length === 0) {
|
||||
alert("Description cannot be empty");
|
||||
return;
|
||||
}
|
||||
if (!language) {
|
||||
alert("Language cannot be empty");
|
||||
return;
|
||||
}
|
||||
if (isNaN(annid) || annid < 1 || annid > 100) {
|
||||
alert("ANN_ID must be a number between 1 and 100");
|
||||
return;
|
||||
}
|
||||
if (!voicetype) {
|
||||
alert("Voice Type cannot be empty");
|
||||
return;
|
||||
}
|
||||
if (messagedetail.length === 0 || messagetags.length === 0) {
|
||||
alert("Message haven't been constructed, please add categories and phrases");
|
||||
return;
|
||||
}
|
||||
let mbUpdate = {
|
||||
Description: description,
|
||||
Language: language,
|
||||
ANN_ID: annid,
|
||||
Voice_Type: voicetype,
|
||||
Message_Detail: messagedetail,
|
||||
Message_TAGS: messagetags
|
||||
};
|
||||
fetchAPI(APIURL + "UpdateByIndex/" + mb.index, "PATCH", mbUpdate, null, (okdata) => {
|
||||
reloadMessageBank(APIURL);
|
||||
alert("Success edit messagebank : " + okdata.message);
|
||||
}, (errdata) => {
|
||||
alert("Error edit messagebank : " + errdata.message);
|
||||
});
|
||||
$modal.modal('hide');
|
||||
});
|
||||
// Close button event
|
||||
$modal.off('click.messagebankclose').on('click.messagebankclose', '#messagebankclose', function () {
|
||||
$modal.modal('hide');
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
$btnExport.click(() => {
|
||||
DoExport(APIURL, "messagebank.xlsx", {});
|
||||
});
|
||||
$btnImport.click(() => {
|
||||
DoImport(APIURL, (okdata) => {
|
||||
reloadMessageBank(APIURL);
|
||||
alert("Success import messagebank : " + okdata.message);
|
||||
}, (errdata) => {
|
||||
alert("Error importing messagebank from XLSX : " + errdata.message);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user