510 lines
19 KiB
JavaScript
510 lines
19 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 = [];
|
|
|
|
$btnRemove = null;
|
|
$btnEdit = null;
|
|
$btnExport = null;
|
|
$btnfilecheck = null;
|
|
|
|
/**
|
|
* 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) {
|
|
// kalau kosong, tidak bisa remove, edit, export dan filecheck
|
|
$btnRemove.prop('disabled', true);
|
|
$btnEdit.prop('disabled', true);
|
|
$btnExport.prop('disabled', true);
|
|
$btnfilecheck.prop('disabled', true);
|
|
return;
|
|
} else {
|
|
// kalau ada isi, bisa export dan filecheck, tapi remove dan edit tetap tergantung selection
|
|
$btnExport.prop('disabled', false);
|
|
$btnfilecheck.prop('disabled', false);
|
|
}
|
|
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];
|
|
}
|
|
|
|
}
|
|
|
|
|
|
fileViewMode = 'all'; // all, valid, invalid
|
|
|
|
$(document).ready(function () {
|
|
console.log("soundbank.js loaded successfully");
|
|
$('#soundbanktablebody').empty();
|
|
window.selectedsoundrow = null;
|
|
let $btnClear = $('#btnClear');
|
|
let $btnAdd = $('#btnAdd');
|
|
$btnRemove = $('#btnRemove');
|
|
$btnEdit = $('#btnEdit');
|
|
$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;
|
|
$btnfilecheck = $('#btnFileCheck');
|
|
|
|
if (dtSoundbank === null) {
|
|
dtSoundbank = new DataTable('#soundbanktable', {
|
|
dom: 'Bfrtip',
|
|
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" }
|
|
],
|
|
rowCallback: function (row, data) {
|
|
row.classList.toggle('table-danger', !!data.filemissing);
|
|
},
|
|
buttons: ['print', 'pdf', {
|
|
extend: 'collection',
|
|
text: 'View',
|
|
className: 'btn btn-outline-secondary',
|
|
buttons: [
|
|
{ text: 'All Files', className: 'btn btn-outline-primary', action() { fileViewMode = 'all'; dtSoundbank.draw(); } },
|
|
{ text: 'Valid Files', className: 'btn btn-outline-success', action() { fileViewMode = 'valid'; dtSoundbank.draw(); } },
|
|
{ text: 'Invalid Files', className: 'btn btn-outline-danger', action() { fileViewMode = 'invalid'; dtSoundbank.draw(); } }
|
|
]
|
|
}]
|
|
});
|
|
}
|
|
$.fn.dataTable.ext.search.push(function (settings, data, dataIndex, rowData) {
|
|
if (settings.nTable.id !== 'soundbanktable') return true;
|
|
const isInvalid = !!rowData.filemissing;
|
|
if (fileViewMode === 'invalid') return isInvalid;
|
|
if (fileViewMode === 'valid') return !isInvalid;
|
|
return true;
|
|
})
|
|
|
|
|
|
/**
|
|
* 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);
|
|
$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);
|
|
});
|
|
});
|
|
$btnfilecheck.click(() => {
|
|
fetchAPI(APIURL + "FileCheck", "GET", {}, null, (okdata) => {
|
|
console.log(okdata);
|
|
let invalidList = Array.isArray(okdata.invalidfile) ? okdata.invalidfile : [];
|
|
let validList = Array.isArray(okdata.validfile) ? okdata.validfile : [];
|
|
const invalidSet = new Set(invalidList.map(f => f.path));
|
|
dtSoundbank.rows().every(function () {
|
|
const d = this.data();
|
|
d.filemissing = invalidSet.has(d.path);
|
|
this.data(d); // update row data
|
|
});
|
|
|
|
dtSoundbank.draw(false);
|
|
console.log(`File Check completed. ${validList.length} valid files, ${invalidList.length} invalid files.`);
|
|
if (validList.length === 0) {
|
|
if (invalidList.length === 0) {
|
|
alert("No soundbank files found on server.");
|
|
} else {
|
|
alert(`File Check completed. All ${invalidList.length} soundbank files are missing on server.`);
|
|
|
|
}
|
|
} else {
|
|
if (invalidList.length === 0) {
|
|
alert(`File Check completed. All ${validList.length} soundbank files are present on server.`);
|
|
} else {
|
|
alert(`File Check completed. ${validList.length} soundbank files are present, ${invalidList.length} soundbank files are missing on server.`);
|
|
}
|
|
}
|
|
|
|
}, (errdata) => {
|
|
alert("Error checking soundbank files : " + errdata.message);
|
|
});
|
|
});
|
|
}); |