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

@@ -323,7 +323,7 @@ let ws = null;
function sendCommand(command, data) {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ command, data }));
}
}
}
/**
@@ -356,12 +356,12 @@ function fetchAPI(endpoint, method, headers = {}, body = null, cbOK, cbError) {
}
return response.json();
})
.then(data => {
.then(data => {
//console.log("fetchAPI: received data", data);
cbOK(data);
})
.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);
});
}
@@ -379,7 +379,7 @@ function reloadSoundBank(APIURL) {
fill_soundbanktablebody(soundbankdata);
}
}, (errdata) => {
alert("Error loading soundbank: " + errdata.message);
alert("Error loading soundbank : " + errdata.message);
});
}
@@ -396,7 +396,7 @@ function reloadMessageBank(APIURL) {
fill_messagebanktablebody(messagebankdata);
}
}, (errdata) => {
alert("Error loading messagebank: " + errdata.message);
alert("Error loading messagebank : " + errdata.message);
});
}
@@ -413,7 +413,7 @@ function reloadLanguageBank(APIURL) {
fill_languagebanktablebody(languagebankdata);
}
}, (errdata) => {
alert("Error loading languagebank: " + errdata.message);
alert("Error loading languagebank : " + errdata.message);
});
}
@@ -425,12 +425,12 @@ function reloadTimerBank(APIURL) {
schedulebankdata = [];
fetchAPI(APIURL + "List", "GET", {}, null, (okdata) => {
if (Array.isArray(okdata)) {
schedulebankdata = okdata.data;
schedulebankdata = okdata;
selectedschedulerow = null;
fill_schedulebanktablebody(schedulebankdata);
}
}, (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) => {
//console.log("Logs data received", okdata);
fill_logtablebody(okdata);
if (Array.isArray(okdata)) {
logdata = okdata;
fill_logtablebody(okdata);
}
}, (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 }));
} else console.log("regetSoundbankFiles: okdata is not array");
}, (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(", "));
} else console.log("getVoiceTypes: okdata is not array");
}, (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(", "));
} else console.log("getCategories: okdata is not array");
}, (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(", ") );
} else console.log("getLanguages: okdata is not array");
}, (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(", ") );
} else console.log("getScheduledDays: okdata is not array");
}, (errdata) => {
alert("Error loading scheduled days: " + errdata.message);
alert("Error loading scheduled days : " + errdata.message);
});
}
@@ -729,7 +732,8 @@ $(document).ready(function () {
reloadSoundBank(APIURL);
$('#findsoundbank').on('input', function () {
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));
fill_soundbanktablebody(filtered);
} else {
@@ -739,14 +743,12 @@ $(document).ready(function () {
});
$btnClear.click(() => {
DoClear(APIURL, "Soundbank", (okdata) => {
alert("Success clear soundbank" + okdata.message);
soundbankdata = []
selectedsoundrow = null;
fill_soundbanktablebody(soundbankdata);
reloadSoundBank(APIURL);
alert("Success clear soundbank : " + okdata.message);
}, (errdata) => {
alert("Error clear soundbank: " + errdata.message);
alert("Error clear soundbank : " + errdata.message);
});
});
$btnAdd.click(() => {
$('.js-example-basic-single').select2({
@@ -779,12 +781,10 @@ $(document).ready(function () {
}
if (confirm(`Are you sure to delete soundbank [${sb.index}] Description=${sb.description} Tag=${sb.tag}?`)) {
fetchAPI(APIURL + "DeleteByIndex/" + sb.index, "DELETE", {}, null, (okdata) => {
alert("Success delete soundbank" + okdata.message);
soundbankdata = soundbankdata.filter(item => item.index !== sb.index);
selectedsoundrow = null;
fill_soundbanktablebody(soundbankdata);
reloadSoundBank(APIURL);
alert("Success delete soundbank : " + okdata.message);
}, (errdata) => {
alert("Error delete soundbank: " + errdata.message);
alert("Error delete soundbank : " + errdata.message);
});
}
}
@@ -813,17 +813,18 @@ $(document).ready(function () {
}
});
$btnExport.click(() => {
DoExport(APIURL, "soundbank.xlsx",{});
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);
alert("Error importing soundbank from XLSX : " + errdata.message);
});
});
} else {
console.error("Error loading soundbank content:", xhr.status, xhr.statusText);
console.error("Error loading soundbank content : ", xhr.status, xhr.statusText);
}
});
@@ -845,19 +846,30 @@ $(document).ready(function () {
$btnRemove.prop('disabled', true);
$btnEdit.prop('disabled', true);
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);
$btnClear.click(() => {
DoClear(APIURL, "Messagebank", (okdata) => {
alert("Success clear messagebank" + okdata.message);
messagebankdata = []
selectedmessagerow = null;
fill_messagebanktablebody(messagebankdata);
reloadMessageBank(APIURL);
alert("Success clear messagebank : " + okdata.message);
}, (errdata) => {
alert("Error clear messagebank: " + errdata.message);
alert("Error clear messagebank : " + errdata.message);
});
});
$btnAdd.click(() => {
let $modal = $('#messagebankmodal');
@@ -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} `)) {
fetchAPI(APIURL + "DeleteByIndex/" + mb.index, "DELETE", {}, null, (okdata) => {
alert("Success delete messagebank" + okdata.message);
messagebankdata = messagebankdata.filter(item => item.index !== mb.index);
selectedmessagerow = null;
fill_messagebanktablebody(messagebankdata);
reloadMessageBank(APIURL);
alert("Success delete messagebank : " + okdata.message);
}, (errdata) => {
alert("Error delete messagebank: " + errdata.message);
alert("Error delete messagebank : " + errdata.message);
});
}
}
@@ -921,17 +931,18 @@ $(document).ready(function () {
}
});
$btnExport.click(() => {
DoExport(APIURL, "messagebank.xlsx",{});
DoExport(APIURL, "messagebank.xlsx", {});
});
$btnImport.click(() => {
DoImport(APIURL, (okdata) => {
reloadMessageBank(APIURL);
alert("Success import messagebank : " + okdata.message);
}, (errdata) => {
alert("Error importing messagebank from XLSX: " + errdata.message);
alert("Error importing messagebank from XLSX : " + errdata.message);
});
});
} 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);
$btnEdit.prop('disabled', true);
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);
$btnClear.click(() => {
DoClear(APIURL, "LanguageLink", (okdata) => {
alert("Success clear languageLink" + okdata.message);
languagebankdata = []
selectedlanguagerow = null;
fill_languagebanktablebody(languagebankdata);
reloadLanguageBank(APIURL);
alert("Success clear languageLink : " + okdata.message);
}, (errdata) => {
alert("Error clear languagebank: " + errdata.message);
alert("Error clear languageLink : " + errdata.message);
});
});
$btnAdd.click(() => {
// show modal with id 'languagemodal'
let $modal = $('#languagemodal');
$modal.modal('show');
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');
clearLanguageModal();
// save button click event
$modal.off('click.languagelinksave').on('click.languagelinksave', '#languagelinksave', function () {
@@ -1007,10 +1039,10 @@ $(document).ready(function () {
language: langString
}
fetchAPI(APIURL + "Add", "POST", {}, ll, (okdata) => {
alert("Success add language" + okdata.message);
alert("Success add language : " + okdata.message);
reloadLanguageBank(APIURL);
}, (errdata) => {
alert("Error add language: " + errdata.message);
alert("Error add language : " + errdata.message);
});
$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}?`)) {
fetchAPI(APIURL + "DeleteByIndex/" + ll.index, "DELETE", {}, null, (okdata) => {
alert("Success delete language" + okdata.message);
languagebankdata = languagebankdata.filter(item => item.index !== ll.index);
selectedlanguagerow = null;
fill_languagebanktablebody(languagebankdata);
reloadLanguageBank(APIURL);
alert("Success delete language : " + okdata.message);
}, (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()
}
if (confirm(`Are you sure to edit language [${ll.index}] Tag=${ll.tag} Language=${ll.language}?`)) {
let $modal = $('#languagemodal');
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');
let $langtag = $modal.find('#languagelinktag');
let $langid = $modal.find('#languagelinkindex');
clearLanguageModal();
$langid.val(ll.index);
$langtag.val(ll.tag);
let langs = ll.language.toUpperCase().split(';');
@@ -1099,10 +1122,10 @@ $(document).ready(function () {
ll.tag = tag;
ll.language = langString;
fetchAPI(APIURL + "UpdateByIndex/" + ll.index, "PATCH", {}, ll, (okdata) => {
alert("Success edit language" + okdata.message);
reloadLanguageBank(APIURL);
alert("Success edit language : " + okdata.message);
}, (errdata) => {
alert("Error edit language: " + errdata.message);
alert("Error edit language : " + errdata.message);
});
$modal.modal('hide');
@@ -1117,19 +1140,20 @@ $(document).ready(function () {
}
});
$btnExport.click(() => {
DoExport(APIURL, "languagebank.xlsx",{});
DoExport(APIURL, "languagebank.xlsx", {});
});
$btnImport.click(() => {
DoImport(APIURL, (okdata) => {
reloadLanguageBank(APIURL);
alert("Success import languagebank : " + okdata.message);
}, (errdata) => {
alert("Error importing languagebank from XLSX: " + errdata.message);
alert("Error importing languagebank from XLSX : " + errdata.message);
});
});
} 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);
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);
$btnClear.click(() => {
DoClear(APIURL, "Timerbank", (okdata) => {
alert("Success clear schedulebank" + okdata.message);
schedulebankdata = []
selectedschedulerow = null;
fill_schedulebanktablebody(schedulebankdata);
reloadTimerBank(APIURL);
alert("Success clear schedulebank : " + okdata.message);
}, (errdata) => {
alert("Error clear schedulebank: " + errdata.message);
alert("Error clear schedulebank : " + errdata.message);
});
});
$btnAdd.click(() => {
//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(() => {
if (selectedtimerow) {
@@ -1184,12 +1343,10 @@ $(document).ready(function () {
}
if (confirm(`Are you sure to delete schedule [${sr.index}] Description=${sr.description}?`)) {
fetchAPI(APIURL + "DeleteByIndex/" + sr.index, "DELETE", {}, null, (okdata) => {
alert("Success delete schedule" + okdata.message);
schedulebankdata = schedulebankdata.filter(item => item.index !== sr.index);
selectedtimerow = null;
fill_schedulebanktablebody(schedulebankdata);
reloadTimerBank(APIURL);
alert("Success delete schedule : " + okdata.message);
}, (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()
}
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(() => {
DoExport(APIURL, "schedulebank.xlsx",{});
DoExport(APIURL, "schedulebank.xlsx", {});
});
$btnImport.click(() => {
DoImport(APIURL, (okdata) => {
reloadTimerBank(APIURL);
alert("Success import schedulebank from XLSX : " + okdata.message);
}, (errdata) => {
alert("Error importing schedulebank from XLSX: " + errdata.message);
alert("Error importing schedulebank from XLSX : " + errdata.message);
});
});
} 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);
});
$btnExport.off('click').on('click', function () {
DoExport(APIURL, "log.xlsx",{date:selectedlogdate,filter:logfilter});
DoExport(APIURL, "log.xlsx", { date: selectedlogdate, filter: logfilter });
});
} else {

View File

@@ -16,6 +16,13 @@
<h2 style="text-align: center;">Language Link</h2>
</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="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>

View File

@@ -16,6 +16,13 @@
<h2 style="text-align: center;">Message Bank</h2>
</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="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>

View File

@@ -16,6 +16,13 @@
<h2 style="text-align: center;">Schedule Bank</h2>
</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="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>
@@ -59,58 +66,110 @@
<div class="col-4 col-sm-3">
<p class="text-add">Index</p>
</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 class="row">
<div class="col-4 col-sm-3">
<p class="text-add">Description</p>
</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 class="row">
<div class="col-4 col-sm-3">
<p class="text-add">Day</p>
</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 class="row">
<div class="col-4 col-sm-3">
<p class="text-add">Time</p>
</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 class="row">
<div class="col-4 col-sm-3">
<p class="text-add">Sound Path</p>
</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 class="row">
<div class="col-4 col-sm-3">
<p class="text-add">Repeat</p>
</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 class="row">
<div class="col-4 col-sm-3">
<p class="text-add">Enable</p>
</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 class="row">
<div class="col-4 col-sm-3">
<p class="text-add">Broadcast Zones</p>
</div>
<div class="col">
<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 class="col border p-2" id="schedulezones"></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>

View File

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

View File

@@ -222,15 +222,15 @@ class MariaDB(
*/
fun GetLogForHtml(date: String, consumer: Consumer<ArrayList<Log>>) {
val logList = ArrayList<Log>()
println("GetLogForHtml Date: $date" )
//println("GetLogForHtml Date: $date" )
if (ValiDateForLogHtml(date)) {
try {
// must convert from DD-MM-YYYY to DD/MM/YYYY, because in database we use DD/MM/YYYY
val adjusteddate = date.replace("-", "/")
val statement = connection?.prepareStatement("SELECT * FROM logs WHERE datenya = ?")
statement?.setString(1, adjusteddate)
println("GetLogForHtml Date: $adjusteddate" )
println("GetLogForHtml SQL: " +statement?.toString())
//println("GetLogForHtml Date: $adjusteddate" )
// println("GetLogForHtml SQL: " +statement?.toString())
val resultSet = statement?.executeQuery()
while (resultSet?.next() == true) {
val log = Log(
@@ -258,7 +258,7 @@ class MariaDB(
*/
fun GetLogForHtml(date: String, filter: String, consumer: Consumer<ArrayList<Log>>) {
val logList = ArrayList<Log>()
println("GetLogForHtml Date: $date Filter: $filter" )
//println("GetLogForHtml Date: $date Filter: $filter" )
if (ValiDateForLogHtml(date)) {
try {
@@ -268,8 +268,8 @@ class MariaDB(
connection?.prepareStatement("SELECT * FROM logs WHERE datenya = ? AND description LIKE ?")
statement?.setString(1, adjusteddate)
statement?.setString(2, "%$filter%")
println("GetLogForHtml Date: $adjusteddate , Filter=$filter" )
println("GetLogForHtml SQL: " +statement?.toString())
//println("GetLogForHtml Date: $adjusteddate , Filter=$filter" )
//println("GetLogForHtml SQL: " +statement?.toString())
val resultSet = statement?.executeQuery()
while (resultSet?.next() == true) {
val log = Log(
@@ -457,6 +457,29 @@ class MariaDB(
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.
*/
@@ -695,6 +718,29 @@ class MariaDB(
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.
*/
@@ -945,6 +991,29 @@ class MariaDB(
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.
*/
@@ -1173,6 +1242,29 @@ class MariaDB(
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.
* @return An XSSFWorkbook containing the messagebank data.
@@ -1527,6 +1619,29 @@ class MariaDB(
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.
*/

View File

@@ -3,7 +3,6 @@ package web
import codes.Somecodes
import codes.Somecodes.Companion.ListAudioFiles
import codes.Somecodes.Companion.ValiDateForLogHtml
import codes.Somecodes.Companion.ValidDate
import codes.Somecodes.Companion.ValidFile
import codes.Somecodes.Companion.ValidScheduleDay
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 password = it.formParam("password")
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
}
// Check if user exists in userlist
val user = userlist.find { it.first == username && it.second == password }
if (user == null) {
it.status(401).result("Invalid username or password")
it.status(401).result(objectmapper.writeValueAsString(resultMessage("Invalid username or password")))
return@post
}
// Set user session
@@ -208,40 +207,43 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
if (!exists) {
if (ValidFile(addvalue.Path)) {
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)
.result("Failed to add soundbank to database")
.result(objectmapper.writeValueAsString(resultMessage("Failed to add soundbank to database")))
} 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)
.result("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(mapOf("message" to "Invalid Language")))
} else it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid Category")))
} else it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid TAG")))
} else it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid Description")))
.result(objectmapper.writeValueAsString(resultMessage("TAG=${addvalue.TAG} already exists for the same Language=${addvalue.Language} and Category=${addvalue.Category}")))
} else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Path")))
} else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Language")))
} else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Category")))
} else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid TAG")))
} else it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Description")))
} catch (_: Exception) {
it.status(400).result("Invalid request body")
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid request body")))
}
}
delete("List") {
// truncate soundbank table
if (db.Clear_Soundbank()) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK")))
db.Reload_Soundbank()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} 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 by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index")))
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
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 {
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()
if (index == null) {
// 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 {
val sb = db.SoundbankList.find { xx -> xx.index == index }
if (sb == null) {
// 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 {
// soundbank dengan index tersebut ditemukan, sekarang update
val json: JsonNode = objectmapper.readTree(it.body())
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 {
val _description = json.get("Description").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
changed = true
} else {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid Category")))
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Category")))
return@patch
}
}
@@ -296,16 +298,17 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
sb.Path = _path
changed = true
} 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
}
}
if (changed) {
if (db.Update_Soundbank_by_index(index, sb)) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK")))
} else it.status(500).result("Failed to update soundbank with index $index")
db.Resort_Soundbank_by_Description()
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)
.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)
}
} 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") {
val uploaded = it.uploadedFile("file")
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
}
try {
val xlsx = XSSFWorkbook(uploaded.content())
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 {
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) {
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") {
// truncate messagebank table
if (db.Clear_Messagebank()) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK")))
db.Reload_Messagebank()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} 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 by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index")))
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
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 {
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
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index")))
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
val mb = db.MessagebankList.find { xx -> xx.index == index }
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 {
val json: JsonNode = objectmapper.readTree(it.body())
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 {
val _description = json.get("Description").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
changed = true
} 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
}
}
@@ -425,11 +431,12 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
}
if (changed) {
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)
.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)
.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)
}
} 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") {
val uploaded = it.uploadedFile("file")
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
}
try {
val xlsx = XSSFWorkbook(uploaded.content())
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 {
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) {
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 tag = json.get("tag").asText()
val languages = json.get("language").asText().split(";")
println("Add Language Link, tag=$tag, languages=$languages")
if (ValidString(tag)){
if (languages.all { xx -> Language.entries.any { yy -> yy.name== xx} }){
if (db.LanguageLinkList.any { ll -> ll.TAG==tag }){
if (languages.all { xx -> Language.entries.any { yy -> yy.name.equals(xx,true)} }){
if (!db.LanguageLinkList.any { ll -> ll.TAG.equals(tag,true) }) {
val newvalue = LanguageLink(0u, tag, languages.joinToString(";"))
if (db.Add_LanguageLink(newvalue)){
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK")))
} else it.status(500).result(objectmapper.writeValueAsString(mapOf("message" to "Failed to add language link to database")))
} else it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "TAG=$tag already exists")))
} else it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Contains unsupported language")))
} else it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid tag or language")))
db.Resort_LanguageLink_by_TAG()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else {
it.status(500).result(objectmapper.writeValueAsString(resultMessage("Failed to add language link to database")))
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") {
// truncate language link table
if (db.Clear_LanguageLink()) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK")))
db.Reload_LanguageLink()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} 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 by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index")))
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
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 {
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
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index")))
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
val ll = db.LanguageLinkList.find { xx -> xx.index == index }
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 {
val json: JsonNode = objectmapper.readTree(it.body())
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 {
val _tag = json.get("tag").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 (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)
.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)
.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)
}
} 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") {
val uploaded = it.uploadedFile("file")
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
}
try {
val xlsx = XSSFWorkbook(uploaded.content())
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 {
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) {
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") {
// truncate timer table
if (db.Clear_Schedulebank()) {
it.result(objectmapper.writeValueAsString(mapOf("message" to "OK")))
db.Reload_Schedulebank()
it.result(objectmapper.writeValueAsString(resultMessage("OK")))
} 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 by index
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index")))
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
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 {
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
val index = it.pathParam("index").toUIntOrNull()
if (index == null) {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid index")))
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid index")))
} else {
val sb = db.SchedulebankList.find { xx -> xx.index == index }
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 {
val json: JsonNode = objectmapper.readTree(it.body())
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 {
val _description = json.get("Description").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
changed = true
} 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
}
}
@@ -645,7 +673,7 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
sb.Day = _day
changed = true
} else {
it.status(400).result("Invalid Day format")
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Day format")))
return@patch
}
}
@@ -670,17 +698,18 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
sb.Language = _language
changed = true
} else {
it.status(400).result(objectmapper.writeValueAsString(mapOf("message" to "Invalid Language")))
it.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid Language")))
return@patch
}
}
if (changed) {
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)
.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)
.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)
}
} 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") {
val uploaded = it.uploadedFile("file")
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
}
try {
val xlsx = XSSFWorkbook(uploaded.content())
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 {
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) {
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 {
println("Invalid logdate=$logdate")
get1.status(400).result("Invalid logdate")
get1.status(400).result(objectmapper.writeValueAsString(resultMessage("Invalid logdate")))
}
}
get("ExportXLSX") { get1 ->
@@ -758,11 +788,86 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
xlsxdata.write(out)
}
} 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)

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

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