/** * @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 */ /** List of Schedulebank data loaded from server * @type {ScheduleBank[]} */ window.schedulebankdata = []; /** * Currently selected schedulebank row in the table * @type {JQuery|null} */ window.selectedschedulerow = null; /** * Fill schedulebank table body with values * @param {ScheduleBank[]} vv values to fill */ function fill_schedulebanktablebody(vv) { $('#schedulebanktablebody').empty(); if (!Array.isArray(vv) || vv.length === 0) return; vv.forEach(item => { const row = ` ${item.index} ${item.description} ${item.day} ${item.time} ${item.soundpath} ${item.repeat} ${item.enable} ${item.broadcastZones} ${item.language} `; $('#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); }); }); $('#tablesize').text("Table Size: " + vv.length); } /** * Reload timer bank from server * @param {string} APIURL API URL endpoint, default "ScheduleBank/" */ function reloadTimerBank(APIURL = "ScheduleBank/") { window.schedulebankdata = []; fetchAPI(APIURL + "List", "GET", {}, null, (okdata) => { if (Array.isArray(okdata)) { window.schedulebankdata.push(...okdata); selectedschedulerow = null; fill_schedulebanktablebody(window.schedulebankdata); } }, (errdata) => { alert("Error loading schedulebank : " + errdata.message); }); } $(document).ready(function () { console.log("schedulebank.js loaded successfully"); $('#schedulebanktablebody').empty(); selectedschedulerow = null; let $btnClear = $('#btnClear'); let $btnAdd = $('#btnAdd'); let $btnEdit = $('#btnEdit'); let $btnRemove = $('#btnRemove'); let $btnExport = $('#btnExport'); let $btnImport = $('#btnImport'); $btnEdit.prop('disabled', true); $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) { window.selectedschedulerow = null; let filtered = window.schedulebankdata.filter(item => item.description.toLowerCase().includes(searchTerm) || item.soundpath.toLowerCase().includes(searchTerm) || item.broadcastZones.toLowerCase().includes(searchTerm)); fill_schedulebanktablebody(filtered); } else { window.selectedschedulerow = null; fill_schedulebanktablebody(window.schedulebankdata); } }); reloadTimerBank(APIURL); $btnClear.click(() => { DoClear(APIURL, "Timerbank", (okdata) => { reloadTimerBank(APIURL); alert("Success clear schedulebank : " + okdata.message); }, (errdata) => { alert("Error clear schedulebank : " + errdata.message); }); }); $btnAdd.click(() => { $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 (window.selectedschedulerow) { let cells = window.selectedschedulerow.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}?`)) { fetchAPI(APIURL + "DeleteByIndex/" + sr.index, "DELETE", {}, null, (okdata) => { reloadTimerBank(APIURL); alert("Success delete schedule : " + okdata.message); }, (errdata) => { alert("Error delete schedule : " + errdata.message); }); } } }); $btnEdit.click(() => { if (window.selectedschedulerow) { let cells = window.selectedschedulerow.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}?`)) { $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", {}); }); $btnImport.click(() => { DoImport(APIURL, (okdata) => { reloadTimerBank(APIURL); alert("Success import schedulebank from XLSX : " + okdata.message); }, (errdata) => { alert("Error importing schedulebank from XLSX : " + errdata.message); }); }); });