commit 11/09/2025

This commit is contained in:
2025-09-11 16:03:33 +07:00
parent 34fc71cfbc
commit b692e2c2c9
8 changed files with 767 additions and 211 deletions

View File

@@ -361,7 +361,7 @@ function fetchAPI(endpoint, method, headers = {}, body = null, cbOK, cbError) {
cbOK(data); cbOK(data);
}) })
.catch(error => { .catch(error => {
// console.error('There was a problem with the fetch operation:', error); // console.error('There was a problem with the fetch operation:', error);
cbError(error); cbError(error);
}); });
} }
@@ -379,7 +379,7 @@ function reloadSoundBank(APIURL) {
fill_soundbanktablebody(soundbankdata); fill_soundbanktablebody(soundbankdata);
} }
}, (errdata) => { }, (errdata) => {
alert("Error loading soundbank: " + errdata.message); alert("Error loading soundbank : " + errdata.message);
}); });
} }
@@ -396,7 +396,7 @@ function reloadMessageBank(APIURL) {
fill_messagebanktablebody(messagebankdata); fill_messagebanktablebody(messagebankdata);
} }
}, (errdata) => { }, (errdata) => {
alert("Error loading messagebank: " + errdata.message); alert("Error loading messagebank : " + errdata.message);
}); });
} }
@@ -413,7 +413,7 @@ function reloadLanguageBank(APIURL) {
fill_languagebanktablebody(languagebankdata); fill_languagebanktablebody(languagebankdata);
} }
}, (errdata) => { }, (errdata) => {
alert("Error loading languagebank: " + errdata.message); alert("Error loading languagebank : " + errdata.message);
}); });
} }
@@ -425,12 +425,12 @@ function reloadTimerBank(APIURL) {
schedulebankdata = []; schedulebankdata = [];
fetchAPI(APIURL + "List", "GET", {}, null, (okdata) => { fetchAPI(APIURL + "List", "GET", {}, null, (okdata) => {
if (Array.isArray(okdata)) { if (Array.isArray(okdata)) {
schedulebankdata = okdata.data; schedulebankdata = okdata;
selectedschedulerow = null; selectedschedulerow = null;
fill_schedulebanktablebody(schedulebankdata); fill_schedulebanktablebody(schedulebankdata);
} }
}, (errdata) => { }, (errdata) => {
alert("Error loading schedulebank: " + errdata.message); alert("Error loading schedulebank : " + errdata.message);
}); });
} }
@@ -447,9 +447,12 @@ function reloadLogs(APIURL, date, filter) {
}) })
fetchAPI(APIURL + "List?" + params.toString(), "GET", {}, null, (okdata) => { fetchAPI(APIURL + "List?" + params.toString(), "GET", {}, null, (okdata) => {
//console.log("Logs data received", okdata); //console.log("Logs data received", okdata);
fill_logtablebody(okdata); if (Array.isArray(okdata)) {
logdata = okdata;
fill_logtablebody(okdata);
}
}, (errdata) => { }, (errdata) => {
alert("Error loading logs: " + errdata.message); alert("Error loading logs : " + errdata.message);
}); });
} }
@@ -469,7 +472,7 @@ function regetSoundbankFiles(APIURL = "SoundBank/") {
select2results.results = soundbankfiles.map((item, index) => ({ id: index + 1, text: item })); select2results.results = soundbankfiles.map((item, index) => ({ id: index + 1, text: item }));
} else console.log("regetSoundbankFiles: okdata is not array"); } else console.log("regetSoundbankFiles: okdata is not array");
}, (errdata) => { }, (errdata) => {
alert("Error loading soundbank files: " + errdata.message); alert("Error loading soundbank files : " + errdata.message);
}); });
} }
@@ -485,7 +488,7 @@ function getVoiceTypes() {
//console.log("Loaded " + voiceTypes.length + " voice types : " + voiceTypes.join(", ")); //console.log("Loaded " + voiceTypes.length + " voice types : " + voiceTypes.join(", "));
} else console.log("getVoiceTypes: okdata is not array"); } else console.log("getVoiceTypes: okdata is not array");
}, (errdata) => { }, (errdata) => {
alert("Error loading voice types: " + errdata.message); alert("Error loading voice types : " + errdata.message);
}); });
} }
@@ -501,7 +504,7 @@ function getCategories() {
//console.log("Loaded " + categories.length + " categories : " + categories.join(", ")); //console.log("Loaded " + categories.length + " categories : " + categories.join(", "));
} else console.log("getCategories: okdata is not array"); } else console.log("getCategories: okdata is not array");
}, (errdata) => { }, (errdata) => {
alert("Error loading categories: " + errdata.message); alert("Error loading categories : " + errdata.message);
}); });
} }
@@ -517,7 +520,7 @@ function getLanguages() {
//console.log("Loaded " + languages.length + " languages : " + languages.join(", ") ); //console.log("Loaded " + languages.length + " languages : " + languages.join(", ") );
} else console.log("getLanguages: okdata is not array"); } else console.log("getLanguages: okdata is not array");
}, (errdata) => { }, (errdata) => {
alert("Error loading languages: " + errdata.message); alert("Error loading languages : " + errdata.message);
}); });
} }
@@ -533,7 +536,7 @@ function getScheduledDays() {
//console.log("Loaded " + scheduledays.length + " scheduled days : " + scheduledays.join(", ") ); //console.log("Loaded " + scheduledays.length + " scheduled days : " + scheduledays.join(", ") );
} else console.log("getScheduledDays: okdata is not array"); } else console.log("getScheduledDays: okdata is not array");
}, (errdata) => { }, (errdata) => {
alert("Error loading scheduled days: " + errdata.message); alert("Error loading scheduled days : " + errdata.message);
}); });
} }
@@ -729,7 +732,8 @@ $(document).ready(function () {
reloadSoundBank(APIURL); reloadSoundBank(APIURL);
$('#findsoundbank').on('input', function () { $('#findsoundbank').on('input', function () {
let searchTerm = $(this).val().trim().toLowerCase(); let searchTerm = $(this).val().trim().toLowerCase();
if (searchTerm.length>0){ if (searchTerm.length > 0) {
selectedsoundrow = null;
let filtered = soundbankdata.filter(item => item.description.toLowerCase().includes(searchTerm) || item.tag.toLowerCase().includes(searchTerm) || item.path.toLowerCase().includes(searchTerm)); let filtered = soundbankdata.filter(item => item.description.toLowerCase().includes(searchTerm) || item.tag.toLowerCase().includes(searchTerm) || item.path.toLowerCase().includes(searchTerm));
fill_soundbanktablebody(filtered); fill_soundbanktablebody(filtered);
} else { } else {
@@ -739,12 +743,10 @@ $(document).ready(function () {
}); });
$btnClear.click(() => { $btnClear.click(() => {
DoClear(APIURL, "Soundbank", (okdata) => { DoClear(APIURL, "Soundbank", (okdata) => {
alert("Success clear soundbank" + okdata.message); reloadSoundBank(APIURL);
soundbankdata = [] alert("Success clear soundbank : " + okdata.message);
selectedsoundrow = null;
fill_soundbanktablebody(soundbankdata);
}, (errdata) => { }, (errdata) => {
alert("Error clear soundbank: " + errdata.message); alert("Error clear soundbank : " + errdata.message);
}); });
}); });
@@ -779,12 +781,10 @@ $(document).ready(function () {
} }
if (confirm(`Are you sure to delete soundbank [${sb.index}] Description=${sb.description} Tag=${sb.tag}?`)) { if (confirm(`Are you sure to delete soundbank [${sb.index}] Description=${sb.description} Tag=${sb.tag}?`)) {
fetchAPI(APIURL + "DeleteByIndex/" + sb.index, "DELETE", {}, null, (okdata) => { fetchAPI(APIURL + "DeleteByIndex/" + sb.index, "DELETE", {}, null, (okdata) => {
alert("Success delete soundbank" + okdata.message); reloadSoundBank(APIURL);
soundbankdata = soundbankdata.filter(item => item.index !== sb.index); alert("Success delete soundbank : " + okdata.message);
selectedsoundrow = null;
fill_soundbanktablebody(soundbankdata);
}, (errdata) => { }, (errdata) => {
alert("Error delete soundbank: " + errdata.message); alert("Error delete soundbank : " + errdata.message);
}); });
} }
} }
@@ -813,17 +813,18 @@ $(document).ready(function () {
} }
}); });
$btnExport.click(() => { $btnExport.click(() => {
DoExport(APIURL, "soundbank.xlsx",{}); DoExport(APIURL, "soundbank.xlsx", {});
}); });
$btnImport.click(() => { $btnImport.click(() => {
DoImport(APIURL, (okdata) => { DoImport(APIURL, (okdata) => {
reloadSoundBank(APIURL); reloadSoundBank(APIURL);
alert("Success import soundbank : " + okdata.message);
}, (errdata) => { }, (errdata) => {
alert("Error importing soundbank from XLSX: " + errdata.message); alert("Error importing soundbank from XLSX : " + errdata.message);
}); });
}); });
} else { } else {
console.error("Error loading soundbank content:", xhr.status, xhr.statusText); console.error("Error loading soundbank content : ", xhr.status, xhr.statusText);
} }
}); });
@@ -845,17 +846,28 @@ $(document).ready(function () {
$btnRemove.prop('disabled', true); $btnRemove.prop('disabled', true);
$btnEdit.prop('disabled', true); $btnEdit.prop('disabled', true);
let APIURL = "MessageBank/"; let APIURL = "MessageBank/";
let $findmessage = $('#findmessage');
$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); reloadMessageBank(APIURL);
$btnClear.click(() => { $btnClear.click(() => {
DoClear(APIURL, "Messagebank", (okdata) => { DoClear(APIURL, "Messagebank", (okdata) => {
alert("Success clear messagebank" + okdata.message); reloadMessageBank(APIURL);
messagebankdata = [] alert("Success clear messagebank : " + okdata.message);
selectedmessagerow = null;
fill_messagebanktablebody(messagebankdata);
}, (errdata) => { }, (errdata) => {
alert("Error clear messagebank: " + errdata.message); alert("Error clear messagebank : " + errdata.message);
}); });
}); });
@@ -892,12 +904,10 @@ $(document).ready(function () {
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} `)) { 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) => { fetchAPI(APIURL + "DeleteByIndex/" + mb.index, "DELETE", {}, null, (okdata) => {
alert("Success delete messagebank" + okdata.message); reloadMessageBank(APIURL);
messagebankdata = messagebankdata.filter(item => item.index !== mb.index); alert("Success delete messagebank : " + okdata.message);
selectedmessagerow = null;
fill_messagebanktablebody(messagebankdata);
}, (errdata) => { }, (errdata) => {
alert("Error delete messagebank: " + errdata.message); alert("Error delete messagebank : " + errdata.message);
}); });
} }
} }
@@ -921,17 +931,18 @@ $(document).ready(function () {
} }
}); });
$btnExport.click(() => { $btnExport.click(() => {
DoExport(APIURL, "messagebank.xlsx",{}); DoExport(APIURL, "messagebank.xlsx", {});
}); });
$btnImport.click(() => { $btnImport.click(() => {
DoImport(APIURL, (okdata) => { DoImport(APIURL, (okdata) => {
reloadMessageBank(APIURL); reloadMessageBank(APIURL);
alert("Success import messagebank : " + okdata.message);
}, (errdata) => { }, (errdata) => {
alert("Error importing messagebank from XLSX: " + errdata.message); alert("Error importing messagebank from XLSX : " + errdata.message);
}); });
}); });
} else { } else {
console.error("Error loading messagebank content:", xhr.status, xhr.statusText); console.error("Error loading messagebank content : ", xhr.status, xhr.statusText);
} }
}); });
@@ -953,33 +964,54 @@ $(document).ready(function () {
$btnRemove.prop('disabled', true); $btnRemove.prop('disabled', true);
$btnEdit.prop('disabled', true); $btnEdit.prop('disabled', true);
let APIURL = "LanguageLink/"; let APIURL = "LanguageLink/";
let $findlanguage = $('#findlanguage');
let $modal = $('#languagemodal');
let $langid = $modal.find('#languagelinkindex');
let $langtag = $modal.find('#languagelinktag');
let $cbInd = $modal.find('#langId');
let $cbLocal = $modal.find('#langLocal');
let $cbEn = $modal.find('#langEn');
let $cbArb = $modal.find('#langArb');
let $cbJap = $modal.find('#langJap');
let $cbChi = $modal.find('#langChi');
function clearLanguageModal() {
$langid.prop('disabled', true).val('');
$langtag.val('');
$cbInd.prop('checked', false);
$cbLocal.prop('checked', false);
$cbEn.prop('checked', false);
$cbArb.prop('checked', false);
$cbJap.prop('checked', false);
$cbChi.prop('checked', false);
}
$findlanguage.on('input', function () {
let searchTerm = $findlanguage.val().toLowerCase();
if (searchTerm.length > 0) {
selectedlanguagerow = null;
let filtered = languagebankdata.filter(item => item.tag.toLowerCase().includes(searchTerm) || item.language.toLowerCase().includes(searchTerm));
fill_languagebanktablebody(filtered);
} else {
selectedlanguagerow = null;
fill_languagebanktablebody(languagebankdata);
}
});
reloadLanguageBank(APIURL); reloadLanguageBank(APIURL);
$btnClear.click(() => { $btnClear.click(() => {
DoClear(APIURL, "LanguageLink", (okdata) => { DoClear(APIURL, "LanguageLink", (okdata) => {
alert("Success clear languageLink" + okdata.message); reloadLanguageBank(APIURL);
languagebankdata = [] alert("Success clear languageLink : " + okdata.message);
selectedlanguagerow = null;
fill_languagebanktablebody(languagebankdata);
}, (errdata) => { }, (errdata) => {
alert("Error clear languagebank: " + errdata.message); alert("Error clear languageLink : " + errdata.message);
}); });
}); });
$btnAdd.click(() => { $btnAdd.click(() => {
// show modal with id 'languagemodal' // show modal with id 'languagemodal'
let $modal = $('#languagemodal');
$modal.modal('show'); $modal.modal('show');
let $langtag = $modal.find('#languagelinktag'); clearLanguageModal();
let $cbInd = $modal.find('#langId');
let $cbLocal = $modal.find('#langLocal');
let $cbEn = $modal.find('#langEn');
let $cbArb = $modal.find('#langArb');
let $cbJap = $modal.find('#langJap');
let $cbChi = $modal.find('#langChi');
// save button click event // save button click event
$modal.off('click.languagelinksave').on('click.languagelinksave', '#languagelinksave', function () { $modal.off('click.languagelinksave').on('click.languagelinksave', '#languagelinksave', function () {
@@ -1007,10 +1039,10 @@ $(document).ready(function () {
language: langString language: langString
} }
fetchAPI(APIURL + "Add", "POST", {}, ll, (okdata) => { fetchAPI(APIURL + "Add", "POST", {}, ll, (okdata) => {
alert("Success add language" + okdata.message); alert("Success add language : " + okdata.message);
reloadLanguageBank(APIURL); reloadLanguageBank(APIURL);
}, (errdata) => { }, (errdata) => {
alert("Error add language: " + errdata.message); alert("Error add language : " + errdata.message);
}); });
$modal.modal('hide'); $modal.modal('hide');
@@ -1032,12 +1064,10 @@ $(document).ready(function () {
} }
if (confirm(`Are you sure to delete language [${ll.index}] Tag=${ll.tag} Language=${ll.language}?`)) { if (confirm(`Are you sure to delete language [${ll.index}] Tag=${ll.tag} Language=${ll.language}?`)) {
fetchAPI(APIURL + "DeleteByIndex/" + ll.index, "DELETE", {}, null, (okdata) => { fetchAPI(APIURL + "DeleteByIndex/" + ll.index, "DELETE", {}, null, (okdata) => {
alert("Success delete language" + okdata.message); reloadLanguageBank(APIURL);
languagebankdata = languagebankdata.filter(item => item.index !== ll.index); alert("Success delete language : " + okdata.message);
selectedlanguagerow = null;
fill_languagebanktablebody(languagebankdata);
}, (errdata) => { }, (errdata) => {
alert("Error delete language: " + errdata.message); alert("Error delete language : " + errdata.message);
}); });
} }
} }
@@ -1052,15 +1082,8 @@ $(document).ready(function () {
language: cells.eq(2).text() language: cells.eq(2).text()
} }
if (confirm(`Are you sure to edit language [${ll.index}] Tag=${ll.tag} Language=${ll.language}?`)) { if (confirm(`Are you sure to edit language [${ll.index}] Tag=${ll.tag} Language=${ll.language}?`)) {
let $modal = $('#languagemodal');
let $cbInd = $modal.find('#langId'); clearLanguageModal();
let $cbLocal = $modal.find('#langLocal');
let $cbEn = $modal.find('#langEn');
let $cbArb = $modal.find('#langArb');
let $cbJap = $modal.find('#langJap');
let $cbChi = $modal.find('#langChi');
let $langtag = $modal.find('#languagelinktag');
let $langid = $modal.find('#languagelinkindex');
$langid.val(ll.index); $langid.val(ll.index);
$langtag.val(ll.tag); $langtag.val(ll.tag);
let langs = ll.language.toUpperCase().split(';'); let langs = ll.language.toUpperCase().split(';');
@@ -1099,10 +1122,10 @@ $(document).ready(function () {
ll.tag = tag; ll.tag = tag;
ll.language = langString; ll.language = langString;
fetchAPI(APIURL + "UpdateByIndex/" + ll.index, "PATCH", {}, ll, (okdata) => { fetchAPI(APIURL + "UpdateByIndex/" + ll.index, "PATCH", {}, ll, (okdata) => {
alert("Success edit language" + okdata.message);
reloadLanguageBank(APIURL); reloadLanguageBank(APIURL);
alert("Success edit language : " + okdata.message);
}, (errdata) => { }, (errdata) => {
alert("Error edit language: " + errdata.message); alert("Error edit language : " + errdata.message);
}); });
$modal.modal('hide'); $modal.modal('hide');
@@ -1117,19 +1140,20 @@ $(document).ready(function () {
} }
}); });
$btnExport.click(() => { $btnExport.click(() => {
DoExport(APIURL, "languagebank.xlsx",{}); DoExport(APIURL, "languagebank.xlsx", {});
}); });
$btnImport.click(() => { $btnImport.click(() => {
DoImport(APIURL, (okdata) => { DoImport(APIURL, (okdata) => {
reloadLanguageBank(APIURL); reloadLanguageBank(APIURL);
alert("Success import languagebank : " + okdata.message);
}, (errdata) => { }, (errdata) => {
alert("Error importing languagebank from XLSX: " + errdata.message); alert("Error importing languagebank from XLSX : " + errdata.message);
}); });
}); });
} else { } else {
console.error("Error loading language content:", xhr.status, xhr.statusText); console.error("Error loading language content : ", xhr.status, xhr.statusText);
} }
}); });
}) })
@@ -1151,21 +1175,156 @@ $(document).ready(function () {
$btnRemove.prop('disabled', true); $btnRemove.prop('disabled', true);
let APIURL = "ScheduleBank/"; let APIURL = "ScheduleBank/";
let $schedulemodal = $('#schedulemodal');
// text input
let $scheduleid = $schedulemodal.find('#scheduleid');
// text input
let $scheduledescription = $schedulemodal.find('#scheduledescription');
// number input 0-23
let $schedulehour = $schedulemodal.find('#schedulehour');
// number input 0-59
let $scheduleminute = $schedulemodal.find('#scheduleminute');
// text input
let $schedulesoundpath = $schedulemodal.find('#schedulesoundpath');
// number input 0-5
let $schedulerepeat = $schedulemodal.find('#schedulerepeat');
// checkbox
let $scheduleenable = $schedulemodal.find('#scheduleenable');
// div for list of checkboxes
let $schedulezones = $schedulemodal.find('#schedulezones');
// radio button for everyday
let $scheduleeveryday = $schedulemodal.find('#scheduleeveryday');
// radio button for weekdays
let $schedulesunday = $schedulemodal.find('#schedulesunday');
let $schedulemonday = $schedulemodal.find('#schedulemonday');
let $scheduletuesday = $schedulemodal.find('#scheduletuesday');
let $schedulewednesday = $schedulemodal.find('#schedulewednesday');
let $schedulethursday = $schedulemodal.find('#schedulethursday');
let $schedulefriday = $schedulemodal.find('#schedulefriday');
let $schedulesaturday = $schedulemodal.find('#schedulesaturday');
// radio button for specific date
let $schedulespecialdate = $schedulemodal.find('#schedulespecialdate');
// date input
let $scheduledate = $schedulemodal.find('#scheduledate');
$schedulespecialdate.on('change', function () {
if ($(this).is(':checked')) {
$scheduledate.prop('disabled', false);
} else {
$scheduledate.prop('disabled', true);
}
});
function clearScheduleModal() {
$scheduleid.prop('disabled', true).val('');
$scheduledescription.val('');
$schedulehour.val('0');
$scheduleminute.val('0');
$schedulesoundpath.val('');
$schedulerepeat.val('0');
$scheduleenable.prop('checked', true);
$scheduleeveryday.prop('checked', false);
$schedulesunday.prop('checked', false);
$schedulemonday.prop('checked', false);
$scheduletuesday.prop('checked', false);
$schedulewednesday.prop('checked', false);
$schedulethursday.prop('checked', false);
$schedulefriday.prop('checked', false);
$schedulesaturday.prop('checked', false);
$schedulespecialdate.prop('checked', false);
$scheduledate.prop('disabled', true).val('');
}
let $findschedule = $('#findschedule');
$findschedule.on('input', function () {
let searchTerm = $findschedule.val().toLowerCase();
if (searchTerm.length > 0) {
selectedtimerow = null;
let filtered = schedulebankdata.filter(item => item.description.toLowerCase().includes(searchTerm) || item.soundpath.toLowerCase().includes(searchTerm) || item.broadcastZones.toLowerCase().includes(searchTerm));
fill_schedulebanktablebody(filtered);
} else {
selectedtimerow = null;
fill_schedulebanktablebody(schedulebankdata);
}
});
reloadTimerBank(APIURL); reloadTimerBank(APIURL);
$btnClear.click(() => { $btnClear.click(() => {
DoClear(APIURL, "Timerbank", (okdata) => { DoClear(APIURL, "Timerbank", (okdata) => {
alert("Success clear schedulebank" + okdata.message); reloadTimerBank(APIURL);
schedulebankdata = [] alert("Success clear schedulebank : " + okdata.message);
selectedschedulerow = null;
fill_schedulebanktablebody(schedulebankdata);
}, (errdata) => { }, (errdata) => {
alert("Error clear schedulebank: " + errdata.message); alert("Error clear schedulebank : " + errdata.message);
}); });
}); });
$btnAdd.click(() => { $btnAdd.click(() => {
//TODO form add timer //TODO form add timer
$schedulemodal.modal('show');
clearScheduleModal();
$schedulemodal.off('click.scheduleclose').on('click.scheduleclose', '#scheduleclose', function () {
$schedulemodal.modal('hide');
});
$schedulemodal.off('click.schedulesave').on('click.schedulesave', '#schedulesave', function () {
// Gather form values
const Description = $scheduledescription.val();
const Soundpath = $schedulesoundpath.val();
const Repeat = parseInt($schedulerepeat.val(), 10);
const Enable = $scheduleenable.is(':checked');
// Collect selected days
let Day = "";
if ($scheduleeveryday.is(':checked')) {
Day = "Everyday";
} else if ($schedulespecialdate.is(':checked')) {
Day = $scheduledate.val();
} else {
if ($schedulesunday.is(':checked')) Day = "Sunday";
if ($schedulemonday.is(':checked')) Day = "Monday";
if ($scheduletuesday.is(':checked')) Day = "Tuesday";
if ($schedulewednesday.is(':checked')) Day = "Wednesday";
if ($schedulethursday.is(':checked')) Day = "Thursday";
if ($schedulefriday.is(':checked')) Day = "Friday";
if ($schedulesaturday.is(':checked')) Day = "Saturday";
}
// Broadcast zones (assuming comma-separated string)
const BroadcastZones = $schedulezones.val();
// Validate required fields
if (!Description || !Soundpath || Day === "") {
alert("Description, sound path, and day are required.");
return;
}
// Format time as HH:mm
const hour = parseInt($schedulehour.val(), 10);
const minute = parseInt($scheduleminute.val(), 10);
const Time = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
// Prepare object
const scheduleObj = {
Description,
Day,
Time,
Soundpath,
Repeat,
Enable,
BroadcastZones
};
fetchAPI(APIURL + "Add", "POST", {}, scheduleObj, (okdata) => {
alert("Success add schedule: " + okdata.message);
reloadTimerBank(APIURL);
}, (errdata) => {
alert("Error add schedule: " + errdata.message);
});
$schedulemodal.modal('hide');
});
}); });
$btnRemove.click(() => { $btnRemove.click(() => {
if (selectedtimerow) { if (selectedtimerow) {
@@ -1184,12 +1343,10 @@ $(document).ready(function () {
} }
if (confirm(`Are you sure to delete schedule [${sr.index}] Description=${sr.description}?`)) { if (confirm(`Are you sure to delete schedule [${sr.index}] Description=${sr.description}?`)) {
fetchAPI(APIURL + "DeleteByIndex/" + sr.index, "DELETE", {}, null, (okdata) => { fetchAPI(APIURL + "DeleteByIndex/" + sr.index, "DELETE", {}, null, (okdata) => {
alert("Success delete schedule" + okdata.message); reloadTimerBank(APIURL);
schedulebankdata = schedulebankdata.filter(item => item.index !== sr.index); alert("Success delete schedule : " + okdata.message);
selectedtimerow = null;
fill_schedulebanktablebody(schedulebankdata);
}, (errdata) => { }, (errdata) => {
alert("Error delete schedule: " + errdata.message); alert("Error delete schedule : " + errdata.message);
}); });
} }
} }
@@ -1210,22 +1367,124 @@ $(document).ready(function () {
language: cells.eq(8).text() language: cells.eq(8).text()
} }
if (confirm(`Are you sure to edit schedule [${sr.index}] Description=${sr.description}?`)) { if (confirm(`Are you sure to edit schedule [${sr.index}] Description=${sr.description}?`)) {
//TODO send edit command $schedulemodal.modal('show');
// fill the form with existing data
$scheduleid.val(sr.index);
$scheduledescription.val(sr.description);
let [hour, minute] = sr.time.split(':').map(num => parseInt(num, 10));
$schedulehour.val(hour.toString());
$scheduleminute.val(minute.toString());
$schedulesoundpath.val(sr.soundpath);
$schedulerepeat.val(sr.repeat.toString());
$scheduleenable.prop('checked', sr.enable.toLowerCase() === 'true');
switch (sr.day) {
case 'Everyday':
$scheduleeveryday.click();
break;
case 'Sunday':
$schedulesunday.click();
break;
case 'Monday':
$schedulemonday.click();
break;
case 'Tuesday':
$scheduletuesday.click();
break;
case 'Wednesday':
$schedulewednesday.click();
break;
case 'Thursday':
$schedulethursday.click();
break;
case 'Friday':
$schedulefriday.click();
break;
case 'Saturday':
$schedulesaturday.click();
break;
default:
// check if the day is in format dd/mm/yyyy
// and set the special date radio button and date input
if (/^\d{2}\/\d{2}\/\d{4}$/.test(sr.day)) {
$schedulespecialdate.click();
$scheduledate.val(sr.day);
}
}
$schedulemodal.off('click.scheduleclose').on('click.scheduleclose', '#scheduleclose', function () {
$schedulemodal.modal('hide');
});
$schedulemodal.off('click.schedulesave').on('click.schedulesave', '#schedulesave', function () {
// Gather form values
const Description = $scheduledescription.val();
const Soundpath = $schedulesoundpath.val();
const Repeat = parseInt($schedulerepeat.val(), 10);
const Enable = $scheduleenable.is(':checked');
// Collect selected days
let Day = "";
if ($scheduleeveryday.is(':checked')) {
Day = "Everyday";
} else if ($schedulespecialdate.is(':checked')) {
Day = $scheduledate.val();
} else {
if ($schedulesunday.is(':checked')) Day = "Sunday";
if ($schedulemonday.is(':checked')) Day = "Monday";
if ($scheduletuesday.is(':checked')) Day = "Tuesday";
if ($schedulewednesday.is(':checked')) Day = "Wednesday";
if ($schedulethursday.is(':checked')) Day = "Thursday";
if ($schedulefriday.is(':checked')) Day = "Friday";
if ($schedulesaturday.is(':checked')) Day = "Saturday";
}
// Broadcast zones (assuming comma-separated string)
const BroadcastZones = $schedulezones.val();
// Validate required fields
if (!Description || !Soundpath || Day === "") {
alert("Description, sound path, and day are required.");
return;
}
// Format time as HH:mm
const hour = parseInt($schedulehour.val(), 10);
const minute = parseInt($scheduleminute.val(), 10);
const Time = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
// Prepare object
const scheduleObj = {
Description,
Day,
Time,
Soundpath,
Repeat,
Enable,
BroadcastZones
};
fetchAPI(APIURL + "UpdateByIndex/" + sr.index, "PATCH", {}, scheduleObj, (okdata) => {
alert("Success edit schedule: " + okdata.message);
reloadTimerBank(APIURL);
}, (errdata) => {
alert("Error edit schedule: " + errdata.message);
});
$schedulemodal.modal('hide');
});
} }
} }
}); });
$btnExport.click(() => { $btnExport.click(() => {
DoExport(APIURL, "schedulebank.xlsx",{}); DoExport(APIURL, "schedulebank.xlsx", {});
}); });
$btnImport.click(() => { $btnImport.click(() => {
DoImport(APIURL, (okdata) => { DoImport(APIURL, (okdata) => {
reloadTimerBank(APIURL); reloadTimerBank(APIURL);
alert("Success import schedulebank from XLSX : " + okdata.message);
}, (errdata) => { }, (errdata) => {
alert("Error importing schedulebank from XLSX: " + errdata.message); alert("Error importing schedulebank from XLSX : " + errdata.message);
}); });
}); });
} else { } else {
console.error("Error loading timer content:", xhr.status, xhr.statusText); console.error("Error loading timer content : ", xhr.status, xhr.statusText);
} }
}); });
}) })
@@ -1267,7 +1526,7 @@ $(document).ready(function () {
reloadLogs(APIURL, selectedlogdate, logfilter); reloadLogs(APIURL, selectedlogdate, logfilter);
}); });
$btnExport.off('click').on('click', function () { $btnExport.off('click').on('click', function () {
DoExport(APIURL, "log.xlsx",{date:selectedlogdate,filter:logfilter}); DoExport(APIURL, "log.xlsx", { date: selectedlogdate, filter: logfilter });
}); });
} else { } else {

View File

@@ -16,6 +16,13 @@
<h2 style="text-align: center;">Language Link</h2> <h2 style="text-align: center;">Language Link</h2>
</div> </div>
</div> </div>
<div class="row">
<div class="col-md-7 col-lg-7 col-xl-7"></div>
<div class="col-2 col-sm-2 col-md-2 col-lg-2 col-xl-2 search">
<p class="text-add">Search</p>
</div>
<div class="col-10 col-sm-10 col-md-3 col-lg-3 col-xl-3"><input class="w-100 form-control" type="text" id="findlanguage" placeholder="Search keyword" name="findsoundbank"></div>
</div>
<div class="row"> <div class="row">
<div class="col-3 col-sm-3 col-md-3 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-add" id="btnClear" type="button">Clear</button></div> <div class="col-3 col-sm-3 col-md-3 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-add" id="btnClear" type="button">Clear</button></div>
<div class="col-3 col-sm-3 col-md-3 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-add" id="btnAdd" type="button">Add</button></div> <div class="col-3 col-sm-3 col-md-3 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-add" id="btnAdd" type="button">Add</button></div>

View File

@@ -16,6 +16,13 @@
<h2 style="text-align: center;">Message Bank</h2> <h2 style="text-align: center;">Message Bank</h2>
</div> </div>
</div> </div>
<div class="row">
<div class="col-md-7 col-lg-7 col-xl-7"></div>
<div class="col-2 col-sm-2 col-md-2 col-lg-2 col-xl-2 search">
<p class="text-add">Search</p>
</div>
<div class="col-10 col-sm-10 col-md-3 col-lg-3 col-xl-3"><input class="w-100 form-control" type="text" id="findmessage" placeholder="Search keyword" name="findsoundbank"></div>
</div>
<div class="row"> <div class="row">
<div class="col-3 col-sm-3 col-md-3 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-add" id="btnClear" type="button">Clear</button></div> <div class="col-3 col-sm-3 col-md-3 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-add" id="btnClear" type="button">Clear</button></div>
<div class="col-3 col-sm-3 col-md-3 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-add" id="btnAdd" type="button">Add</button></div> <div class="col-3 col-sm-3 col-md-3 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-add" id="btnAdd" type="button">Add</button></div>

View File

@@ -16,6 +16,13 @@
<h2 style="text-align: center;">Schedule Bank</h2> <h2 style="text-align: center;">Schedule Bank</h2>
</div> </div>
</div> </div>
<div class="row">
<div class="col-md-7 col-lg-7 col-xl-7"></div>
<div class="col-2 col-sm-2 col-md-2 col-lg-2 col-xl-2 search">
<p class="text-add">Search</p>
</div>
<div class="col-10 col-sm-10 col-md-3 col-lg-3 col-xl-3"><input class="w-100 form-control" type="text" id="findschedule" placeholder="Search keyword" name="findsoundbank"></div>
</div>
<div class="row"> <div class="row">
<div class="col-3 col-sm-3 col-md-3 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-add" id="btnClear" type="button">Clear</button></div> <div class="col-3 col-sm-3 col-md-3 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-add" id="btnClear" type="button">Clear</button></div>
<div class="col-3 col-sm-3 col-md-3 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-add" id="btnAdd" type="button">Add</button></div> <div class="col-3 col-sm-3 col-md-3 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-add" id="btnAdd" type="button">Add</button></div>
@@ -59,58 +66,110 @@
<div class="col-4 col-sm-3"> <div class="col-4 col-sm-3">
<p class="text-add">Index</p> <p class="text-add">Index</p>
</div> </div>
<div class="col"><input type="text" class="input-add form-control"></div> <div class="col"><input type="text" id="scheduleid" class="input-add form-control" disabled=""></div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-4 col-sm-3"> <div class="col-4 col-sm-3">
<p class="text-add">Description</p> <p class="text-add">Description</p>
</div> </div>
<div class="col"><input type="text" class="input-add form-control"></div> <div class="col"><input type="text" id="scheduledescription" class="input-add form-control"></div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-4 col-sm-3"> <div class="col-4 col-sm-3">
<p class="text-add">Day</p> <p class="text-add">Day</p>
</div> </div>
<div class="col"><input type="text" class="input-add form-control"></div> <div class="col">
<div class="row">
<div class="col">
<div class="form-check"><input class="form-check-input" type="radio" id="scheduleeveryday" name="dayselection" value="Everyday"><label class="form-check-label" for="formCheck-1">Everyday</label></div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-check"><input class="form-check-input" type="radio" id="schedulesunday" name="dayselection" value="Sunday"><label class="form-check-label" for="formCheck-8">Sunday</label></div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-check"><input class="form-check-input" type="radio" id="schedulemonday" name="dayselection" value="Monday"><label class="form-check-label" for="formCheck-7">Monday</label></div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-check"><input class="form-check-input" type="radio" id="scheduletuesday" name="dayselection" value="Tuesday"><label class="form-check-label" for="formCheck-6">Tuesday</label></div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-check"><input class="form-check-input" type="radio" id="schedulewednesday" name="dayselection" value="Wednesday"><label class="form-check-label" for="formCheck-5">Wednesday</label></div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-check"><input class="form-check-input" type="radio" id="schedulethursday" name="dayselection" value="Thursday"><label class="form-check-label" for="formCheck-4">Thursday</label></div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-check"><input class="form-check-input" type="radio" id="schedulefriday" name="dayselection" value="Friday"><label class="form-check-label" for="formCheck-3">Friday</label></div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-check"><input class="form-check-input" type="radio" id="schedulesaturday" name="dayselection" value="Saturday"><label class="form-check-label" for="formCheck-2">Saturday</label></div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-check"><input class="form-check-input" type="radio" id="schedulespecialdate" name="dayselection"><label class="form-check-label" for="formCheck-9">Special Date</label></div>
</div>
<div class="col"><input id="scheduledate" type="date"></div>
</div>
</div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-4 col-sm-3"> <div class="col-4 col-sm-3">
<p class="text-add">Time</p> <p class="text-add">Time</p>
</div> </div>
<div class="col"><input type="text" class="input-add form-control"></div> <div class="col">
<div class="row w-100 h-100">
<div class="col-3"><input class="w-100 h-100" type="number" id="schedulehour" value="0" min="0" max="23" step="1"></div>
<div class="col-1">
<p class="w-100 h-100">(H)</p>
</div>
<div class="col-3"><input class="w-100 h-100" type="number" id="scheduleminute" value="0" min="0" max="59" step="1"></div>
<div class="col-1">
<p class="w-100 h-100">(M)</p>
</div>
</div>
</div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-4 col-sm-3"> <div class="col-4 col-sm-3">
<p class="text-add">Sound Path</p> <p class="text-add">Sound Path</p>
</div> </div>
<div class="col"><input type="text" class="input-add form-control"></div> <div class="col"><input type="text" id="schedulesoundpath" class="input-add form-control"></div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-4 col-sm-3"> <div class="col-4 col-sm-3">
<p class="text-add">Repeat</p> <p class="text-add">Repeat</p>
</div> </div>
<div class="col"><input class="w-25 form-select input-add" type="number" min="1" max="5" step="1" value="1"></div> <div class="col"><input class="w-25 form-select input-add" type="number" id="schedulerepeat" min="0" max="5" step="1" value="0"></div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-4 col-sm-3"> <div class="col-4 col-sm-3">
<p class="text-add">Enable</p> <p class="text-add">Enable</p>
</div> </div>
<div class="col"><input type="checkbox" class="form-check-input form-check text-add" checked=""></div> <div class="col"><input type="checkbox" id="scheduleenable" class="form-check-input form-check text-add" checked=""></div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-4 col-sm-3"> <div class="col-4 col-sm-3">
<p class="text-add">Broadcast Zones</p> <p class="text-add">Broadcast Zones</p>
</div> </div>
<div class="col"> <div class="col border p-2" id="schedulezones"></div>
<ul class="list-group">
<li class="list-group-item"><span>List Group Item 1</span></li>
<li class="list-group-item"><span>List Group Item 2</span></li>
<li class="list-group-item"><span>List Group Item 3</span></li>
</ul>
</div>
</div> </div>
</div> </div>
<div class="modal-footer"><button class="btn btn-round-basic color-edit class25" type="button" data-bs-dismiss="modal">Close</button><button class="btn btn-round-basic class25 color-add" type="button">Save</button></div> <div class="modal-footer"><button class="btn btn-round-basic color-edit class25" id="scheduleclose" type="button" data-bs-dismiss="modal">Close</button><button class="btn btn-round-basic class25 color-add" id="schedulesave" type="button">Save</button></div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -12,5 +12,5 @@ enum class Language(name: String) {
Local("LOCAL"), Local("LOCAL"),
Japanese("JAPANESE"), Japanese("JAPANESE"),
Chinese("CHINESE"), Chinese("CHINESE"),
Arabic("ARABIC"),; Arabic("ARABIC");
} }

View File

@@ -222,15 +222,15 @@ class MariaDB(
*/ */
fun GetLogForHtml(date: String, consumer: Consumer<ArrayList<Log>>) { fun GetLogForHtml(date: String, consumer: Consumer<ArrayList<Log>>) {
val logList = ArrayList<Log>() val logList = ArrayList<Log>()
println("GetLogForHtml Date: $date" ) //println("GetLogForHtml Date: $date" )
if (ValiDateForLogHtml(date)) { if (ValiDateForLogHtml(date)) {
try { try {
// must convert from DD-MM-YYYY to DD/MM/YYYY, because in database we use DD/MM/YYYY // must convert from DD-MM-YYYY to DD/MM/YYYY, because in database we use DD/MM/YYYY
val adjusteddate = date.replace("-", "/") val adjusteddate = date.replace("-", "/")
val statement = connection?.prepareStatement("SELECT * FROM logs WHERE datenya = ?") val statement = connection?.prepareStatement("SELECT * FROM logs WHERE datenya = ?")
statement?.setString(1, adjusteddate) statement?.setString(1, adjusteddate)
println("GetLogForHtml Date: $adjusteddate" ) //println("GetLogForHtml Date: $adjusteddate" )
println("GetLogForHtml SQL: " +statement?.toString()) // println("GetLogForHtml SQL: " +statement?.toString())
val resultSet = statement?.executeQuery() val resultSet = statement?.executeQuery()
while (resultSet?.next() == true) { while (resultSet?.next() == true) {
val log = Log( val log = Log(
@@ -258,7 +258,7 @@ class MariaDB(
*/ */
fun GetLogForHtml(date: String, filter: String, consumer: Consumer<ArrayList<Log>>) { fun GetLogForHtml(date: String, filter: String, consumer: Consumer<ArrayList<Log>>) {
val logList = ArrayList<Log>() val logList = ArrayList<Log>()
println("GetLogForHtml Date: $date Filter: $filter" ) //println("GetLogForHtml Date: $date Filter: $filter" )
if (ValiDateForLogHtml(date)) { if (ValiDateForLogHtml(date)) {
try { try {
@@ -268,8 +268,8 @@ class MariaDB(
connection?.prepareStatement("SELECT * FROM logs WHERE datenya = ? AND description LIKE ?") connection?.prepareStatement("SELECT * FROM logs WHERE datenya = ? AND description LIKE ?")
statement?.setString(1, adjusteddate) statement?.setString(1, adjusteddate)
statement?.setString(2, "%$filter%") statement?.setString(2, "%$filter%")
println("GetLogForHtml Date: $adjusteddate , Filter=$filter" ) //println("GetLogForHtml Date: $adjusteddate , Filter=$filter" )
println("GetLogForHtml SQL: " +statement?.toString()) //println("GetLogForHtml SQL: " +statement?.toString())
val resultSet = statement?.executeQuery() val resultSet = statement?.executeQuery()
while (resultSet?.next() == true) { while (resultSet?.next() == true) {
val log = Log( val log = Log(
@@ -457,6 +457,29 @@ class MariaDB(
return false return false
} }
/**
* Resort the schedulebank table, in order to reorder the index after deletions, and sort ascending by Day and Time.
* @return True if the resorting was successful, false otherwise.
*/
fun Resort_Schedulebank_by_Day_Time(): Boolean {
try {
val statement = connection?.createStatement()
// use a temporary table to reorder the index
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS temp_schedulebank LIKE schedulebank")
statement?.executeUpdate("INSERT INTO temp_schedulebank (Description, Day, Time, Soundpath, Repeat, Enable, BroadcastZones, Language) SELECT Description, Day, Time, Soundpath, Repeat, Enable, BroadcastZones, Language FROM schedulebank ORDER BY Day ASC, Time ASC")
statement?.executeUpdate("TRUNCATE TABLE schedulebank")
statement?.executeUpdate("INSERT INTO schedulebank (Description, Day, Time, Soundpath, Repeat, Enable, BroadcastZones, Language) SELECT Description, Day, Time, Soundpath, Repeat, Enable, BroadcastZones, Language FROM temp_schedulebank")
statement?.executeUpdate("DROP TABLE temp_schedulebank")
Logger.info("schedulebank table resorted by Day and Time" as Any)
// reload the local list
Reload_Schedulebank()
return true
} catch (e: Exception) {
Logger.error("Error resorting schedulebank table by Day and Time: ${e.message}" as Any)
}
return false
}
/** /**
* Clears all entries from the schedulebank table in the database and the local list. * Clears all entries from the schedulebank table in the database and the local list.
*/ */
@@ -695,6 +718,29 @@ class MariaDB(
return false return false
} }
/**
* Resort the language link table, in order to reorder the index after deletions, and sort ascending by TAG.
* @return True if the resorting was successful, false otherwise.
*/
fun Resort_LanguageLink_by_TAG() : Boolean {
try {
val statement = connection?.createStatement()
// use a temporary table to reorder the index
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS temp_languagelinking LIKE languagelinking")
statement?.executeUpdate("INSERT INTO temp_languagelinking (TAG, Language) SELECT TAG, Language FROM languagelinking ORDER BY TAG ASC")
statement?.executeUpdate("TRUNCATE TABLE languagelinking")
statement?.executeUpdate("INSERT INTO languagelinking (TAG, Language) SELECT TAG, Language FROM temp_languagelinking")
statement?.executeUpdate("DROP TABLE temp_languagelinking")
Logger.info("languagelinking table resorted by TAG" as Any)
// reload the local list
Reload_LanguageLink()
return true
} catch (e: Exception) {
Logger.error("Error resorting languagelinking table by TAG: ${e.message}" as Any)
}
return false
}
/** /**
* Clears all entries from the language link table in the database and the local list. * Clears all entries from the language link table in the database and the local list.
*/ */
@@ -945,6 +991,29 @@ class MariaDB(
return false return false
} }
/**
* Resort the soundbank table, in order to reorder the index after deletions, and sort ascending by Description.
* @return True if the resorting was successful, false otherwise.
*/
fun Resort_Soundbank_by_Description(): Boolean {
try {
val statement = connection?.createStatement()
// use a temporary table to reorder the index
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS temp_soundbank LIKE soundbank")
statement?.executeUpdate("INSERT INTO temp_soundbank (Description, TAG, Category, Language, VoiceType, Path) SELECT Description, TAG, Category, Language, VoiceType, Path FROM soundbank ORDER BY Description ASC")
statement?.executeUpdate("TRUNCATE TABLE soundbank")
statement?.executeUpdate("INSERT INTO soundbank (Description, TAG, Category, Language, VoiceType, Path) SELECT Description, TAG, Category, Language, VoiceType, Path FROM temp_soundbank")
statement?.executeUpdate("DROP TABLE temp_soundbank")
Logger.info("soundbank table resorted by Description" as Any)
// reload the local list
Reload_Soundbank()
return true
} catch (e: Exception) {
Logger.error("Error resorting soundbank table by Description: ${e.message}" as Any)
}
return false
}
/** /**
* Clears all entries from the soundbank table in the database and the local list. * Clears all entries from the soundbank table in the database and the local list.
*/ */
@@ -1173,6 +1242,29 @@ class MariaDB(
return false return false
} }
/**
* Resort the messagebank table, in order to reorder the index after deletions, and sort ascending by ANN_ID.
* @return True if the resorting was successful, false otherwise.
*/
fun Resort_Messagebank_by_ANN_ID(): Boolean {
try {
val statement = connection?.createStatement()
// use a temporary table to reorder the index
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS temp_messagebank LIKE messagebank")
statement?.executeUpdate("INSERT INTO temp_messagebank (Description, Language, ANN_ID, Voice_Type, Message_Detail, Message_TAGS) SELECT Description, Language, ANN_ID, Voice_Type, Message_Detail, Message_TAGS FROM messagebank ORDER BY ANN_ID ASC")
statement?.executeUpdate("TRUNCATE TABLE messagebank")
statement?.executeUpdate("INSERT INTO messagebank (Description, Language, ANN_ID, Voice_Type, Message_Detail, Message_TAGS) SELECT Description, Language, ANN_ID, Voice_Type, Message_Detail, Message_TAGS FROM temp_messagebank")
statement?.executeUpdate("DROP TABLE temp_messagebank")
Logger.info("messagebank table resorted by Description" as Any)
// reload the local list
Reload_Messagebank()
return true
} catch (e: Exception) {
Logger.error("Error resorting messagebank table by Description: ${e.message}" as Any)
}
return false
}
/** /**
* Exports the messagebank table to an XLSX workbook. * Exports the messagebank table to an XLSX workbook.
* @return An XSSFWorkbook containing the messagebank data. * @return An XSSFWorkbook containing the messagebank data.
@@ -1527,6 +1619,29 @@ class MariaDB(
return false return false
} }
/**
* Resort the broadcast_zones table, in order to reorder the index after deletions, and sort ascending by description.
* @return True if the resorting was successful, false otherwise.
*/
fun Resort_BroadcastZones_by_description(): Boolean {
try {
val statement = connection?.createStatement()
// use a temporary table to reorder the index
statement?.executeUpdate("CREATE TABLE IF NOT EXISTS temp_broadcast_zones LIKE broadcast_zones")
statement?.executeUpdate("INSERT INTO temp_broadcast_zones (description, SoundChannel, Box, Relay) SELECT description, SoundChannel, Box, Relay FROM broadcast_zones ORDER BY description ASC")
statement?.executeUpdate("TRUNCATE TABLE broadcast_zones")
statement?.executeUpdate("INSERT INTO broadcast_zones (description, SoundChannel, Box, Relay) SELECT description, SoundChannel, Box, Relay FROM temp_broadcast_zones")
statement?.executeUpdate("DROP TABLE temp_broadcast_zones")
Logger.info("broadcast_zones table resorted by description" as Any)
// reload the local list
GetBroadcastZones()
return true
} catch (e: Exception) {
Logger.error("Error resorting broadcast_zones table by description: ${e.message}" as Any)
}
return false
}
/** /**
* Clears all entries from the broadcast_zones in the database. * Clears all entries from the broadcast_zones in the database.
*/ */

View File

@@ -3,7 +3,6 @@ package web
import codes.Somecodes import codes.Somecodes
import codes.Somecodes.Companion.ListAudioFiles import codes.Somecodes.Companion.ListAudioFiles
import codes.Somecodes.Companion.ValiDateForLogHtml import codes.Somecodes.Companion.ValiDateForLogHtml
import codes.Somecodes.Companion.ValidDate
import codes.Somecodes.Companion.ValidFile import codes.Somecodes.Companion.ValidFile
import codes.Somecodes.Companion.ValidScheduleDay import codes.Somecodes.Companion.ValidScheduleDay
import codes.Somecodes.Companion.ValidScheduleTime import codes.Somecodes.Companion.ValidScheduleTime
@@ -66,13 +65,13 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
val username = it.formParam("username") val username = it.formParam("username")
val password = it.formParam("password") val password = it.formParam("password")
if (username == null || password == null) { if (username == null || password == null) {
it.status(400).result("Username and password are required") it.status(400).result(objectmapper.writeValueAsString(resultMessage("Username and password are required")))
return@post return@post
} }
// Check if user exists in userlist // Check if user exists in userlist
val user = userlist.find { it.first == username && it.second == password } val user = userlist.find { it.first == username && it.second == password }
if (user == null) { if (user == null) {
it.status(401).result("Invalid username or password") it.status(401).result(objectmapper.writeValueAsString(resultMessage("Invalid username or password")))
return@post return@post
} }
// Set user session // Set user session
@@ -208,40 +207,43 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
if (!exists) { if (!exists) {
if (ValidFile(addvalue.Path)) { if (ValidFile(addvalue.Path)) {
if (db.Add_Soundbank(addvalue)) { if (db.Add_Soundbank(addvalue)) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Resort_Soundbank_by_Description()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else it.status(500) } else it.status(500)
.result("Failed to add soundbank to database") .result(objectmapper.writeValueAsString(resultMessage("Failed to add soundbank to database")))
} else it.status(400) } else it.status(400)
.result("Invalid Path, file does not exist") .result(objectmapper.writeValueAsString(resultMessage("Invalid Path, file does not exist")))
} else it.status(400) } else it.status(400)
.result("TAG=${addvalue.TAG} already exists for the same Language=${addvalue.Language} and Category=${addvalue.Category}") .result(objectmapper.writeValueAsString(resultMessage("TAG=${addvalue.TAG} already exists for the same Language=${addvalue.Language} and Category=${addvalue.Category}")))
} else it.status(400).result("Invalid Path") } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Path")))
} else it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid Language"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Language")))
} else it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid Category"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Category")))
} else it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid TAG"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid TAG")))
} else it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid Description"))) } else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Description")))
} catch (_: Exception) { } catch (_: Exception) {
it.status(400).result("Invalid request body") it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid request body")))
} }
} }
delete("List") { delete("List") {
// truncate soundbank table // truncate soundbank table
if (db.Clear_Soundbank()) { if (db.Clear_Soundbank()) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Reload_Soundbank()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else { } else {
it.status(500).result("Failed to truncate soundbank table") it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to truncate soundbank table")))
} }
} }
delete("DeleteByIndex/{index}") { delete("DeleteByIndex/{index}") {
// delete by index // delete by index
val index = it.pathParam("index").toUIntOrNull() val index = it.pathParam("index").toUIntOrNull()
if (index == null) { if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else { } else {
if (db.Delete_Soundbank_by_index(index)) { if (db.Delete_Soundbank_by_index(index)) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Resort_Soundbank_by_Description()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else { } else {
it.status(500).result("Failed to delete soundbank with index $index") it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to delete soundbank with index $index")))
} }
} }
} }
@@ -250,17 +252,17 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
val index = it.pathParam("index").toUIntOrNull() val index = it.pathParam("index").toUIntOrNull()
if (index == null) { if (index == null) {
// tidak ada path param index // tidak ada path param index
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else { } else {
val sb = db.SoundbankList.find { xx -> xx.index == index } val sb = db.SoundbankList.find { xx -> xx.index == index }
if (sb == null) { if (sb == null) {
// soundbank dengan index tersebut tidak ditemukan // soundbank dengan index tersebut tidak ditemukan
it.status(404).result("Soundbank with index $index not found") it.status(404).result(objectmapper.writeValueAsString(resultMessage("Soundbank with index $index not found")))
} else { } else {
// soundbank dengan index tersebut ditemukan, sekarang update // soundbank dengan index tersebut ditemukan, sekarang update
val json: JsonNode = objectmapper.readTree(it.body()) val json: JsonNode = objectmapper.readTree(it.body())
if (json.isEmpty) { if (json.isEmpty) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "UpdateByIndex with index=$index has empty body"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("UpdateByIndex with index=$index has empty body")))
} else { } else {
val _description = json.get("Description").asText() val _description = json.get("Description").asText()
val _tag = json.get("TAG").asText() val _tag = json.get("TAG").asText()
@@ -283,7 +285,7 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
sb.Category = _category sb.Category = _category
changed = true changed = true
} else { } else {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid Category"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Category")))
return@patch return@patch
} }
} }
@@ -296,16 +298,17 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
sb.Path = _path sb.Path = _path
changed = true changed = true
} else { } else {
it.status(400).result("Invalid Path, file does not exist") it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Path, file does not exist")))
return@patch return@patch
} }
} }
if (changed) { if (changed) {
if (db.Update_Soundbank_by_index(index, sb)) { if (db.Update_Soundbank_by_index(index, sb)) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Resort_Soundbank_by_Description()
} else it.status(500).result("Failed to update soundbank with index $index") it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to update soundbank with index $index")))
} else it.status(400) } else it.status(400)
.result("Nothing has changed for soundbank with index $index") .result(objectmapper.writeValueAsString(resultMessage("Nothing has changed for soundbank with index $index")))
} }
} }
} }
@@ -322,24 +325,25 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
xlsxdata.write(out) xlsxdata.write(out)
} }
} else { } else {
it.status(500).result("Failed to export soundbank to XLSX") it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to export soundbank to XLSX")))
} }
} }
post("ImportXLSX") { post("ImportXLSX") {
val uploaded = it.uploadedFile("file") val uploaded = it.uploadedFile("file")
if (uploaded == null) { if (uploaded == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "No file uploaded"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("No file uploaded")))
return@post return@post
} }
try { try {
val xlsx = XSSFWorkbook(uploaded.content()) val xlsx = XSSFWorkbook(uploaded.content())
if (db.Import_Soundbank_XLSX(xlsx)) { if (db.Import_Soundbank_XLSX(xlsx)) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Resort_Soundbank_by_Description()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else { } else {
it.status(500).result("Failed to import soundbank from XLSX") it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to import soundbank from XLSX")))
} }
} catch (e: Exception) { } catch (e: Exception) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid XLSX file"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid XLSX file")))
} }
} }
} }
@@ -354,21 +358,23 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
delete("List") { delete("List") {
// truncate messagebank table // truncate messagebank table
if (db.Clear_Messagebank()) { if (db.Clear_Messagebank()) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Reload_Messagebank()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else { } else {
it.status(500).result(objectmapper.writeValueAsString(mapOf("message" to "Failed to truncate messagebank table"))) it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to truncate messagebank table")))
} }
} }
delete("DeleteByIndex/{index}") { delete("DeleteByIndex/{index}") {
// delete by index // delete by index
val index = it.pathParam("index").toUIntOrNull() val index = it.pathParam("index").toUIntOrNull()
if (index == null) { if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else { } else {
if (db.Delete_Messagebank_by_index(index)) { if (db.Delete_Messagebank_by_index(index)) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Resort_Messagebank_by_ANN_ID()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else { } else {
it.status(500).result(objectmapper.writeValueAsString(mapOf("message" to "Failed to delete messagebank with index $index"))) it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to delete messagebank with index $index")))
} }
} }
} }
@@ -376,15 +382,15 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// update messagebank by index // update messagebank by index
val index = it.pathParam("index").toUIntOrNull() val index = it.pathParam("index").toUIntOrNull()
if (index == null) { if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else { } else {
val mb = db.MessagebankList.find { xx -> xx.index == index } val mb = db.MessagebankList.find { xx -> xx.index == index }
if (mb == null) { if (mb == null) {
it.status(404).result(objectmapper.writeValueAsString(mapOf("message" to "Messagebank with index $index not found"))) it.status(404).result(objectmapper.writeValueAsString(resultMessage("Messagebank with index $index not found")))
} else { } else {
val json: JsonNode = objectmapper.readTree(it.body()) val json: JsonNode = objectmapper.readTree(it.body())
if (json.isEmpty) { if (json.isEmpty) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "UpdateByIndex with index=$index has empty body"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("UpdateByIndex with index=$index has empty body")))
} else { } else {
val _description = json.get("Description").asText() val _description = json.get("Description").asText()
val _language = json.get("Language").asText() val _language = json.get("Language").asText()
@@ -411,7 +417,7 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
mb.Voice_Type = _voice_type mb.Voice_Type = _voice_type
changed = true changed = true
} else { } else {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid Voice_Type"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Voice_Type")))
return@patch return@patch
} }
} }
@@ -425,11 +431,12 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
} }
if (changed) { if (changed) {
if (db.Update_Messagebank_by_index(index, mb)) { if (db.Update_Messagebank_by_index(index, mb)) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Resort_Messagebank_by_ANN_ID()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else it.status(500) } else it.status(500)
.result(objectmapper.writeValueAsString(mapOf("message" to "Failed to update messagebank with index $index"))) .result(objectmapper.writeValueAsString(resultMessage("Failed to update messagebank with index $index")))
} else it.status(400) } else it.status(400)
.result(objectmapper.writeValueAsString(mapOf("message" to "Nothing has changed for messagebank with index $index"))) .result(objectmapper.writeValueAsString(resultMessage("Nothing has changed for messagebank with index $index")))
} }
} }
} }
@@ -446,24 +453,25 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
xlsxdata.write(out) xlsxdata.write(out)
} }
} else { } else {
it.status(500).result(objectmapper.writeValueAsString(mapOf("message" to "Failed to export messagebank to XLSX"))) it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to export messagebank to XLSX")))
} }
} }
post("ImportXLSX") { post("ImportXLSX") {
val uploaded = it.uploadedFile("file") val uploaded = it.uploadedFile("file")
if (uploaded == null) { if (uploaded == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "No file uploaded"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("No file uploaded")))
return@post return@post
} }
try { try {
val xlsx = XSSFWorkbook(uploaded.content()) val xlsx = XSSFWorkbook(uploaded.content())
if (db.Import_Messagebank_XLSX(xlsx)) { if (db.Import_Messagebank_XLSX(xlsx)) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Resort_Messagebank_by_ANN_ID()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else { } else {
it.status(500).result(objectmapper.writeValueAsString(mapOf("message" to "Failed to import messagebank from XLSX"))) it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to import messagebank from XLSX")))
} }
} catch (e: Exception) { } catch (e: Exception) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid XLSX file"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid XLSX file")))
} }
} }
} }
@@ -477,35 +485,51 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
val json: JsonNode = objectmapper.readTree(it.body()) val json: JsonNode = objectmapper.readTree(it.body())
val tag = json.get("tag").asText() val tag = json.get("tag").asText()
val languages = json.get("language").asText().split(";") val languages = json.get("language").asText().split(";")
println("Add Language Link, tag=$tag, languages=$languages")
if (ValidString(tag)){ if (ValidString(tag)){
if (languages.all { xx -> Language.entries.any { yy -> yy.name== xx} }){ if (languages.all { xx -> Language.entries.any { yy -> yy.name.equals(xx,true)} }){
if (db.LanguageLinkList.any { ll -> ll.TAG==tag }){ if (!db.LanguageLinkList.any { ll -> ll.TAG.equals(tag,true) }) {
val newvalue = LanguageLink(0u, tag, languages.joinToString(";")) val newvalue = LanguageLink(0u, tag, languages.joinToString(";"))
if (db.Add_LanguageLink(newvalue)){ if (db.Add_LanguageLink(newvalue)){
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Resort_LanguageLink_by_TAG()
} else it.status(500).result(objectmapper.writeValueAsString(mapOf("message" to "Failed to add language link to database"))) it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "TAG=$tag already exists"))) } else {
} else it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Contains unsupported language"))) it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to add language link to database")))
} else it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid tag or language"))) println("Failed to add language link to database")
}
} else {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("TAG=$tag already exists")))
println("TAG=$tag already exists")
}
} else {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Contains unsupported language")))
println("Contains unsupported language")
}
} else {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid tag or language")))
println("Invalid tag")
}
} }
delete("List") { delete("List") {
// truncate language link table // truncate language link table
if (db.Clear_LanguageLink()) { if (db.Clear_LanguageLink()) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Reload_LanguageLink()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else { } else {
it.status(500).result(objectmapper.writeValueAsString(mapOf("message" to "Failed to truncate language link table"))) it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to truncate language link table")))
} }
} }
delete("DeleteByIndex/{index}") { delete("DeleteByIndex/{index}") {
// delete by index // delete by index
val index = it.pathParam("index").toUIntOrNull() val index = it.pathParam("index").toUIntOrNull()
if (index == null) { if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else { } else {
if (db.Delete_LanguageLink_by_index(index)) { if (db.Delete_LanguageLink_by_index(index)) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Resort_LanguageLink_by_TAG()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else { } else {
it.status(500).result(objectmapper.writeValueAsString(mapOf("message" to "Failed to delete language link with index $index"))) it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to delete language link with index $index")))
} }
} }
} }
@@ -513,15 +537,15 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// update by index // update by index
val index = it.pathParam("index").toUIntOrNull() val index = it.pathParam("index").toUIntOrNull()
if (index == null) { if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else { } else {
val ll = db.LanguageLinkList.find { xx -> xx.index == index } val ll = db.LanguageLinkList.find { xx -> xx.index == index }
if (ll == null) { if (ll == null) {
it.status(404).result(objectmapper.writeValueAsString(mapOf("message" to "Language link with index $index not found"))) it.status(404).result(objectmapper.writeValueAsString(resultMessage("Language link with index $index not found")))
} else { } else {
val json: JsonNode = objectmapper.readTree(it.body()) val json: JsonNode = objectmapper.readTree(it.body())
if (json.isEmpty) { if (json.isEmpty) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "UpdateByIndex with index=$index has empty body"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("UpdateByIndex with index=$index has empty body")))
} else { } else {
val _tag = json.get("tag").asText() val _tag = json.get("tag").asText()
val _language = json.get("language").asText() val _language = json.get("language").asText()
@@ -536,11 +560,12 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
} }
if (changed) { if (changed) {
if (db.Update_LanguageLink_by_index(index, ll)) { if (db.Update_LanguageLink_by_index(index, ll)) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Resort_LanguageLink_by_TAG()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else it.status(500) } else it.status(500)
.result(objectmapper.writeValueAsString(mapOf("message" to "Failed to update language link with index $index"))) .result(objectmapper.writeValueAsString(resultMessage("Failed to update language link with index $index")))
} else it.status(400) } else it.status(400)
.result(objectmapper.writeValueAsString(mapOf("message" to "Nothing has changed for language link with index $index"))) .result(objectmapper.writeValueAsString(resultMessage("Nothing has changed for language link with index $index")))
} }
} }
} }
@@ -557,24 +582,25 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
xlsxdata.write(out) xlsxdata.write(out)
} }
} else { } else {
it.status(500).result(objectmapper.writeValueAsString(mapOf("message" to "Failed to export language link to XLSX"))) it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to export language link to XLSX")))
} }
} }
post("ImportXLSX") { post("ImportXLSX") {
val uploaded = it.uploadedFile("file") val uploaded = it.uploadedFile("file")
if (uploaded == null) { if (uploaded == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "No file uploaded"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("No file uploaded")))
return@post return@post
} }
try { try {
val xlsx = XSSFWorkbook(uploaded.content()) val xlsx = XSSFWorkbook(uploaded.content())
if (db.Import_LanguageLink_XLSX(xlsx)) { if (db.Import_LanguageLink_XLSX(xlsx)) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Resort_LanguageLink_by_TAG()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else { } else {
it.status(500).result(objectmapper.writeValueAsString(mapOf("message" to "Failed to import language link from XLSX"))) it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to import language link from XLSX")))
} }
} catch (e: Exception) { } catch (e: Exception) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid XLSX file"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid XLSX file")))
} }
} }
} }
@@ -586,21 +612,23 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
delete("List") { delete("List") {
// truncate timer table // truncate timer table
if (db.Clear_Schedulebank()) { if (db.Clear_Schedulebank()) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Reload_Schedulebank()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else { } else {
it.status(500).result(objectmapper.writeValueAsString(mapOf("message" to "Failed to truncate schedulebank table"))) it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to truncate schedulebank table")))
} }
} }
delete("DeleteByIndex/{index}") { delete("DeleteByIndex/{index}") {
// delete by index // delete by index
val index = it.pathParam("index").toUIntOrNull() val index = it.pathParam("index").toUIntOrNull()
if (index == null) { if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else { } else {
if (db.Delete_Schedulebank_by_index(index)) { if (db.Delete_Schedulebank_by_index(index)) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Resort_Schedulebank_by_Day_Time()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else { } else {
it.status(500).result("Failed to delete schedule with index $index") it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to delete schedule with index $index")))
} }
} }
} }
@@ -608,15 +636,15 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// update by index // update by index
val index = it.pathParam("index").toUIntOrNull() val index = it.pathParam("index").toUIntOrNull()
if (index == null) { if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else { } else {
val sb = db.SchedulebankList.find { xx -> xx.index == index } val sb = db.SchedulebankList.find { xx -> xx.index == index }
if (sb == null) { if (sb == null) {
it.status(404).result("Schedule with index $index not found") it.status(404).result(objectmapper.writeValueAsString(resultMessage("Schedule with index $index not found")))
} else { } else {
val json: JsonNode = objectmapper.readTree(it.body()) val json: JsonNode = objectmapper.readTree(it.body())
if (json.isEmpty) { if (json.isEmpty) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "UpdateByIndex with index=$index has empty body"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("UpdateByIndex with index=$index has empty body")))
} else { } else {
val _description = json.get("Description").asText() val _description = json.get("Description").asText()
val _time = json.get("Time").asText() val _time = json.get("Time").asText()
@@ -636,7 +664,7 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
sb.Time = _time sb.Time = _time
changed = true changed = true
} else { } else {
it.status(400).result("Invalid Time format, must be HH:mm") it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Time format, must be HH:mm")))
return@patch return@patch
} }
} }
@@ -645,7 +673,7 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
sb.Day = _day sb.Day = _day
changed = true changed = true
} else { } else {
it.status(400).result("Invalid Day format") it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Day format")))
return@patch return@patch
} }
} }
@@ -670,17 +698,18 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
sb.Language = _language sb.Language = _language
changed = true changed = true
} else { } else {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid Language"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Language")))
return@patch return@patch
} }
} }
if (changed) { if (changed) {
if (db.Update_Schedulebank_by_index(index, sb)) { if (db.Update_Schedulebank_by_index(index, sb)) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Resort_Schedulebank_by_Day_Time()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else it.status(500) } else it.status(500)
.result(objectmapper.writeValueAsString(mapOf("message" to "Failed to update schedule with index $index"))) .result(objectmapper.writeValueAsString(resultMessage("Failed to update schedule with index $index")))
} else it.status(400) } else it.status(400)
.result(objectmapper.writeValueAsString(mapOf("message" to "Nothing has changed for schedule with index $index"))) .result(objectmapper.writeValueAsString(resultMessage("Nothing has changed for schedule with index $index")))
} }
} }
} }
@@ -697,24 +726,25 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
xlsxdata.write(out) xlsxdata.write(out)
} }
} else { } else {
it.status(500).result(objectmapper.writeValueAsString(mapOf("message" to "Failed to export schedulebank to XLSX"))) it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to export schedulebank to XLSX")))
} }
} }
post("ImportXLSX") { post("ImportXLSX") {
val uploaded = it.uploadedFile("file") val uploaded = it.uploadedFile("file")
if (uploaded == null) { if (uploaded == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "No file uploaded"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("No file uploaded")))
return@post return@post
} }
try { try {
val xlsx = XSSFWorkbook(uploaded.content()) val xlsx = XSSFWorkbook(uploaded.content())
if (db.Import_Schedulebank_XLSX(xlsx)) { if (db.Import_Schedulebank_XLSX(xlsx)) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK"))) db.Resort_Schedulebank_by_Day_Time()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else { } else {
it.status(500).result("Failed to import schedulebank from XLSX") it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to import schedulebank from XLSX")))
} }
} catch (e: Exception) { } catch (e: Exception) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid XLSX file"))) it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid XLSX file")))
} }
} }
} }
@@ -735,7 +765,7 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
} }
} else { } else {
println("Invalid logdate=$logdate") println("Invalid logdate=$logdate")
get1.status(400).result("Invalid logdate") get1.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid logdate")))
} }
} }
get("ExportXLSX") { get1 -> get("ExportXLSX") { get1 ->
@@ -758,11 +788,86 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
xlsxdata.write(out) xlsxdata.write(out)
} }
} else { } else {
get1.status(500).result("Failed to export log to XLSX") get1.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to export log to XLSX")))
} }
} else get1.status(400).result("Invalid logdate") } else get1.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid logdate")))
} }
} }
path("BroadcastZones"){
get("List") {
// get broadcast zones list
it.result(MariaDB.ArrayListtoString(db.BroadcastZoneList))
}
delete("List"){
// truncate broadcast zones table
if (db.Clear_BroadcastZones()) {
db.GetBroadcastZones()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else {
it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to truncate broadcast zones table")))
}
}
post("Add") {
// Parse JSON from request body
val json: JsonNode = objectmapper.readTree(it.body())
val zone = json.get("zone").asText()
val description = json.get("description").asText()
println("Add Broadcast Zone, zone=$zone, description=$description")
// TODO continue tomorrow
}
delete("DeleteByIndex/{index}") {
// delete by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
if (db.Delete_BroadcastZones_by_index(index)) {
db.Resort_BroadcastZones_by_description()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else {
it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to delete broadcast zone with index $index")))
}
}
}
post("UpdateByIndex/{index}") {
// TODO continue tomorrow
}
get("ExportXLSX") {
val xlsxdata = db.Export_BroadcastZones_XLSX()
if (xlsxdata != null) {
it.header(
"Content-Type",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
)
it.header("Content-Disposition", "attachment; filename=\"broadcastzones.xlsx\"")
it.outputStream().use { out ->
xlsxdata.write(out)
}
} else {
it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to export broadcast zones to XLSX")))
}
}
post("ImportXLSX") {
val uploaded = it.uploadedFile("file")
if (uploaded == null) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("No file uploaded")))
return@post
}
try {
val xlsx = XSSFWorkbook(uploaded.content())
if (db.Import_BroadcastZones_XLSX(xlsx)) {
db.Resort_BroadcastZones_by_description()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else {
it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to import broadcast zones from XLSX")))
}
} catch (e: Exception) {
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid XLSX file")))
}
}
}
} }
} }
}.start(listenPort) }.start(listenPort)

4
src/web/resultMessage.kt Normal file
View File

@@ -0,0 +1,4 @@
package web
@Suppress("unused")
data class resultMessage(val message: String)