Files
AAS_NewGeneration/html/webpage/assets/js/soundbank.js
2026-01-26 17:12:48 +07:00

450 lines
16 KiB
JavaScript

/**
* @typedef {Object} Select2item
* @property {number} id
* @property {string} text
*/
/**
* @typedef {Object} SoundBank
* @property {number} index
* @property {string} description
* @property {string} tag
* @property {string} category
* @property {string} language
* @property {string} voiceType
* @property {string} path
*/
/**
* List of Soundbank data loaded from server
* @type {SoundBank[]}
*/
window.soundbankdata = [];
/**
* Currently selected soundbank row in the table
* @type {JQuery<HTMLElement>|null}
*/
window.selectedsoundrow = null;
dtSoundbank = null;
/**
* Select2 data source
* See https://select2.org/data-sources/formats
* @type {Select2item[]}
*/
window.select2data = [];
/**
* Reload sound bank from server
* @param {String} APIURL API URL endpoint, default "SoundBank/"
*/
function reloadSoundBank(APIURL = "SoundBank/") {
window.soundbankdata = [];
fetchAPI(APIURL + "List", "GET", {}, null, (okdata) => {
if (Array.isArray(okdata)) {
//console.log("reloadSoundBank: got " + okdata.length + " items");
window.soundbankdata.push(...okdata);
window.selectedsoundrow = null;
fill_soundbanktablebody(window.soundbankdata);
}
}, (errdata) => {
alert("Error loading soundbank : " + errdata.message);
});
}
/**
* Fill soundbank table body with values
* @param {SoundBank[]} vv values to fill
*/
function fill_soundbanktablebody(vv) {
dtSoundbank.clear();
if (!Array.isArray(vv) || vv.length === 0) return;
dtSoundbank.rows.add(vv);
dtSoundbank.draw();
$('#soundbanktable tbody').off('click').on('click', 'tr', function () {
// if no data
if (!dtSoundbank) return;
// if user click an empty row
if (!dtSoundbank.data().any()) return;
const selected = dtSoundbank.row(this)
// toggle behaviour - unselect if already selected
if ($(this).hasClass('row-selected')) {
$(this).removeClass('row-selected').find('td').css('background-color', '');
window.selectedsoundrow = null;
$('#btnRemove').prop('disabled', true);
$('#btnEdit').prop('disabled', true);
return;
}
// unselect previously selected row
$('#soundbanktable tbody tr.row-selected').removeClass('row-selected').find('td').css('background-color', '');
$(this).addClass('row-selected').find('td').css('background-color', '#ffeeba');
window.selectedsoundrow = selected.data();
$('#btnRemove').prop('disabled', false);
$('#btnEdit').prop('disabled', false);
})
$('#tablesize').text("Table Size: " + vv.length);
}
/**
* Reload soundbank files from server and filter by language, category, and voiceType
* @param {String} language
* @param {String} category
* @param {String} voiceType
* @param {Function} cb callback function when done
*/
function reloadSoundbankFiles(language, category, voiceType, cb = null) {
window.select2data = [];
$('#modalpath').empty().trigger('change');
if (language && language.length > 0) {
if (category && category.length > 0) {
if (voiceType && voiceType.length > 0) {
fetchAPI(`ListFiles/${language}/${voiceType}/${category}`, "GET", {}, null, (okdata) => {
//console.log("reloadSoundbankFiles: got " + okdata.length + " items");
if (Array.isArray(okdata)) {
window.select2data = okdata.map(p => ({ id: getFilenameFromPath(p), text: getFilenameFromPath(p) }));
$('#modalpath').select2({
data: window.select2data,
placeholder: 'Select a sound file',
allowClear: true,
width: '100%',
dropdownParent: $('#soundbankmodal')
});
if (cb) cb();
}
}, (errdata) => {
alert("Error loading soundbank files : " + errdata.message);
});
}
}
}
}
function getFilenameFromPath(path) {
if (!path || path.length === 0) return "";
if (path.includes('\\')) {
let parts = path.split('\\');
return parts[parts.length - 1];
} else if (!path.includes('/')) {
let parts = path.split('/');
return parts[parts.length - 1];
}
}
$(document).ready(function () {
console.log("soundbank.js loaded successfully");
$('#soundbanktablebody').empty();
window.selectedsoundrow = 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 = "SoundBank/";
let $modal = $('#soundbankmodal');
let $modalindex = $modal.find('#modalindex');
let $modaldescription = $modal.find('#modaldescription');
let $modaltag = $modal.find('#modaltag');
let $modalcategory = $modal.find('#modalcategory');
let $modallanguage = $modal.find('#modallanguage');
let $modalvoicetype = $modal.find('#modalvoicetype');
let selected_category = null;
let selected_language = null;
let selected_voicetype = null;
if (dtSoundbank === null) {
dtSoundbank = new DataTable('#soundbanktable', {
data: [],
pageLength: 25,
columns: [
{ title: "Index", data: "index" },
{ title: "Description", data: "description" },
{ title: "Tag", data: "tag" },
{ title: "Category", data: "category" },
{ title: "Language", data: "language" },
{ title: "Type", data: "voiceType" },
{ title: "Filename", data: "path" }
]
});
}
/**
* Clear soundbank modal inputs
*/
function clearSoundbankModal() {
$modalindex.val('').prop('disabled', true);
$modaldescription.val('');
$modaltag.val('');
// fill modalcategory options from categories[]
$modalcategory.empty();
categories.forEach(cat => {
$modalcategory.append(new Option(cat, cat));
});
$modalcategory.val(null);
// fill modallanguage options from languages[]
$modallanguage.empty();
languages.forEach(lang => {
$modallanguage.append(new Option(lang, lang));
});
$modallanguage.val(null);
// fill modalvoicetype options from voiceTypes[]
$modalvoicetype.empty();
voiceTypes.forEach(vt => {
$modalvoicetype.append(new Option(vt, vt));
});
$modalvoicetype.val(null);
$('#modalpath').select2()
}
reloadSoundBank(APIURL);
// $('#findsoundbank').on('input', function () {
// let searchTerm = $(this).val().trim().toLowerCase();
// if (searchTerm.length > 0) {
// window.selectedsoundrow = null;
// let filtered = window.soundbankdata.filter(item => item.description.toLowerCase().includes(searchTerm) || item.tag.toLowerCase().includes(searchTerm) || item.path.toLowerCase().includes(searchTerm));
// fill_soundbanktablebody(filtered);
// } else {
// window.selectedsoundrow = null;
// fill_soundbanktablebody(window.soundbankdata);
// }
// });
$btnClear.click(() => {
DoClear(APIURL, "Soundbank", (okdata) => {
reloadSoundBank(APIURL);
alert("Success clear soundbank : " + okdata.message);
}, (errdata) => {
alert("Error clear soundbank : " + errdata.message);
});
});
function SetupEventForCategoryLanguageVoiceType() {
$modalcategory.off('change').on('change', function () {
selected_category = $(this).val();
reloadSoundbankFiles(selected_language, selected_category, selected_voicetype);
});
$modallanguage.off('change').on('change', function () {
selected_language = $(this).val();
reloadSoundbankFiles(selected_language, selected_category, selected_voicetype);
});
$modalvoicetype.off('change').on('change', function () {
selected_voicetype = $(this).val();
reloadSoundbankFiles(selected_language, selected_category, selected_voicetype);
});
}
$btnAdd.click(() => {
$modal.modal('show');
clearSoundbankModal();
// event on selection change of language, category, voiceType
SetupEventForCategoryLanguageVoiceType();
// event on Click save button
$modal.off('click.soundbanksave').on('click.soundbanksave', '#soundbanksave', function () {
let description = $modaldescription.val().trim();
let tag = $modaltag.val().trim();
let category = $modalcategory.val();
let language = $modallanguage.val();
let voiceType = $modalvoicetype.val();
let path = $('#soundbankmodal #modalpath').val();
if (!description || description.length === 0) {
alert("Description is required");
return;
}
if (!tag || tag.length === 0) {
alert("Tag is required");
return;
}
if (!category || category.length === 0) {
alert("Category is required");
return;
}
if (!language || language.length === 0) {
alert("Language is required");
return;
}
if (!voiceType || voiceType.length === 0) {
alert("Voice Type is required");
return;
}
if (!path || path.length === 0) {
alert("Path is required");
return;
}
$modal.modal('hide');
/**
* @type {SoundBank}
*/
let nsb = {
index: 0,
Description: description,
TAG: tag,
Category: category,
Language: language,
VoiceType: voiceType,
Path: path
}
fetchAPI(APIURL + "Add", "POST", {}, nsb, (okdata) => {
reloadSoundBank(APIURL);
alert("Success add soundbank : " + okdata.message);
}, (errdata) => {
alert("Error add soundbank : " + errdata.message);
});
});
// event on Click close button
$modal.off('click.soundbankclose').on('click.soundbankclose', '#soundbankclose', function () {
$modal.modal('hide');
});
});
$btnRemove.click(() => {
if (window.selectedsoundrow) {
//console.log(window.selectedsoundrow);
/** @type {SoundBank} */
let sb = {
index: window.selectedsoundrow.index,
description: window.selectedsoundrow.description,
tag: window.selectedsoundrow.tag,
category: window.selectedsoundrow.category,
language: window.selectedsoundrow.language,
voiceType: window.selectedsoundrow.voiceType,
path: window.selectedsoundrow.path
}
if (confirm(`Are you sure to delete soundbank [${sb.index}] Description=${sb.description} Tag=${sb.tag}?`)) {
fetchAPI(APIURL + "DeleteByIndex/" + sb.index, "DELETE", {}, null, (okdata) => {
reloadSoundBank(APIURL);
alert("Success delete soundbank : " + okdata.message);
}, (errdata) => {
alert("Error delete soundbank : " + errdata.message);
});
}
}
});
$btnEdit.click(() => {
if (window.selectedsoundrow) {
//console.log(window.selectedsoundrow);
/** @type {SoundBank} */
let sb = {
index: window.selectedsoundrow.index,
Description: window.selectedsoundrow.description,
TAG: window.selectedsoundrow.tag,
Category: window.selectedsoundrow.category,
Language: window.selectedsoundrow.language,
VoiceType: window.selectedsoundrow.voiceType,
Path: window.selectedsoundrow.path
}
if (confirm(`Are you sure to edit soundbank [${sb.index}] Description=${sb.Description} Tag=${sb.TAG}?`)) {
$modal.modal('show');
clearSoundbankModal();
SetupEventForCategoryLanguageVoiceType();
$modalindex.val(sb.index).prop('disabled', true);
$modaldescription.val(sb.Description);
$modaltag.val(sb.TAG);
$modalcategory.val(sb.Category);
selected_category = sb.Category;
$modallanguage.val(sb.Language);
selected_language = sb.Language;
$modalvoicetype.val(sb.VoiceType);
selected_voicetype = sb.VoiceType;
// load soundbank files for selected language, category, voiceType
reloadSoundbankFiles(selected_language, selected_category, selected_voicetype, () => {
// set selected path
$('#modalpath').val(getFilenameFromPath(sb.Path)).trigger('change');
});
// event on Click save button
$modal.off('click.soundbanksave').on('click.soundbanksave', '#soundbanksave', function () {
let description = $modaldescription.val().trim();
let tag = $modaltag.val().trim();
let category = $modalcategory.val();
let language = $modallanguage.val();
let voiceType = $modalvoicetype.val();
let path = $('#soundbankmodal #modalpath').val();
if (!description || description.length === 0) {
alert("Description is required");
return;
}
if (!tag || tag.length === 0) {
alert("Tag is required");
return;
}
if (!category || category.length === 0) {
alert("Category is required");
return;
}
if (!language || language.length === 0) {
alert("Language is required");
return;
}
if (!voiceType || voiceType.length === 0) {
alert("Voice Type is required");
return;
}
if (!path || path.length === 0) {
alert("Path is required");
return;
}
if (description === sb.Description && tag === sb.TAG && category === sb.Category && language === sb.Language && voiceType === sb.VoiceType && path === sb.Path) {
alert("No changes detected");
return;
}
sb.Description = description;
sb.TAG = tag;
sb.Category = category;
sb.Language = language;
sb.VoiceType = voiceType;
sb.Path = path;
fetchAPI(APIURL + "UpdateByIndex/" + sb.index, "PATCH", {}, sb, (okdata) => {
reloadSoundBank(APIURL);
alert("Success update soundbank : " + okdata.message);
}, (errdata) => {
alert("Error update soundbank : " + errdata.message);
});
$modal.modal('hide');
});
// event on Click close button
$modal.off('click.soundbankclose').on('click.soundbankclose', '#soundbankclose', function () {
$modal.modal('hide');
});
}
}
});
$btnExport.click(() => {
DoExport(APIURL, "soundbank.xlsx", {});
});
$btnImport.click(() => {
DoImport(APIURL, (okdata) => {
reloadSoundBank(APIURL);
alert("Success import soundbank : " + okdata.message);
}, (errdata) => {
alert("Error importing soundbank from XLSX : " + errdata.message);
});
});
});