From 09b65738af5910ca4b879b2cfc26f4dec379a84c Mon Sep 17 00:00:00 2001 From: rdkartono Date: Tue, 26 Aug 2025 16:13:37 +0700 Subject: [PATCH] commit 26/08/2025 --- html/webpage/assets/js/script.js | 435 +++++++++++++++++++++++++++++-- html/webpage/language.html | 50 +++- html/webpage/messagebank.html | 38 ++- html/webpage/soundbank.html | 54 ++++ html/webpage/timer.html | 80 +++++- src/web/WebApp.kt | 33 ++- 6 files changed, 638 insertions(+), 52 deletions(-) diff --git a/html/webpage/assets/js/script.js b/html/webpage/assets/js/script.js index 57cab44..f61f4c7 100644 --- a/html/webpage/assets/js/script.js +++ b/html/webpage/assets/js/script.js @@ -1,11 +1,67 @@ +/** + * @typedef {Object} SoundBank + * @property {number} index + * @property {string} description + * @property {string} tag + * @property {string} category + * @property {string} language + * @property {string} voiceType + * @property {string} path + */ + +/** + * @typedef {Object} MessageBank + * @property {number} index + * @property {string} description + * @property {string} language + * @property {number} aNN_ID + * @property {string} voice_Type + * @property {string} message_Detail + * @property {string} message_TAGS + */ + +/** + * @typedef {Object} LanguageBank + * @property {number} index + * @property {string} tag + * @property {string} language + * @ + */ + +/** + * @typedef {Object} ScheduleBank + * @property {number} index + * @property {string} description + * @property {string} day + * @property {string} time + * @property {string} soundpath + * @property {number} repeat + * @property {boolean} enable + * @property {string} broadcastZones + * @property {string} language + */ + +/** + * @typedef {Object} Log + * @property {number} index + * @property {string} datenya + * @property {string} timenya + * @property {string} machine + * @property {string} description + */ + $(document).ready(function () { document.title = "Automatic Announcement System" $('#onlineindicator').attr('src', '/assets/img/red_circle.png'); let soundbankdata = []; + let selectedsoundrow = null; let messagebankdata = []; + let selectedmessagerow = null; let languagebankdata = []; + let selectedlanguagerow = null; let schedulebankdata = []; + let selectedschedulerow = null; let logdata = []; /** @@ -25,14 +81,30 @@ $(document).ready(function () { ${item.path} `; $('#soundbanktablebody').append(row); + let $addedrow = $('#soundbanktablebody tr:last'); + $addedrow.on('click', function () { + if (selectedsoundrow) { + selectedsoundrow.find('td').css('background-color', ''); + if (selectedsoundrow.is($(this))) { + selectedsoundrow = null; + $('#btnRemove').prop('disabled', true); + $('#btnEdit').prop('disabled', true); + return; + } + } + $(this).find('td').css('background-color', '#ffeeba'); + selectedsoundrow = $(this); + $('#btnRemove').prop('disabled', false); + $('#btnEdit').prop('disabled', false); + }); }); $('#tablesize').text("Table Size: " + vv.length); } /** - * Fill messagebank table body with values - * @param {MessageBank[]} vv values to fill - */ + * Fill messagebank table body with values + * @param {MessageBank[]} vv values to fill + */ function fill_messagebanktablebody(vv) { $('#messagebanktablebody').empty(); vv.forEach(item => { @@ -46,53 +118,110 @@ $(document).ready(function () { ${item.message_TAGS} `; $('#messagebanktablebody').append(row); + let $addedrow = $('#messagebanktablebody tr:last'); + $addedrow.click(function () { + if (selectedmessagerow) { + selectedmessagerow.find('td').css('background-color', ''); + if (selectedmessagerow.is($(this))) { + selectedmessagerow = null; + $('#btnRemove').prop('disabled', true); + $('#btnEdit').prop('disabled', true); + return; + } + } + $addedrow.find('td').css('background-color', '#ffeeba'); + selectedmessagerow = $addedrow; + $('#btnRemove').prop('disabled', false); + $('#btnEdit').prop('disabled', false); + }); }); console.log("loaded " + vv.length + " messagebank items"); } + /** + * Fill languagebank table body with values + * @param {LanguageBank[]} vv values to fill + */ function fill_languagebanktablebody(vv) { $('#languagebanktablebody').empty(); vv.forEach(item => { - //TODO examine JSON structure const row = ` ${item.index} - ${item.description} + ${item.tag} ${item.language} - ${item.aNN_ID} - ${item.voice_Type} - ${item.message_Detail} - ${item.message_TAGS} `; $('#languagebanktablebody').append(row); + let $addedrow = $('#languagebanktablebody tr:last'); + $addedrow.click(function () { + if (selectedlanguagerow) { + selectedlanguagerow.find('td').css('background-color', ''); + if (selectedlanguagerow.is($(this))) { + selectedlanguagerow = null; + $('#btnRemove').prop('disabled', true); + $('#btnEdit').prop('disabled', true); + return; + } + } + $addedrow.find('td').css('background-color', '#ffeeba'); + selectedlanguagerow = $addedrow; + $('#btnRemove').prop('disabled', false); + $('#btnEdit').prop('disabled', false); + }); }); console.log("loaded " + vv.length + " languagebank items"); } + /** + * Fill schedulebank table body with values + * @param {ScheduleBank[]} vv values to fill + */ function fill_schedulebanktablebody(vv) { $('#schedulebanktablebody').empty(); - //TODO examine JSON structure vv.forEach(item => { const row = ` ${item.index} ${item.description} + ${item.day} + ${item.time} + ${item.soundpath} + ${item.repeat} + ${item.enable} + ${item.broadcastZones} ${item.language} - ${item.aNN_ID} - ${item.voice_Type} - ${item.message_Detail} - ${item.message_TAGS} `; $('#schedulebanktablebody').append(row); + let $addedrow = $('#schedulebanktablebody tr:last'); + $addedrow.click(function () { + if (selectedschedulerow) { + selectedschedulerow.find('td').css('background-color', ''); + if (selectedschedulerow.is($(this))) { + selectedschedulerow = null; + $('#btnRemove').prop('disabled', true); + $('#btnEdit').prop('disabled', true); + return; + } + } + $addedrow.find('td').css('background-color', '#ffeeba'); + selectedschedulerow = $addedrow; + $('#btnRemove').prop('disabled', false); + $('#btnEdit').prop('disabled', false); + }); }); console.log("loaded " + vv.length + " schedulebank items"); } + /** + * Fill log table body with values + * @param {Log[]} vv values to fill + */ function fill_logtablebody(vv) { $('#logtablebody').empty(); vv.forEach(item => { const row = ` ${item.index} - ${item.date} - ${item.time} + ${item.datenya} + ${item.timenya} + ${item.machine} ${item.description} `; $('#logtablebody').append(row); @@ -150,7 +279,7 @@ $(document).ready(function () { ); fill_soundbanktablebody(filtered); } - + }); } else { $soundbankfilter.prop('disabled', true); @@ -198,6 +327,30 @@ $(document).ready(function () { console.log("Setting:"); console.log(data); break; + case "clearSoundBank": + soundbankdata = []; + selectedsoundrow = null; + fill_soundbanktablebody(soundbankdata); + alert(`Clear SoundBank Result : ${data}`); + break; + case "clearMessageBank": + messagebankdata = []; + selectedmessagerow = null; + fill_messagebanktablebody(messagebankdata); + alert(`Clear MessageBank Result : ${data}`); + break; + case "clearLanguageBank": + languagebankdata = []; + selectedlanguagerow = null; + fill_languagebanktablebody(languagebankdata); + alert(`Clear LanguageBank Result : ${data}`); + break; + case "clearTimerBank": + schedulebankdata = []; + selectedschedulerow = null; + fill_schedulebanktablebody(schedulebankdata); + alert(`Clear ScheduleBank Result : ${data}`); + break; } } }; @@ -231,16 +384,85 @@ $(document).ready(function () { }, 1000) let sidemenu = new bootstrap.Offcanvas('#offcanvas-menu'); - $('#showmenu').click(() => { - sidemenu.show(); - }) + $('#showmenu').click(() => { sidemenu.show(); }) + + $('#soundbanklink').click(() => { sidemenu.hide(); $('#content').load('soundbank.html', function (response, status, xhr) { if (status === "success") { console.log("Soundbank content loaded successfully"); - sendCommand("getSoundBankList", ""); + // initialize first state of buttons and text input + $('#soundbanktablebody').empty(); + selectedsoundrow = null; + let $btnRemove = $('#btnRemove'); + let $btnEdit = $('#btnEdit'); + let $modal = $('#soundbankmodal'); + $btnRemove.prop('disabled', true); + $btnEdit.prop('disabled', true); + + sendCommand("getSoundBankList", ""); + $('#btnClear').click(() => { + if (confirm(`Are you sure want to clear Soundbank ? This procedure is not reversible`)) { + sendCommand("clearSoundBank", ""); + } + }); + $('#btnAdd').click(() => { + $modal.modal('show'); + $modal.off('hidden.bs.modal').on('hidden.bs.modal', function () { + const desc = $('#description').val(); + console.log('Description input value:', desc); + // You can use desc here (e.g., send to server) + }); + }); + $btnRemove.click(() => { + if (selectedsoundrow) { + let cells = selectedsoundrow.find('td'); + /** @type {SoundBank} */ + let sb = { + index: cells.eq(0).text(), + description: cells.eq(1).text(), + tag: cells.eq(2).text(), + category: cells.eq(3).text(), + language: cells.eq(4).text(), + voiceType: cells.eq(5).text(), + path: cells.eq(6).text() + } + if (confirm(`Are you sure to delete soundbank [${sb.index}] Description=${sb.description} Tag=${sb.tag}?`)) { + sendCommand("deleteSoundBank", sb); + } + } + }); + $btnEdit.click(() => { + if (selectedsoundrow) { + let cells = selectedsoundrow.find('td'); + /** @type {SoundBank} */ + let sb = { + index: cells.eq(0).text(), + description: cells.eq(1).text(), + tag: cells.eq(2).text(), + category: cells.eq(3).text(), + language: cells.eq(4).text(), + voiceType: cells.eq(5).text(), + path: cells.eq(6).text() + } + if (confirm(`Are you sure to edit soundbank [${sb.index}] Description=${sb.description} Tag=${sb.tag}?`)) { + $modal.modal('show'); + $modal.off('hidden.bs.modal').on('hidden.bs.modal', function () { + const desc = $('#description').val(); + console.log('Description input value:', desc); + // You can use desc here (e.g., send to server) + }); + } + } + }); + $('#btnExport').click(() => { + alert("Feature disabled for now"); + }); + $('#btnImport').click(() => { + alert("Feature disabled for now"); + }); } else { console.error("Error loading soundbank content:", xhr.status, xhr.statusText); } @@ -252,7 +474,66 @@ $(document).ready(function () { $('#content').load('messagebank.html', function (response, status, xhr) { if (status === "success") { console.log("Messagebank content loaded successfully"); + // initialize first state of buttons and text input + $('#messagebanktablebody').empty(); + selectedmessagerow = null; + let $btnRemove = $('#btnRemove'); + let $btnEdit = $('#btnEdit'); + $btnRemove.prop('disabled', true); + $btnEdit.prop('disabled', true); + sendCommand("getMessageBankList", ""); + $('#btnClear').click(() => { + if (confirm(`Are you sure want to clear Messagebank ? This procedure is not reversible`)) { + sendCommand("clearMessageBank", ""); + } + }); + $('#btnAdd').click(() => { + //TODO form add messagebank + }); + $btnRemove.click(() => { + if (selectedmessagerow) { + let cells = selectedmessagerow.find('td'); + /** @type {MessageBank} */ + let mb = { + index: cells.eq(0).text(), + description: cells.eq(1).text(), + language: cells.eq(2).text(), + aNN_ID: parseInt(cells.eq(3).text()), + voice_Type: cells.eq(4).text(), + message_Detail: cells.eq(5).text(), + message_TAGS: cells.eq(6).text() + } + + if (confirm(`Are you sure to delete messagebank [${mb.index}] Description=${mb.description}? ANN_ID=${mb.aNN_ID} Language=${mb.language} Voice_Type=${mb.voice_Type} `)) { + sendCommand("deleteMessageBank", mb); + } + } + }); + $btnEdit.click(() => { + if (selectedmessagerow) { + let cells = selectedmessagerow.find('td'); + /** @type {MessageBank} */ + let mb = { + index: cells.eq(0).text(), + description: cells.eq(1).text(), + language: cells.eq(2).text(), + aNN_ID: parseInt(cells.eq(3).text()), + voice_Type: cells.eq(4).text(), + message_Detail: cells.eq(5).text(), + message_TAGS: cells.eq(6).text() + } + if (confirm(`Are you sure to edit messagebank [${mb.index}] Description=${mb.description} ANN_ID=${mb.aNN_ID} Language=${mb.language} Voice_Type=${mb.voice_Type} `)) { + //TODO send edit command + } + } + }); + $('#btnExport').click(() => { + alert("Feature disabled for now"); + }); + $('#btnImport').click(() => { + alert("Feature disabled for now"); + }); } else { console.error("Error loading messagebank content:", xhr.status, xhr.statusText); } @@ -264,7 +545,57 @@ $(document).ready(function () { $('#content').load('language.html', function (response, status, xhr) { if (status === "success") { console.log("Language content loaded successfully"); + // initialize first state of buttons and text input + $('#languagebanktablebody').empty(); + selectedlanguagerow = null; + let $btnRemove = $('#btnRemove'); + let $btnEdit = $('#btnEdit'); + $btnRemove.prop('disabled', true); + $btnEdit.prop('disabled', true); + sendCommand("getLanguageList", ""); + $('#btnClear').click(() => { + if (confirm(`Are you sure want to clear Languagebank ? This procedure is not reversible`)) { + sendCommand("clearLanguageBank", ""); + } + }); + $('#btnAdd').click(() => { + //TODO form add language + }); + $btnRemove.click(() => { + if (selectedlanguagerow) { + let cells = selectedlanguagerow.find('td'); + /** @type {Language} */ + let ll = { + index: cells.eq(0).text(), + tag: cells.eq(1).text(), + language: cells.eq(2).text() + } + if (confirm(`Are you sure to delete language [${ll.index}] Tag=${ll.tag} Language=${ll.language}?`)) { + sendCommand("deleteLanguage", ll); + } + } + }); + $btnEdit.click(() => { + if (selectedlanguagerow) { + let cells = selectedlanguagerow.find('td'); + /** @type {Language} */ + let ll = { + index: cells.eq(0).text(), + tag: cells.eq(1).text(), + language: cells.eq(2).text() + } + if (confirm(`Are you sure to edit language [${ll.index}] Tag=${ll.tag} Language=${ll.language}?`)) { + //TODO send edit command + } + } + }); + $('#btnExport').click(() => { + alert("Feature disabled for now"); + }); + $('#btnImport').click(() => { + alert("Feature disabled for now"); + }); } else { console.error("Error loading language content:", xhr.status, xhr.statusText); } @@ -275,7 +606,69 @@ $(document).ready(function () { $('#content').load('timer.html', function (response, status, xhr) { if (status === "success") { console.log("Timer content loaded successfully"); + // initialize first state of buttons and text input + $('#schedulebanktablebody').empty(); + selectedschedulerow = null; + let $btnEdit = $('#btnEdit'); + let $btnRemove = $('#btnRemove'); + $btnEdit.prop('disabled', true); + $btnRemove.prop('disabled', true); + sendCommand("getTimerList", ""); + $('#btnClear').click(() => { + if (confirm(`Are you sure want to clear Timerbank ? This procedure is not reversible`)) { + sendCommand("clearTimerBank", ""); + } + }); + $('#btnAdd').click(() => { + //TODO form add timer + }); + $btnRemove.click(() => { + if (selectedtimerow) { + let cells = selectedtimerow.find('td'); + /** @type {ScheduleBank} */ + let sr = { + index: cells.eq(0).text(), + description: cells.eq(1).text(), + day: cells.eq(2).text(), + time: cells.eq(3).text(), + soundpath: cells.eq(4).text(), + repeat: cells.eq(5).text(), + enable: cells.eq(6).text(), + broadcastZones: cells.eq(7).text(), + language: cells.eq(8).text() + } + if (confirm(`Are you sure to delete schedule [${sr.index}] Description=${sr.description}?`)) { + sendCommand("deleteSchedule", sr); + } + } + }); + $btnEdit.click(() => { + if (selectedtimerow) { + let cells = selectedtimerow.find('td'); + /** @type {ScheduleBank} */ + let sr = { + index: cells.eq(0).text(), + description: cells.eq(1).text(), + day: cells.eq(2).text(), + time: cells.eq(3).text(), + soundpath: cells.eq(4).text(), + repeat: cells.eq(5).text(), + enable: cells.eq(6).text(), + broadcastZones: cells.eq(7).text(), + language: cells.eq(8).text() + } + if (confirm(`Are you sure to edit schedule [${sr.index}] Description=${sr.description}?`)) { + //TODO send edit command + } + } + }); + $('#btnExport').click(() => { + alert("Feature disabled for now"); + }); + $('#btnImport').click(() => { + alert("Feature disabled for now"); + }); } else { console.error("Error loading timer content:", xhr.status, xhr.statusText); } diff --git a/html/webpage/language.html b/html/webpage/language.html index 5f6cf73..231e95a 100644 --- a/html/webpage/language.html +++ b/html/webpage/language.html @@ -15,6 +15,14 @@

Language Link

+
+
+
+
+
+
+
+
@@ -52,13 +60,41 @@
-
-
-
-
-
-
-
+ diff --git a/html/webpage/messagebank.html b/html/webpage/messagebank.html index d563ee3..790281c 100644 --- a/html/webpage/messagebank.html +++ b/html/webpage/messagebank.html @@ -15,6 +15,14 @@

Message Bank

+
+
+
+
+
+
+
+
@@ -52,13 +60,29 @@
-
-
-
-
-
-
-
+ diff --git a/html/webpage/soundbank.html b/html/webpage/soundbank.html index da10250..0a7a480 100644 --- a/html/webpage/soundbank.html +++ b/html/webpage/soundbank.html @@ -71,6 +71,60 @@
+ diff --git a/html/webpage/timer.html b/html/webpage/timer.html index d2a8fd3..9cb003a 100644 --- a/html/webpage/timer.html +++ b/html/webpage/timer.html @@ -15,6 +15,14 @@

Timer

+
+
+
+
+
+
+
+
@@ -52,13 +60,71 @@
-
-
-
-
-
-
-
+ diff --git a/src/web/WebApp.kt b/src/web/WebApp.kt index 55684df..9d8491a 100644 --- a/src/web/WebApp.kt +++ b/src/web/WebApp.kt @@ -10,6 +10,7 @@ import io.javalin.apibuilder.ApiBuilder.path import io.javalin.apibuilder.ApiBuilder.post import io.javalin.apibuilder.ApiBuilder.ws import io.javalin.http.Context +import io.javalin.websocket.WsMessageContext import java.time.LocalDateTime @Suppress("unused") @@ -17,6 +18,16 @@ class WebApp(val listenPort: Int, val userlist: List>, val var app : Javalin? = null val objectmapper = jacksonObjectMapper() + + private fun SendReply(context: WsMessageContext, command: String, value: String) { + try { + if (context.session.isOpen) { + context.send(objectmapper.writeValueAsString(WebsocketReply(command, value))) + } + } catch (_: Exception) { + } + } + fun Start() { app = Javalin.create { config -> @@ -67,38 +78,38 @@ class WebApp(val listenPort: Int, val userlist: List>, val val cmd = objectmapper.readValue(wsMessageContext.message(), WebsocketCommand::class.java) when (cmd.command) { "getSystemTime" ->{ - wsMessageContext.send(objectmapper.writeValueAsString(WebsocketReply(cmd.command, LocalDateTime.now().format(Somecodes.datetimeformat1)))) + SendReply(wsMessageContext, cmd.command, LocalDateTime.now().format(Somecodes.datetimeformat1)) } "getCPUStatus" ->{ Somecodes.getCPUUsage { vv -> - wsMessageContext.send(objectmapper.writeValueAsString(WebsocketReply(cmd.command, vv))) + SendReply(wsMessageContext, cmd.command, vv ) } } "getMemoryStatus" ->{ - wsMessageContext.send(objectmapper.writeValueAsString(WebsocketReply(cmd.command, Somecodes.getMemoryUsage()))) + SendReply(wsMessageContext, cmd.command, Somecodes.getMemoryUsage()) } "getDiskStatus" ->{ - wsMessageContext.send(objectmapper.writeValueAsString(WebsocketReply(cmd.command, Somecodes.getDiskUsage()))) + SendReply(wsMessageContext, cmd.command, Somecodes.getDiskUsage()) } "getNetworkStatus" ->{ // TODO Get Network status - wsMessageContext.send(objectmapper.writeValueAsString(WebsocketReply(cmd.command,"OK"))) + SendReply(wsMessageContext, cmd.command, "OK") } "getSoundBankList" ->{ println("getSoundBankList command received") - wsMessageContext.send(objectmapper.writeValueAsString(WebsocketReply(cmd.command, MariaDB.ArrayListtoString(db.SoundbankList)))) + SendReply(wsMessageContext, cmd.command, MariaDB.ArrayListtoString(db.SoundbankList)) } "getMessageBankList"->{ println("getMessageBankList command received") - wsMessageContext.send(objectmapper.writeValueAsString(WebsocketReply(cmd.command, MariaDB.ArrayListtoString(db.MessagebankList))) ) + SendReply(wsMessageContext, cmd.command, MariaDB.ArrayListtoString(db.MessagebankList)) } "getLanguageList"->{ println("getLanguageList command received") - wsMessageContext.send(objectmapper.writeValueAsString(WebsocketReply(cmd.command, MariaDB.ArrayListtoString(db.LanguageLinkList)))) + SendReply(wsMessageContext, cmd.command, MariaDB.ArrayListtoString(db.LanguageLinkList)) } "getTimerList"->{ println("getTimerList command received") - wsMessageContext.send(objectmapper.writeValueAsString(WebsocketReply(cmd.command, MariaDB.ArrayListtoString(db.SchedulebankList)))) + SendReply(wsMessageContext, cmd.command, MariaDB.ArrayListtoString(db.SchedulebankList)) } "getLog" ->{ println("getLog command received") @@ -107,7 +118,7 @@ class WebApp(val listenPort: Int, val userlist: List>, val println("getSetting command received") } else -> { - wsMessageContext.send(objectmapper.writeValueAsString(WebsocketReply("error", "Unknown command: ${cmd.command}"))) + SendReply(wsMessageContext, cmd.command, "Unknown command") } } } catch (e: Exception){ @@ -152,6 +163,8 @@ class WebApp(val listenPort: Int, val userlist: List>, val } + + fun CheckUsers(ctx: Context){ val user = ctx.sessionAttribute("user") if (user == null) {