commit 10/09/2025

This commit is contained in:
2025-09-10 12:05:56 +07:00
parent 40f462ce79
commit f48ead1b44
12 changed files with 218 additions and 215 deletions

11
.idea/libraries/mysql_connector_j.xml generated Normal file
View File

@@ -0,0 +1,11 @@
<component name="libraryTable">
<library name="mysql.connector.j" type="repository">
<properties maven-id="com.mysql:mysql-connector-j:8.4.0" />
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/mysql/mysql-connector-j/8.4.0/mysql-connector-j-8.4.0.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/com/google/protobuf/protobuf-java/3.25.1/protobuf-java-3.25.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -16,7 +16,6 @@
<orderEntry type="library" name="tinylog.impl" level="project" /> <orderEntry type="library" name="tinylog.impl" level="project" />
<orderEntry type="library" name="net.java.dev.jna" level="project" /> <orderEntry type="library" name="net.java.dev.jna" level="project" />
<orderEntry type="library" name="io.javalin" level="project" /> <orderEntry type="library" name="io.javalin" level="project" />
<orderEntry type="library" name="mariadb.jdbc.java.client" level="project" />
<orderEntry type="library" name="kotlinx-coroutines-core" level="project" /> <orderEntry type="library" name="kotlinx-coroutines-core" level="project" />
<orderEntry type="library" name="slf4j.simple" level="project" /> <orderEntry type="library" name="slf4j.simple" level="project" />
<orderEntry type="library" name="fasterxml.jackson.module.kotlin" level="project" /> <orderEntry type="library" name="fasterxml.jackson.module.kotlin" level="project" />
@@ -35,5 +34,6 @@
<jarDirectory url="file://C:/SLC/Apache POI" recursive="false" type="SOURCES" /> <jarDirectory url="file://C:/SLC/Apache POI" recursive="false" type="SOURCES" />
</library> </library>
</orderEntry> </orderEntry>
<orderEntry type="library" name="mysql.connector.j" level="project" />
</component> </component>
</module> </module>

View File

@@ -212,7 +212,7 @@ function fill_messagebanktablebody(vv) {
}); });
}); });
console.log("loaded " + vv.length + " messagebank items"); $('#tablesize').text("Table Size: " + vv.length);
} }
/** /**
@@ -246,7 +246,7 @@ function fill_languagebanktablebody(vv) {
$('#btnEdit').prop('disabled', false); $('#btnEdit').prop('disabled', false);
}); });
}); });
console.log("loaded " + vv.length + " languagebank items"); $('#tablesize').text("Table Size: " + vv.length);
} }
/** /**
@@ -286,7 +286,7 @@ function fill_schedulebanktablebody(vv) {
$('#btnEdit').prop('disabled', false); $('#btnEdit').prop('disabled', false);
}); });
}); });
console.log("loaded " + vv.length + " schedulebank items"); $('#tablesize').text("Table Size: " + vv.length);
} }
/** /**
@@ -306,7 +306,7 @@ function fill_logtablebody(vv) {
</tr>`; </tr>`;
$('#logtablebody').append(row); $('#logtablebody').append(row);
}); });
console.log("loaded " + vv.length + " log items"); $('#tablesize').text("Table Size: " + vv.length);
} }
/** /**
@@ -349,21 +349,21 @@ function fetchAPI(endpoint, method, headers = {}, body = null, cbOK, cbError) {
options.headers['Content-Type'] = 'application/json'; options.headers['Content-Type'] = 'application/json';
} }
} }
console.log("About to fetch from " + url + " with options", options); //console.log("About to fetch from " + url + " with options", options);
fetch(url, options) fetch(url, options)
.then(response => { .then(response => {
console.log("fetchAPI: received response", response); //console.log("fetchAPI: received response", response);
if (!response.ok) { if (!response.ok) {
throw new Error('Network response was not ok ' + response.statusText); throw new Error('Network response was not ok ' + response.statusText);
} }
return response.json(); return response.json();
}) })
.then(data => { .then(data => {
console.log("fetchAPI: received data", data); //console.log("fetchAPI: received data", data);
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);
}); });
} }
@@ -374,9 +374,7 @@ function fetchAPI(endpoint, method, headers = {}, body = null, cbOK, cbError) {
*/ */
function reloadSoundBank(APIURL) { function reloadSoundBank(APIURL) {
soundbankdata = []; soundbankdata = [];
console.log("reloadSoundBank: fetching from " + APIURL + "List");
fetchAPI(APIURL + "List", "GET", {}, null, (okdata) => { fetchAPI(APIURL + "List", "GET", {}, null, (okdata) => {
console.log("reloadSoundBank: received data", okdata);
if (Array.isArray(okdata)) { if (Array.isArray(okdata)) {
soundbankdata = okdata; soundbankdata = okdata;
selectedsoundrow = null; selectedsoundrow = null;
@@ -441,12 +439,17 @@ function reloadTimerBank(APIURL) {
/** /**
* Reload logs from server with date and filter * Reload logs from server with date and filter
* @param {String} APIURL API URL endpoint * @param {String} APIURL API URL endpoint
* @param {String} date date in format dd/MM/yyyy * @param {String} date date in format dd-mm-yyyy
* @param {String} filter log filter text * @param {String} filter log filter text
*/ */
function reloadLogs(APIURL, date, filter) { function reloadLogs(APIURL, date, filter) {
fetchAPI(APIURL + "List/" + date + "/" + filter, "GET", {}, null, (okdata) => { const params = new URLSearchParams({
$('#logcontent').val(okdata.data); date: date,
filter: filter
})
fetchAPI(APIURL + "List?" + params.toString(), "GET", {}, null, (okdata) => {
//console.log("Logs data received", okdata);
fill_logtablebody(okdata);
}, (errdata) => { }, (errdata) => {
alert("Error loading logs: " + errdata.message); alert("Error loading logs: " + errdata.message);
}); });
@@ -536,6 +539,24 @@ function getScheduledDays() {
}); });
} }
/**
* Clear database mechanism
* @param {String} APIURL API URL endpoint
* @param {String} whattoclear what to clear
* @param {Function} cbOK callback function on success
* @param {Function} cbError callback function on error
*/
function DoClear(APIURL, whattoclear, cbOK, cbError) {
if (confirm(`Are you sure want to clear ${whattoclear} ? This procedure is not reversible`)) {
fetchAPI(APIURL + "List", "DELETE", {}, null, (okdata) => {
cbOK(okdata);
}, (errdata) => {
cbError(errdata);
});
}
}
/** /**
* Export mechanism to XLSX file * Export mechanism to XLSX file
* @param {String} APIURL API URL endpoint * @param {String} APIURL API URL endpoint
@@ -569,8 +590,6 @@ function DoExport(APIURL, filename) {
}); });
return; // prevent the rest of the function from running return; // prevent the rest of the function from running
} }
/** /**
@@ -704,9 +723,18 @@ $(document).ready(function () {
reloadSoundBank(APIURL); reloadSoundBank(APIURL);
$('#findsoundbank').on('input', function () {
let searchTerm = $(this).val().trim().toLowerCase();
if (searchTerm.length>0){
let filtered = soundbankdata.filter(item => item.description.toLowerCase().includes(searchTerm) || item.tag.toLowerCase().includes(searchTerm) || item.path.toLowerCase().includes(searchTerm));
fill_soundbanktablebody(filtered);
} else {
selectedsoundrow = null;
fill_soundbanktablebody(soundbankdata);
}
});
$btnClear.click(() => { $btnClear.click(() => {
if (confirm(`Are you sure want to clear Soundbank ? This procedure is not reversible`)) { DoClear(APIURL, "Soundbank", (okdata) => {
fetchAPI(APIURL + "List", "DELETE", {}, null, (okdata) => {
alert("Success clear soundbank" + okdata.message); alert("Success clear soundbank" + okdata.message);
soundbankdata = [] soundbankdata = []
selectedsoundrow = null; selectedsoundrow = null;
@@ -714,7 +742,7 @@ $(document).ready(function () {
}, (errdata) => { }, (errdata) => {
alert("Error clear soundbank: " + errdata.message); alert("Error clear soundbank: " + errdata.message);
}); });
}
}); });
$btnAdd.click(() => { $btnAdd.click(() => {
$('.js-example-basic-single').select2({ $('.js-example-basic-single').select2({
@@ -817,8 +845,7 @@ $(document).ready(function () {
reloadMessageBank(APIURL); reloadMessageBank(APIURL);
$btnClear.click(() => { $btnClear.click(() => {
if (confirm(`Are you sure want to clear Messagebank ? This procedure is not reversible`)) { DoClear(APIURL, "Messagebank", (okdata) => {
fetchAPI(APIURL + "List", "DELETE", {}, null, (okdata) => {
alert("Success clear messagebank" + okdata.message); alert("Success clear messagebank" + okdata.message);
messagebankdata = [] messagebankdata = []
selectedmessagerow = null; selectedmessagerow = null;
@@ -826,7 +853,7 @@ $(document).ready(function () {
}, (errdata) => { }, (errdata) => {
alert("Error clear messagebank: " + errdata.message); alert("Error clear messagebank: " + errdata.message);
}); });
}
}); });
$btnAdd.click(() => { $btnAdd.click(() => {
let $modal = $('#messagebankmodal'); let $modal = $('#messagebankmodal');
@@ -921,22 +948,21 @@ $(document).ready(function () {
let $btnImport = $('#btnImport'); let $btnImport = $('#btnImport');
$btnRemove.prop('disabled', true); $btnRemove.prop('disabled', true);
$btnEdit.prop('disabled', true); $btnEdit.prop('disabled', true);
let APIURL = "LanguageBank/"; let APIURL = "LanguageLink/";
reloadLanguageBank(APIURL); reloadLanguageBank(APIURL);
$btnClear.click(() => { $btnClear.click(() => {
if (confirm(`Are you sure want to clear Languagebank ? This procedure is not reversible`)) { DoClear(APIURL, "LanguageLink", (okdata) => {
fetchAPI(APIURL + "List", "DELETE", {}, null, (okdata) => { alert("Success clear languageLink" + okdata.message);
alert("Success clear languagebank" + okdata.message);
languagebankdata = [] languagebankdata = []
selectedlanguagerow = null; selectedlanguagerow = null;
fill_languagebanktablebody(languagebankdata); fill_languagebanktablebody(languagebankdata);
}, (errdata) => { }, (errdata) => {
alert("Error clear languagebank: " + errdata.message); alert("Error clear languagebank: " + errdata.message);
}); });
}
}); });
$btnAdd.click(() => { $btnAdd.click(() => {
// show modal with id 'languagemodal' // show modal with id 'languagemodal'
@@ -1107,8 +1133,7 @@ $(document).ready(function () {
reloadTimerBank(APIURL); reloadTimerBank(APIURL);
$btnClear.click(() => { $btnClear.click(() => {
if (confirm(`Are you sure want to clear Timerbank ? This procedure is not reversible`)) { DoClear(APIURL, "Timerbank", (okdata) => {
fetchAPI(APIURL + "List", "DELETE", {}, null, (okdata) => {
alert("Success clear schedulebank" + okdata.message); alert("Success clear schedulebank" + okdata.message);
schedulebankdata = [] schedulebankdata = []
selectedschedulerow = null; selectedschedulerow = null;
@@ -1116,7 +1141,7 @@ $(document).ready(function () {
}, (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
@@ -1190,9 +1215,11 @@ $(document).ready(function () {
console.log("Log content loaded successfully"); console.log("Log content loaded successfully");
const $logdate = $('#logdate'); const $logdate = $('#logdate');
const $searchfilter = $('#searchfilter'); const $searchfilter = $('#searchfilter');
const $logtable = $('#logtablebody')
let selectedlogdate = ""; let selectedlogdate = "";
let logfilter = ""; let logfilter = "";
let APIURL = "/api/Logs/"; let APIURL = "Log/";
$logtable.empty();
if (!$logdate.val()) { if (!$logdate.val()) {
@@ -1201,13 +1228,14 @@ $(document).ready(function () {
const mm = String(today.getMonth() + 1).padStart(2, '0'); const mm = String(today.getMonth() + 1).padStart(2, '0');
const yyyy = today.getFullYear(); const yyyy = today.getFullYear();
$logdate.val(`${yyyy}-${mm}-${dd}`); $logdate.val(`${yyyy}-${mm}-${dd}`);
selectedlogdate = `${dd}/${mm}/${yyyy}`; selectedlogdate = `${dd}-${mm}-${yyyy}`;
reloadLogs(APIURL, selectedlogdate, logfilter);
} }
$logdate.off('change').on('change', function () { $logdate.off('change').on('change', function () {
const selected = $(this).val(); const selected = $(this).val();
if (selected) { if (selected) {
const [year, month, day] = selected.split('-'); const [year, month, day] = selected.split('-');
selectedlogdate = `${day}/${month}/${year}`; selectedlogdate = `${day}-${month}-${year}`;
reloadLogs(APIURL, selectedlogdate, logfilter); reloadLogs(APIURL, selectedlogdate, logfilter);
} }
}); });

View File

@@ -24,40 +24,22 @@
<div class="col-6 col-sm-6 col-md-6 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-import" id="btnExport" type="button">Export</button></div> <div class="col-6 col-sm-6 col-md-6 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-import" id="btnExport" type="button">Export</button></div>
<div class="col-6 col-sm-6 col-md-6 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-import" id="btnImport" type="button">Import</button></div> <div class="col-6 col-sm-6 col-md-6 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-import" id="btnImport" type="button">Import</button></div>
</div> </div>
<div class="row">
<div class="col">
<p id="tablesize" class="text-add" style="text-align: center;">Table Length : N/A</p>
</div>
</div>
<div class="row"> <div class="row">
<div class="table-responsive"> <div class="table-responsive">
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th class="col-sm-1">No</th> <th class="col-sm-1">No</th>
<th>Description</th> <th class="col-sm-2">TAG</th>
<th class="col-sm-1">TAG</th> <th class="col">Languages</th>
<th class="col-sm-1">Category</th>
<th class="col-sm-1">Language</th>
<th class="col-sm-1">Type</th>
<th class="col-sm-3">Filename</th>
</tr> </tr>
</thead> </thead>
<tbody id="languagebanktablebody"> <tbody id="languagebanktablebody"></tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
<td>Cell 3</td>
<td>Cell 5</td>
<td>Cell 6</td>
<td>Cell 7</td>
</tr>
<tr>
<td>Cell 3</td>
<td>Cell 4</td>
<td>Cell 3</td>
<td>Cell 3</td>
<td>Cell 5</td>
<td>Cell 6</td>
<td>Cell 7</td>
</tr>
</tbody>
</table> </table>
</div> </div>
</div> </div>

View File

@@ -27,6 +27,11 @@
</div> </div>
<div class="col-6 col-sm col-md-2 col-lg-2 col-xl-2"><input type="text" id="searchfilter" class="form-control" placeholder="Search Filter"></div> <div class="col-6 col-sm col-md-2 col-lg-2 col-xl-2"><input type="text" id="searchfilter" class="form-control" placeholder="Search Filter"></div>
</div> </div>
<div class="row">
<div class="col">
<p id="tablesize" class="text-add" style="text-align: center;">Table Length : N/A</p>
</div>
</div>
<div class="row"> <div class="row">
<div class="table-responsive"> <div class="table-responsive">
<table class="table"> <table class="table">
@@ -35,23 +40,11 @@
<th class="col-1 col-md-1">No</th> <th class="col-1 col-md-1">No</th>
<th class="col-2 col-md-2 col-lg-2">Date</th> <th class="col-2 col-md-2 col-lg-2">Date</th>
<th class="col-2 col-md-2 col-lg-2">Time</th> <th class="col-2 col-md-2 col-lg-2">Time</th>
<th class="col-2 col-md-2 col-lg-2">Machine</th>
<th>Description</th> <th>Description</th>
</tr> </tr>
</thead> </thead>
<tbody id="logtablebody"> <tbody id="logtablebody"></tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
<td>Cell 4</td>
</tr>
<tr>
<td>Cell 3</td>
<td>Cell 4</td>
<td>Cell 3</td>
<td>Cell 4</td>
</tr>
</tbody>
</table> </table>
</div> </div>
</div> </div>

View File

@@ -24,6 +24,11 @@
<div class="col-6 col-sm-6 col-md-6 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-import" id="btnExport" type="button">Export</button></div> <div class="col-6 col-sm-6 col-md-6 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-import" id="btnExport" type="button">Export</button></div>
<div class="col-6 col-sm-6 col-md-6 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-import" id="btnImport" type="button">Import</button></div> <div class="col-6 col-sm-6 col-md-6 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-import" id="btnImport" type="button">Import</button></div>
</div> </div>
<div class="row">
<div class="col">
<p id="tablesize" class="text-add" style="text-align: center;">Table Length : N/A</p>
</div>
</div>
<div class="row"> <div class="row">
<div class="table-responsive"> <div class="table-responsive">
<table class="table"> <table class="table">
@@ -38,26 +43,7 @@
<th class="col-sm-3">Message Tags</th> <th class="col-sm-3">Message Tags</th>
</tr> </tr>
</thead> </thead>
<tbody id="messagebanktablebody"> <tbody id="messagebanktablebody"></tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
<td>Cell 3</td>
<td>Cell 5</td>
<td>Cell 6</td>
<td>Cell 7</td>
</tr>
<tr>
<td>Cell 3</td>
<td>Cell 4</td>
<td>Cell 3</td>
<td>Cell 3</td>
<td>Cell 5</td>
<td>Cell 6</td>
<td>Cell 7</td>
</tr>
</tbody>
</table> </table>
</div> </div>
</div> </div>

View File

@@ -50,26 +50,7 @@
<th class="col-sm-3">Filename</th> <th class="col-sm-3">Filename</th>
</tr> </tr>
</thead> </thead>
<tbody id="soundbanktablebody"> <tbody id="soundbanktablebody"></tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
<td>Cell 3</td>
<td>Cell 5</td>
<td>Cell 6</td>
<td>Cell 7</td>
</tr>
<tr>
<td>Cell 3</td>
<td>Cell 4</td>
<td>Cell 3</td>
<td>Cell 3</td>
<td>Cell 5</td>
<td>Cell 6</td>
<td>Cell 7</td>
</tr>
</tbody>
</table> </table>
</div> </div>
</div> </div>

View File

@@ -13,7 +13,7 @@
<body> <body>
<div class="row"> <div class="row">
<div class="col w-100 h-100 pad-header"> <div class="col w-100 h-100 pad-header">
<h2 style="text-align: center;">Timer</h2> <h2 style="text-align: center;">Schedule Bank</h2>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
@@ -24,40 +24,27 @@
<div class="col-6 col-sm-6 col-md-6 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-import" id="btnExport" type="button">Export</button></div> <div class="col-6 col-sm-6 col-md-6 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-import" id="btnExport" type="button">Export</button></div>
<div class="col-6 col-sm-6 col-md-6 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-import" id="btnImport" type="button">Import</button></div> <div class="col-6 col-sm-6 col-md-6 col-lg-2 col-xl-2"><button class="btn w-100 pad-button btn-round-basic color-import" id="btnImport" type="button">Import</button></div>
</div> </div>
<div class="row">
<div class="col">
<p id="tablesize" class="text-add" style="text-align: center;">Table Length : N/A</p>
</div>
</div>
<div class="row"> <div class="row">
<div class="table-responsive"> <div class="table-responsive">
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th class="col-sm-1">No</th> <th class="col-sm-1">No</th>
<th>Description</th> <th class="col-sm-2">Description</th>
<th class="col-sm-1">TAG</th> <th class="col-sm-1">Day</th>
<th class="col-sm-1">Category</th> <th class="col-sm-1">Time</th>
<th class="col-sm-1">Language</th> <th class="col-sm-2">Sound Path</th>
<th class="col-sm-1">Type</th> <th class="col-sm-1">Repeat</th>
<th class="col-sm-3">Filename</th> <th class="col-sm-1">Enable</th>
<th>Broadcast Zones</th>
</tr> </tr>
</thead> </thead>
<tbody id="schedulebanktablebody"> <tbody id="schedulebanktablebody"></tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
<td>Cell 3</td>
<td>Cell 5</td>
<td>Cell 6</td>
<td>Cell 7</td>
</tr>
<tr>
<td>Cell 3</td>
<td>Cell 4</td>
<td>Cell 3</td>
<td>Cell 3</td>
<td>Cell 5</td>
<td>Cell 6</td>
<td>Cell 7</td>
</tr>
</tbody>
</table> </table>
</div> </div>
</div> </div>

View File

@@ -32,14 +32,14 @@ fun main() {
CoroutineScope(Dispatchers.Default).launch { CoroutineScope(Dispatchers.Default).launch {
while (isActive) { while (isActive) {
delay(1000) delay(1000)
val broadcastzones = db.GetBroadcastZones()
// baca dulu queue paging, prioritas 1 // baca dulu queue paging, prioritas 1
db.Read_Queue_Paging().forEach { db.Read_Queue_Paging().forEach {
// cek apakah queue paging ada broadcast zone nya // cek apakah queue paging ada broadcast zone nya
if (it.BroadcastZones.isNotBlank()) { if (it.BroadcastZones.isNotBlank()) {
val zz = it.BroadcastZones.split(";") val zz = it.BroadcastZones.split(";")
// cek apakah semua target broadcast zone dari queue paging ada di dalam database broadcast zones // cek apakah semua target broadcast zone dari queue paging ada di dalam database broadcast zones
if (zz.all { z -> broadcastzones.any { bz -> bz.equals(z) } }) { if (zz.all { z -> db.BroadcastZoneList.any { bz -> bz.equals(z) } }) {
// semua target broadcast zone valid, sekarang cek apakah semua target broadcast zone idle // semua target broadcast zone valid, sekarang cek apakah semua target broadcast zone idle
} else { } else {
@@ -59,7 +59,7 @@ fun main() {
if (it.BroadcastZones.isNotBlank()) { if (it.BroadcastZones.isNotBlank()) {
val zz = it.BroadcastZones.split(";") val zz = it.BroadcastZones.split(";")
// cek apakah semua target broadcast zone dari queue table ada di dalam database broadcast zones // cek apakah semua target broadcast zone dari queue table ada di dalam database broadcast zones
if (zz.all { z -> broadcastzones.any { bz -> bz.equals(z) } }) { if (zz.all { z -> db.BroadcastZoneList.any { bz -> bz.equals(z) } }) {
// semua target broadcast zone valid, sekarang cek apakah semua target broadcast zone idle // semua target broadcast zone valid, sekarang cek apakah semua target broadcast zone idle
} else { } else {

View File

@@ -24,6 +24,7 @@ class Somecodes {
val memory : GlobalMemory = si.hardware.memory val memory : GlobalMemory = si.hardware.memory
val datetimeformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss") val datetimeformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss")
val dateformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy") val dateformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy")
val dateformat2: DateTimeFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy")
val timeformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("hh:mm:ss") val timeformat1: DateTimeFormatter = DateTimeFormatter.ofPattern("hh:mm:ss")
val timeformat2: DateTimeFormatter = DateTimeFormatter.ofPattern("hh:mm") val timeformat2: DateTimeFormatter = DateTimeFormatter.ofPattern("hh:mm")
const val KB_threshold = 1024.0 const val KB_threshold = 1024.0
@@ -180,6 +181,24 @@ class Somecodes {
} }
} }
/**
* Check if a string is a valid date in the format "dd-MM-yyyy".
* This format is used for log HTML files.
* @param value The string to check.
* @return True if the string is a valid date, false otherwise.
*/
fun ValiDateForLogHtml(value: String): Boolean{
return try{
if (ValidString(value)){
dateformat2.parse(value)
true
} else throw Exception()
} catch (_: Exception){
false
}
}
/** /**
* Check if a string is a valid time in the format "hh:mm:ss". * Check if a string is a valid time in the format "hh:mm:ss".
* @param value The string to check. * @param value The string to check.

View File

@@ -1,12 +1,13 @@
package database package database
import codes.Somecodes.Companion.ValiDateForLogHtml
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.apache.poi.xssf.usermodel.XSSFWorkbook import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.mariadb.jdbc.Connection
import org.tinylog.Logger import org.tinylog.Logger
import java.sql.Connection
import java.sql.DriverManager import java.sql.DriverManager
import java.util.function.Consumer import java.util.function.Consumer
@@ -33,6 +34,7 @@ class MariaDB(
var MessagebankList: ArrayList<Messagebank> = ArrayList() var MessagebankList: ArrayList<Messagebank> = ArrayList()
var LanguageLinkList: ArrayList<LanguageLink> = ArrayList() var LanguageLinkList: ArrayList<LanguageLink> = ArrayList()
var SchedulebankList: ArrayList<ScheduleBank> = ArrayList() var SchedulebankList: ArrayList<ScheduleBank> = ArrayList()
var BroadcastZoneList: ArrayList<BroadcastZones> = ArrayList()
companion object { companion object {
fun ValidDate(date: String): Boolean { fun ValidDate(date: String): Boolean {
@@ -56,7 +58,7 @@ class MariaDB(
*/ */
fun <T> ArrayListtoString(list: ArrayList<T>): String { fun <T> ArrayListtoString(list: ArrayList<T>): String {
return try { return try {
objectMapper.writeValueAsString(list.toArray()) objectMapper.writeValueAsString(list)
} catch (e: Exception) { } catch (e: Exception) {
Logger.error("Error converting list to JSON: ${e.message}" as Any) Logger.error("Error converting list to JSON: ${e.message}" as Any)
"[]" "[]"
@@ -68,7 +70,7 @@ class MariaDB(
init { init {
try { try {
connection = connection =
DriverManager.getConnection("jdbc:mariadb://$address:$port/$dbName", username, password) as Connection DriverManager.getConnection("jdbc:mysql://$address:$port/$dbName?sslMode=REQUIRED", username, password) as Connection
Logger.info("Connected to MariaDB" as Any) Logger.info("Connected to MariaDB" as Any)
connected = true connected = true
@@ -78,6 +80,7 @@ class MariaDB(
Reload_Soundbank() Reload_Soundbank()
Reload_LanguageLink() Reload_LanguageLink()
Reload_Schedulebank() Reload_Schedulebank()
GetBroadcastZones()
} }
} }
@@ -88,6 +91,7 @@ class MariaDB(
Logger.info { "Messagebank count: ${MessagebankList.size}" } Logger.info { "Messagebank count: ${MessagebankList.size}" }
Logger.info { "LanguageLink count: ${LanguageLinkList.size}" } Logger.info { "LanguageLink count: ${LanguageLinkList.size}" }
Logger.info { "Schedulebank count: ${SchedulebankList.size}" } Logger.info { "Schedulebank count: ${SchedulebankList.size}" }
Logger.info { "BroadcastZones count: ${BroadcastZoneList.size}" }
} catch (e: Exception) { } catch (e: Exception) {
@@ -195,7 +199,7 @@ class MariaDB(
val logList = ArrayList<Log>() val logList = ArrayList<Log>()
try { try {
val statement = connection?.createStatement() val statement = connection?.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM log") val resultSet = statement?.executeQuery("SELECT * FROM logs")
while (resultSet?.next() == true) { while (resultSet?.next() == true) {
val log = Log( val log = Log(
resultSet.getLong("index").toULong(), resultSet.getLong("index").toULong(),
@@ -213,16 +217,18 @@ class MariaDB(
} }
/** /**
* Get Log from database by date * Get Log from database by date for HTML usage
* @param date The date to filter logs by (format: DD/MM/YYYY) * @param date The date to filter logs by (format: DD-MM-YYYY)
* @param consumer A Consumer that will receive the list of logs for the specified date * @param consumer A Consumer that will receive the list of logs for the specified date
*/ */
fun GetLog(date: String, consumer: Consumer<ArrayList<Log>>) { fun GetLogForHtml(date: String, consumer: Consumer<ArrayList<Log>>) {
val logList = ArrayList<Log>() val logList = ArrayList<Log>()
if (ValidDate(date)) { if (ValiDateForLogHtml(date)) {
try { try {
val statement = connection?.prepareStatement("SELECT * FROM log WHERE datenya = ?") // must convert from DD-MM-YYYY to DD/MM/YYYY, because in database we use DD/MM/YYYY
statement?.setString(1, date) val adjusteddate = date.replace("-", "/")
val statement = connection?.prepareStatement("SELECT * FROM logs WHERE datenya = ?")
statement?.setString(1, adjusteddate)
val resultSet = statement?.executeQuery() val resultSet = statement?.executeQuery()
while (resultSet?.next() == true) { while (resultSet?.next() == true) {
val log = Log( val log = Log(
@@ -242,13 +248,21 @@ class MariaDB(
consumer.accept(logList) consumer.accept(logList)
} }
fun GetLog(date: String, filter: String, consumer: Consumer<ArrayList<Log>>) { /**
* Get Log from database by date and filter for HTML usage
* @param date The date to filter logs by (format: DD-MM-YYYY)
* @param filter The filter string to search in description or machine
* @param consumer A Consumer that will receive the list of logs for the specified date and filter
*/
fun GetLogForHtml(date: String, filter: String, consumer: Consumer<ArrayList<Log>>) {
val logList = ArrayList<Log>() val logList = ArrayList<Log>()
if (ValidDate(date)) { if (ValiDateForLogHtml(date)) {
try { 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 = val statement =
connection?.prepareStatement("SELECT * FROM log WHERE datenya = ? AND description LIKE ?") connection?.prepareStatement("SELECT * FROM logs WHERE datenya = ? AND description LIKE ?")
statement?.setString(1, date) statement?.setString(1, adjusteddate)
statement?.setString(2, "%$filter%") statement?.setString(2, "%$filter%")
val resultSet = statement?.executeQuery() val resultSet = statement?.executeQuery()
while (resultSet?.next() == true) { while (resultSet?.next() == true) {
@@ -559,7 +573,7 @@ class MariaDB(
LanguageLinkList.clear() LanguageLinkList.clear()
try { try {
val statement = connection?.createStatement() val statement = connection?.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM languagelink") val resultSet = statement?.executeQuery("SELECT * FROM languagelinking")
while (resultSet?.next() == true) { while (resultSet?.next() == true) {
val languageLink = LanguageLink( val languageLink = LanguageLink(
resultSet.getLong("index").toUInt(), resultSet.getLong("index").toUInt(),
@@ -1378,11 +1392,11 @@ class MariaDB(
* Get All Broadcast Zones from database * Get All Broadcast Zones from database
* @return A list of BroadcastZones entries. * @return A list of BroadcastZones entries.
*/ */
fun GetBroadcastZones(): List<BroadcastZones> { fun GetBroadcastZones(){
val zonesList = ArrayList<BroadcastZones>() BroadcastZoneList.clear()
try { try {
val statement = connection?.createStatement() val statement = connection?.createStatement()
val resultSet = statement?.executeQuery("SELECT * FROM broadcast_zones") val resultSet = statement?.executeQuery("SELECT * FROM broadcastzones")
while (resultSet?.next() == true) { while (resultSet?.next() == true) {
val zone = BroadcastZones( val zone = BroadcastZones(
resultSet.getLong("index").toUInt(), resultSet.getLong("index").toUInt(),
@@ -1391,12 +1405,11 @@ class MariaDB(
resultSet.getString("Box"), resultSet.getString("Box"),
resultSet.getString("Relay") resultSet.getString("Relay")
) )
zonesList.add(zone) BroadcastZoneList.add(zone)
} }
} catch (e: Exception) { } catch (e: Exception) {
Logger.error("Error fetching broadcast zones: ${e.message}" as Any) Logger.error("Error fetching broadcast zones: ${e.message}" as Any)
} }
return zonesList
} }
/** /**

View File

@@ -2,6 +2,7 @@ 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.ValidDate 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
@@ -123,11 +124,11 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
} }
"getPagingQueue" ->{ "getPagingQueue" ->{
SendReply(wsMessageContext, cmd.command, MariaDB.ArrayListtoString(db.Read_Queue_Paging())) SendReply(wsMessageContext, cmd.command, objectmapper.writeValueAsString(db.Read_Queue_Paging()))
} }
"getAASQueue" ->{ "getAASQueue" ->{
SendReply(wsMessageContext, cmd.command, MariaDB.ArrayListtoString(db.Read_Queue_Table())) SendReply(wsMessageContext, cmd.command, objectmapper.writeValueAsString(db.Read_Queue_Table()))
} }
else -> { else -> {
@@ -187,7 +188,6 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
} }
path("SoundBank") { path("SoundBank") {
get("List") { get("List") {
// get soundbank list
it.result(MariaDB.ArrayListtoString(db.SoundbankList)) it.result(MariaDB.ArrayListtoString(db.SoundbankList))
} }
get("ListFiles"){ get("ListFiles"){
@@ -719,21 +719,24 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
} }
} }
path("Log") { path("Log") {
get("List/<logdate>/<logfilter>") { get1 -> get("List") { get1 ->
val logdate = get1.pathParam("logdate") val logdate = get1.queryParam("date") ?: ""
val logfilter = get1.pathParam("logfilter") val logfilter = get1.queryParam("filter") ?: ""
if (ValidDate(logdate)) { if (ValiDateForLogHtml(logdate)) {
if (ValidString(logfilter)) { if (ValidString(logfilter)) {
// ada log filter // ada log filter
db.GetLog(logdate, logfilter) { db.GetLogForHtml(logdate, logfilter) {
get1.result(MariaDB.ArrayListtoString(it)) get1.result(MariaDB.ArrayListtoString(it))
} }
} else { } else {
db.GetLog(logdate) { db.GetLogForHtml(logdate) {
get1.result(MariaDB.ArrayListtoString(it)) get1.result(MariaDB.ArrayListtoString(it))
} }
} }
} else get1.status(400).result("Invalid logdate") } else {
println("Invalid logdate=$logdate")
get1.status(400).result("Invalid logdate")
}
} }
get("ExportXLSX/<logdate>/<logfilter>") { get1 -> get("ExportXLSX/<logdate>/<logfilter>") { get1 ->
val logdate = get1.pathParam("logdate") val logdate = get1.pathParam("logdate")