//////////////////////////////////////////////////////////////////////////////////////// //Page 전역 변수 //////////////////////////////////////////////////////////////////////////////////////// var selectId; // 제품 아이디 var selectName; // 제품 이름 var selectedIndex; // 데이터테이블 선택한 인덱스 var selectedPage; // 데이터테이블 선택한 인덱스 var selectVersion; // 선택한 버전 아이디 var dataTableRef; // 데이터테이블 참조 변수 var scheduleList; //////////////////////////////////////////////////////////////////////////////////////// //Document Ready //////////////////////////////////////////////////////////////////////////////////////// function execDocReady() { var pluginGroups = [ [ "../reference/light-blue/lib/vendor/jquery.ui.widget.js", "../reference/light-blue/lib/vendor/http_blueimp.github.io_JavaScript-Templates_js_tmpl.js", "../reference/light-blue/lib/vendor/http_blueimp.github.io_JavaScript-Load-Image_js_load-image.js", "../reference/light-blue/lib/vendor/http_blueimp.github.io_JavaScript-Canvas-to-Blob_js_canvas-to-blob.js", "../reference/light-blue/lib/jquery.iframe-transport.js", "../reference/light-blue/lib/jquery.fileupload.js", "../reference/light-blue/lib/jquery.fileupload-fp.js", "../reference/light-blue/lib/jquery.fileupload-ui.js", "../reference/light-blue/lib/icheck.js/jquery.icheck.js", "../reference/jquery-plugins/unityping-0.1.0/dist/jquery.unityping.min.js", "../reference/jquery-plugins/cron-editor-master/css/jquery-ui_arms.css", "../reference/jquery-plugins/cron-editor-master/js/jquery-ui.js", "../reference/jquery-plugins/cron-editor-master/js/jquery.croneditor_arms.js" ], [ "../reference/jquery-plugins/select2-4.0.2/dist/css/select2_lightblue4.css", "../reference/jquery-plugins/select2-4.0.2/dist/js/select2.min.js", "../reference/jquery-plugins/lou-multi-select-0.9.12/css/multiselect-lightblue4.css", "../reference/jquery-plugins/lou-multi-select-0.9.12/js/jquery.quicksearch.js", "../reference/jquery-plugins/lou-multi-select-0.9.12/js/jquery.multi-select.js", "../reference/jquery-plugins/multiple-select-1.5.2/dist/multiple-select-bluelight.css", "../reference/jquery-plugins/multiple-select-1.5.2/dist/multiple-select.min.js", //highlight "../reference/jquery-plugins/highlight.js-11.10.0/highlight.js.lib/src/styles/base16/darcula.css", "../reference/jquery-plugins/highlight.js-11.10.0/highlight.js.lib/highlight.min.js", "../reference/jquery-plugins/highlight.js-11.10.0/highlightjs-line-numbers.js/src/highlightjs-line-numbers.js" ], [ "../reference/jquery-plugins/datetimepicker-2.5.20/build/jquery.datetimepicker.min.css", "../reference/light-blue/lib/bootstrap-datepicker.js", "../reference/jquery-plugins/datetimepicker-2.5.20/build/jquery.datetimepicker.full.min.js", "../reference/lightblue4/docs/lib/widgster/widgster.js", "../reference/lightblue4/docs/lib/slimScroll/jquery.slimscroll.min.js", // jspreadsheet "../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jsuites.js", "../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/index.js", "../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jsuites.css", "../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jspreadsheet.css", "../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jspreadsheet.datatables.css", "../reference/jquery-plugins/jspreadsheet-ce-4.13.1/dist/jspreadsheet.theme.css", "/arms/js/common/jspreadsheet/spreadsheet.js", "/arms/css/jspreadsheet/custom_sheet.css" ], [ "../reference/jquery-plugins/dataTables-1.10.16/media/css/jquery.dataTables_lightblue4.css", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Responsive/css/responsive.dataTables_lightblue4.css", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Select/css/select.dataTables_lightblue4.css", "../reference/jquery-plugins/dataTables-1.10.16/media/js/jquery.dataTables.min.js", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Responsive/js/dataTables.responsive.min.js", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Select/js/dataTables.select.min.js", "../reference/jquery-plugins/dataTables-1.10.16/extensions/RowGroup/js/dataTables.rowsGroup.min.js", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/dataTables.buttons.min.js", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/buttons.html5.js", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/buttons.print.js", "../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/jszip.min.js", // Table "../arms/js/common/table_new.js" ] // 추가적인 플러그인 그룹들을 이곳에 추가하면 됩니다. ]; loadPluginGroupsParallelAndSequential(pluginGroups) .then(function () { console.log("모든 플러그인 로드 완료"); //vfs_fonts 파일이 커서 defer 처리 함. setTimeout(function () { var script = document.createElement("script"); script.src = "../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/vfs_fonts.js"; script.defer = true; // defer 속성 설정 document.head.appendChild(script); }, 5000); // 5초 후에 실행됩니다. //pdfmake 파일이 커서 defer 처리 함. setTimeout(function () { var script = document.createElement("script"); script.src = "../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/pdfmake.min.js"; script.defer = true; // defer 속성 설정 document.head.appendChild(script); }, 5000); // 5초 후에 실행됩니다. // 사이드 메뉴 색상 설정 $(".widget").widgster(); setSideMenu("sidebar_menu_config", "sidebar_menu_config_schedule"); // 데이터 테이블 로드 함수 console.log("load :: init.scheduleListTable"); $("#schedule_list_table").trigger($.Event("init.scheduleListTable")); // 버튼클릭이벤트 활성화 btnClickEvent(); // 현재 스케줄 목록 가져오기 getCurrentScheduleList(); }) .catch(function (error) { console.error("플러그인 로드 중 오류 발생"); console.log(error); }); } //////////////////////////////////////////////////////////////////////////////////////// // --- 데이터 테이블 설정 --- // //////////////////////////////////////////////////////////////////////////////////////// // 데이터 테이블 구성 이후 꼭 구현해야 할 메소드 : 열 클릭시 이벤트 function dataTableClick(tempDataTable, selectedData) { console.log(selectedData); } // 데이터 테이블 데이터 렌더링 이후 콜백 함수. function dataTableCallBack(settings, json) { console.log("check"); } function dataTableDrawCallback(tableInfo) { // resourceDataTable.columns.adjust(); console.log(tableInfo); } +(function ($) { let columns = [ { name: "idx", title: "No.", // data: null, // idx 는 데이터소스에 있는 필드가 아님 data: null, // idx 는 데이터소스에 있는 필드가 아님 render: function (data, type, row, meta) { if (type === "display") { return meta.row + 1; // meta.row는 현재 행의 인덱스 (0부터 시작) } return meta.row + 1; // 정렬, 필터링 등 다른 타입에서도 인덱스 값 반환 }, className: "dt-body-center", // 가운데 정렬 orderable: false, // 정렬 불가 searchable: false // 검색 불가 }, { name: "fileName", title: "스케줄 그룹(파일명)", data: "fileName", render: function (data, type, row, meta) { if (type === "display") { return '"; } return data; }, className: "dt-body-left", visible: true }, { name: "name", title: "스케줄 명", data: "name", render: function (data, type, row, meta) { if (type === "display") { return '"; } return data; }, className: "dt-body-left", visible: true }, { name: "cron", title: "주기(cron)", data: "cron", render: function (data, type, row, meta) { if (type === "display") { return '"; } return data; }, className: "dt-body-left", visible: true }, { name: "notes", title: "비고", data: "notes", render: function (data, type, row, meta) { if (type === "display") { return '"; } return data; }, className: "dt-body-left", visible: true }, { name: "enabled", title: "스케줄 동작", data: "enabled", render: function (data, type, row, meta) { if (type === "display") { let innerText = ""; if (data === true) { return ( '" ); } else { return ( '" ); } } return data; }, className: "dt-body-left", visible: true } ]; $(document).one("init.scheduleListTable", function () { let lastScrollTop = 0; $("#schedule_list_table") .on("length.dt", function (e, settings, len) { lastScrollTop = $(window).scrollTop(); }) .on("page.dt", function () { console.log("workerStatusTable :: page.dt"); lastScrollTop = $(window).scrollTop(); }) .on("select.table", function (event, selectedData, rowIndex) { console.log("event => ", $(event.target).closest("tr").index() + 1); console.log("select => ", selectedData); $("#modify_schedule_btn").removeClass("disabled"); $("#remove_schedule_btn").removeClass("disabled"); let table = $("#schedule_list_table").DataTable(); let page = table.page.info().page; let pageLength = table.page.info().length; var idx = page * pageLength + $(event.target).closest("tr").index() + 1; setEditScheduleContents($.extend({}, { idx: idx }, selectedData)); setRemoveScheduleContents($.extend({}, { idx: idx }, selectedData)); // 스케줄 이력 조회 (methodName) fetchScheduleHistory(selectedData.methodName ? selectedData.methodName : selectedData.name); // sender 설정 (스케줄 명) changeSender(selectedData.name); }) .on("deselect.table", function (event, selectedData) { console.log("deselect => ", selectedData); $("#modify_schedule_btn").addClass("disabled"); $("#remove_schedule_btn").addClass("disabled"); selectedIndex = null; modalInitialize(); // sender 설정 changeSender(); //$("#selectedSchedule").text("선택되지 않음"); // 엑셀초기화 $("#schedule_history_excel")[0].jexcel.destroy(); }) .table({ order: [], columns: columns, // isAddCheckbox: true, scrollCollapse: false, scrollY: "350px", data: [], drawCallback: function () { console.log("scheduleListTable :: drawCallback"); console.log("lastScrollTop => ", lastScrollTop); setTimeout(() => { $(window).scrollTop(lastScrollTop); }, 0); // 필요시 10~20ms로 늘릴 수 있음 } }); }); })(jQuery); ///////////////////////////////// // 선택한 스케줄 이름 표시 ///////////////////////////////// function changeSender(text) { if (text) { $("#schedule-history-chat-message .chat-message-body").css("border-color", "#e5603b"); $("#schedule-history-chat-message .chat-message-body .arrow").css("border-right", "5px solid #e5603b"); $("#schedule-history-chat-message .sender #senderSelected").text(text); } else { $("#schedule-history-chat-message .chat-message-body").css("border-color", "#a4c6ff"); $("#schedule-history-chat-message .chat-message-body .arrow").css("border-right", "5px solid #a4c6ff"); $("#schedule-history-chat-message .sender #senderSelected").text("선택되지 않음"); } } ///////////////////////////////// // 스케줄 이력 조회 (by fluentd) ///////////////////////////////// function fetchScheduleHistory(methodName) { $.ajax({ url: "/engine-search-api/engine/search/schedule-history-log", type: "POST", contentType: "application/json", data: JSON.stringify({ searchString: methodName }), dataType: "json", success: function (result) { let elapsedTimeFormatted = result.map((item) => { return { ...item, formatElapsedTime: formatElapsedTime(item.elapsedTime) }; }); drawExcel("schedule_history_excel", elapsedTimeFormatted); } }); } ///////////////////////////////// // 스케줄 목록 조회 ///////////////////////////////// function getCurrentScheduleList() { $.ajax({ url: "/auth-sche/getCurrentScheduleList", type: "GET", contentType: "application/json;charset=UTF-8", dataType: "json", progress: true, async: true, statusCode: { 200: function (data) { console.log("[analysisCost :: getCurrentScheduleList] :: response => ", data); scheduleList = data; $("#schedule_list_table").table().reDraw(data); } } }); } // 수정/삭제 모달 초기화 function modalInitialize() { let $radioInputsEdit = $('#edit_modal_enabled input[type="radio"]'); let $radioLabelsEdit = $radioInputsEdit.parent("label"); $radioLabelsEdit.removeClass("active").removeClass("focus"); $("#schedule_edit_modal .modal-content #fileName").val(""); $("#schedule_edit_modal .modal-content #name").val(""); $("#schedule_edit_modal .modal-content #methodName").val(""); $("#schedule_edit_modal .modal-content #cron").val(""); $("#schedule_edit_modal .modal-content #notes").val(""); $("#schedule_edit_modal .modal-content #enabled").val(""); let $radioInputsRemove = $('#remove_modal_enabled input[type="radio"]'); let $radioLabelsRemove = $radioInputsRemove.parent("label"); $radioLabelsRemove.removeClass("active").removeClass("focus"); $("#schedule_remove_modal .modal-content #fileName").val(""); $("#schedule_remove_modal .modal-content #name").val(""); $("#schedule_remove_modal .modal-content #methodName").val(""); $("#schedule_remove_modal .modal-content #cron").val(""); $("#schedule_remove_modal .modal-content #notes").val(""); $("#schedule_remove_modal .modal-content #enabled").val(""); } // 스케줄 수정 모달 세팅 function setEditScheduleContents(selectedData) { console.log("selected Row Idx => ", selectedData.idx); selectedIndex = selectedData.idx; $("#schedule_edit_modal .modal-content #fileName").val(selectedData.fileName); $("#schedule_edit_modal .modal-content #name").val(selectedData.name); $("#schedule_edit_modal .modal-content #methodName").val(selectedData.methodName); $("#schedule_edit_modal .modal-content #cron").val(selectedData.cron); $("#schedule_edit_modal .modal-content #notes").val(selectedData.notes); $("#schedule_edit_modal .modal-content #enabled").val(selectedData.enabled); console.log("selectedData.enabled => ", selectedData.enabled); let $activeOption = $('#edit_modal_enabled input[value="true"]'); let $inactiveOption = $('#edit_modal_enabled input[value="false"]'); if (selectedData.enabled && selectedData.enabled === true) { $activeOption.prop("checked", true); $activeOption.parent("label").addClass("active").addClass("focus"); $inactiveOption.parent("label").removeClass("active").removeClass("focus"); } else { $inactiveOption.prop("checked", true); $activeOption.parent("label").removeClass("active").removeClass("focus"); $inactiveOption.parent("label").addClass("active").addClass("focus"); } } // 스케줄 삭제 모달 세팅 function setRemoveScheduleContents(selectedData) { console.log("selected Row Idx => ", selectedData.idx); selectedIndex = selectedData.idx; $("#schedule_remove_modal .modal-content #fileName").val(selectedData.fileName); $("#schedule_remove_modal .modal-content #name").val(selectedData.name); $("#schedule_remove_modal .modal-content #methodName").val(selectedData.methodName); $("#schedule_remove_modal .modal-content #cron").val(selectedData.cron); $("#schedule_remove_modal .modal-content #notes").val(selectedData.notes); $("#schedule_remove_modal .modal-content #enabled").val(selectedData.enabled); let $radioInputs = $('#remove_modal_enabled input[type="radio"]'); // 모든 라디오 input 선택 let $radioLabels = $radioInputs.parent("label"); // 해당 라디오 input의 부모 label 선택 // 1. 모든 라디오 버튼과 레이블을 비활성화 $radioInputs.prop("disabled", true); // input 자체를 disabled $radioLabels.css("pointer-events", "none"); // 클릭 이벤트를 막음 (혹시 모를 우회 방지) $radioLabels.css("cursor", "not-allowed"); // 마우스 커서 변경 // 2. 현재 데이터에 따라 'active' 상태를 설정 (비활성화 상태이지만, 데이터는 반영) let $activeOption = $('#remove_modal_enabled input[value="true"]'); let $inactiveOption = $('#remove_modal_enabled input[value="false"]'); if (selectedData.enabled && selectedData.enabled === true) { $activeOption.prop("checked", true); $activeOption.parent("label").addClass("active").addClass("focus"); $inactiveOption.parent("label").removeClass("active").removeClass("focus"); } else { $inactiveOption.prop("checked", true); $activeOption.parent("label").removeClass("active").removeClass("focus"); $inactiveOption.parent("label").addClass("active").addClass("focus"); } $radioLabels.removeClass("focus"); } function btnClickEvent() { $("#modify_schedule_btn, #remove_schedule_btn").on("click", function (event) { if ($(this).hasClass("disabled")) { event.preventDefault(); event.stopPropagation(); } }); $("#save_edit_schedule_btn").on("click", function () { console.log("scheduleConfig :: save_edit_schedule_btn is clicked"); let formDataArray = $("#schedule_edit_modal #scheduleForm").serializeArray(); let enabledValue = $('#edit_modal_enabled input[name="edit_modal_enabled_options"]:checked').val(); let notesValue = $("#notes").val(); let dataToSave = {}; formDataArray.forEach(function (item) { dataToSave[item.name] = item.value; }); dataToSave["enabled"] = enabledValue === "true"; // 문자열 "true"/"false"를 boolean으로 변환 dataToSave["notes"] = notesValue; // notes 필드 추가 dataToSave["idx"] = selectedIndex; delete dataToSave.edit_modal_enabled_options; // 1. scheduleList 에서 해당 idx 의 element 를 dataToSave 로 변경 let convertedSchedules = convertedScheduleList(dataToSave, scheduleList); // 2. saveScheduleList API 호출 -> fileName 및 scheduleList 전달 saveScheduleList(convertedSchedules); }); $("#remove_edit_schedule_btn").on("click", function () { if (!selectedIndex || selectedIndex === null) { jError("선택된 스케줄이 없습니다.(삭제 대상 없음)"); } console.log("scheduleConfig :: remove_edit_schedule_btn is clicked"); // 1. scheduleList 에서 해당 idx 의 element 를 삭제 // 2. fileName 과 동일한 내용만 필터링 let dataToRemove = {}; dataToRemove["fileName"] = $("#schedule_remove_modal #scheduleForm #fileName").val(); dataToRemove["idx"] = selectedIndex; let convertedSchedules = updatedScheduleListByRemoval(dataToRemove, scheduleList); console.log("[ scheduleConfig :: remove_edit_schedule_btn ] :: remove.convertedSchedules => ", convertedSchedules); saveScheduleList(convertedSchedules); }); } var updatedScheduleListByRemoval = function removeScheduleElement(targetData, scheduleList) { let updatedRawData = $.extend(true, [], scheduleList); let targetIndex = targetData.idx; updatedRawData.splice(targetIndex - 1, 1); // 업데이트된 rawData 중에서 targetData의 fileName과 일치하는 요소만 필터링 let filteredData = updatedRawData.filter((item) => item.fileName === targetData.fileName); return { updatedScheduleList: updatedRawData, targetSchedules: filteredData }; }; var convertedScheduleList = function convertScheduleElement(targetData, scheduleList) { let updatedRawData = $.extend(true, [], scheduleList); let taretIndex = targetData.idx; if (taretIndex !== undefined && taretIndex > 0 && taretIndex <= updatedRawData.length) { delete targetData.idx; updatedRawData[taretIndex - 1] = targetData; } else { console.warn( "targetData.idx가 유효한 배열 인덱스를 벗어나거나 정의되지 않았습니다. 데이터를 업데이트하지 못했습니다." ); } let filteredData = updatedRawData.filter((item) => item.fileName === targetData.fileName); return { updatedScheduleList: updatedRawData, targetSchedules: filteredData }; }; function saveScheduleList(convertedSchedules) { $.ajax({ url: "/auth-sche/saveScheduleList?fileName=" + convertedSchedules.targetSchedules[0].fileName, type: "POST", data: JSON.stringify(convertedSchedules.targetSchedules), contentType: "application/json;charset=UTF-8", dataType: "json", success: function (result) { if (result === 200 || result === "200") { console.log("[ scheduleConfig:: saveScheduleList ] :: complete"); scheduleList = convertedSchedules.updatedScheduleList; $("#schedule_list_table").table().reDraw(scheduleList); selectedIndex = null; } else { console.error("[ scheduleConfig:: saveScheduleList ] :: unexpected server response : ", result); } }, error: function (xhr, status, error) { console.error("AJAX 요청 실패:", status, error); console.error("응답 본문:", xhr.responseText); } }); } //////////////// // 엑셀 그리기 //////////////// function drawExcel(target, data) { var columnList = [ { readOnly: true, type: "hidden", name: "scheduleName", title: "스케줄 명", wRatio: 0 }, // 0 스케줄명 { readOnly: true, type: "text", name: "startedAt", title: "시작 시점", wRatio: 0.4 }, // 1 시작시점 // { readOnly: true, type: "calendar", options: {format: "YYYY/MM/DD"}, name: "createDate", title: "ALM 이슈 생성일", wRatio: 0.1 }, //10 { readOnly: true, type: "text", name: "finishedAt", title: "종료 시점", wRatio: 0.4 }, // 2 종료시점 { readOnly: true, type: "text", name: "formatElapsedTime", title: "경과", wRatio: 0.2 }, // 3 경과시간(ms) { readOnly: true, type: "hidden", name: "elapsedTime", title: "경과 시간(ms)", wRatio: 0 }, // 3 경과시간(ms) { readOnly: true, type: "hidden", name: "threadName", title: "스레드명", wRatio: 0 }, // 4 (히든) 스레드명 { readOnly: true, type: "hidden", name: "threadId", title: "스레드아이디", wRatio: 0 } // 5 (히든) 스레드아이디 ]; var customOption = { toolbar: [], pagination: 30, contextMenu: [], search: true, allowInsertRow: false, allowInsertColumn: false, columnSorting: false, onload: function (element) { var $jexcel = $(element); var $searchInput = $( '' + ' ' + "" ); $jexcel.find(".jexcel_toolbar_item[data-k='undo']").addClass("fa fa-mail-reply "); $jexcel.find(".jexcel_toolbar_item[data-k='redo']").addClass("fa fa-mail-forward "); $jexcel.find(".jexcel_toolbar_item[data-k='save']").addClass("fa fa-save"); $jexcel .find(".jexcel_toolbar_item[data-k='text-align'][data-v='left']") .addClass("fa fa-align-left fa-flip-vertical"); $jexcel .find(".jexcel_toolbar_item[data-k='text-align'][data-v='center']") .addClass("fa fa-align-center fa-flip-vertical"); $jexcel .find(".jexcel_toolbar_item[data-k='text-align'][data-v='right']") .addClass("fa fa-align-right fa-flip-vertical"); $jexcel.find(".jexcel_toolbar_item[data-k='font-weight'][data-v='bold']").addClass("fa fa-bold"); $jexcel.find(".jexcel_toolbar_item[data-k='font-style'][data-v='italic']").addClass("fa fa-italic"); $jexcel.find(".jexcel_toolbar_item[data-k='text-decoration'][data-v='underline']").addClass("fa fa-underline"); $jexcel .find(".jexcel_toolbar_item[data-k='text-decoration'][data-v='line-through']") .addClass("fa fa-strikethrough"); $jexcel.find(".jexcel_toolbar_item[data-k='color']").addClass("fa fa-font"); $jexcel.find(".jexcel_toolbar_item[data-k='background-color']").addClass("fa fa-font fa-background"); $jexcel.find(".jexcel_filter").addClass("hidden"); $jexcel.find(".jexcel_toolbar_item[data-k='search-box']").addClass("search-box").append($searchInput); // 검색 input 에 focus 일때, 선택 초기화 var $inputField = $searchInput.find("input.jexcel_search"); if ($inputField.length) { $inputField.on("focus", function () { if (element.jexcel) { element.jexcel.resetSelection(); } }); } }, updateTable: function (instace, cell, col, row, val, id) { cell.style.whiteSpace = "normal"; cell.style.textAlign = "left"; cell.style.color = "#a4c6ff"; if (col === 20 && val !== true) { // 현재 행(row)에 해당하는 모든 셀 가져오기 let rowCells = cell.parentElement.children; // 해당 행의 모든 셀의 글꼴 색상을 red로 변경 for (let i = 0; i < 14; i++) { rowCells[i].style.color = "#f8f8f8"; } } }, oneditionstart: function () { SpreadsheetFunctions.isEditingCell = true; SpreadsheetFunctions.stopObserver(); }, oneditionend: function () { SpreadsheetFunctions.isEditingCell = false; SpreadsheetFunctions.startObserver(); } }; SpreadsheetFunctions.setTargetId(target); SpreadsheetFunctions.setDefaultTargetRect(); SpreadsheetFunctions.setColumns(columnList); SpreadsheetFunctions.setColumnWidth(SpreadsheetFunctions.getTargetRect("width")); SpreadsheetFunctions.setOptions(customOption); SpreadsheetFunctions.startObserver(); SpreadsheetFunctions.setExcelData(data); SpreadsheetFunctions.drawResizedExcel(SpreadsheetFunctions.getTargetId()); } var SpreadsheetFunctions = (function () { let targetId = { v: "", jq: "" }; let targetRect = { width: 0, height: 0 }; let excelData; // 엑셀 데이터 let excelColumns; // 엑셀 컬럼 let customOptions; // 엑셀 커스텀 옵션들 :: 정의 안할 경우 default let isEditingCell = false; var setDefaultTargetRect = function () { let defaultWidth = $(getTargetId("jq")).width(); let defaultHeight = $(getTargetId("jq")).height(); setTargetRect(defaultWidth, defaultHeight); }; var setTargetRect = function (width, height) { targetRect.width = width; targetRect.height = height; }; var getTargetRect = function (type) { if (type === "width") { return targetRect.width; } else if (type === "height") { return targetRect.height; } else { return targetRect; } }; var setTargetId = function (target) { targetId.v = target; targetId.jq = "#" + target; }; var getTargetId = function (type) { if (type === "jq") { return targetId.jq; } else { return targetId.v; } }; var setExcelData = function (data) { excelData = data; }; var getExcelData = function () { return excelData; }; var setColumns = function (columns) { excelColumns = columns; }; var getColumns = function () { return excelColumns; }; var setColumnWidth = function (width) { if (excelColumns) { excelColumns = excelColumns.map((column) => ({ ...column, width: width * column.wRatio - 1 })); } }; function setColumnWidthAsync(width) { return new Promise((resolve) => { if (excelColumns) { excelColumns = excelColumns.map((column) => ({ ...column, width: width * column.wRatio - 1 })); } resolve(); // 컬럼 너비 설정이 완료된 후 resolve 호출 }); } var setOptions = function (options) { customOptions = options; }; var getOptions = function () { return customOptions ? customOptions : null; }; var resizeObserver = new ResizeObserver(function (entries) { if (isEditingCell) { // 수정중에는 resize 비활성화 return; } for (let entry of entries) { setTargetRect(entry.contentRect.width, entry.contentRect.height); handleResize(entry.target.id, getTargetRect("width"), getTargetRect("height")); } }); // 모달요소 크기 변화 관찰(Observer) function startObserver() { resizeObserver.observe($(getTargetId("jq"))[0]); } // Observer 멈추기 function stopObserver() { console.log("Stopping ResizeObserver"); resizeObserver.disconnect(); // 크기 변화를 더 이상 감지하지 않음 } function handleResize(id, width, height) { if (id === getTargetId() && height !== 0) { if (excelData) { drawResizedExcel(getTargetId()); } else { console.log("Spreadsheet.handleResize :: 엑셀 데이터 없음"); } } else { console.log("Spreadsheet.handleResize :: id 불일치 또는 height 가 0 입니다."); } } function drawResizedExcel(target) { let $targetId = "#" + target; if ($($targetId).length > 0 && $($targetId)[0].jexcel) { $($targetId)[0].jexcel.destroy(); } setColumnWidthAsync(getTargetRect("width") - 50).then(() => { $($targetId).spreadsheet( $.extend( {}, { columns: getColumns(), data: getExcelData() }, getOptions() ) ); let jexcel_content_height = getTargetRect("height") - 40 - 30 - 35 - 34; $($targetId + " .jexcel_content").css("max-height", jexcel_content_height); $($targetId + " .jexcel_content").css("width", "100%"); }); } function drawExcel(target) { let $targetId = "#" + target; if ($($targetId).length > 0 && $($targetId)[0].jexcel) { $($targetId)[0].jexcel.destroy(); } $($targetId).spreadsheet( $.extend( {}, { columns: getColumns(), data: getExcelData() }, getOptions() ) ); let jexcel_content_height = getTargetRect("height") - 40 - 30 - 35 - 34; $($targetId + " .jexcel_content").css("max-height", jexcel_content_height); $($targetId + " .jexcel_content").css("width", "100%"); } return { setTargetId, getTargetId, setTargetRect, getTargetRect, setDefaultTargetRect, setExcelData, getExcelData, setColumns, getColumns, setColumnWidth, setOptions, getOptions, startObserver, stopObserver, drawExcel, drawResizedExcel }; })(); //////////////////////////////// // 경과시간 //////////////////////////////// function formatElapsedTime(milliseconds) { if (milliseconds === undefined || milliseconds === null) { return ""; // 또는 다른 적절한 기본값 } const ms = parseInt(milliseconds, 10); // 문자열을 숫자로 변환 if (isNaN(ms)) { return "Invalid Time"; } const seconds = Math.floor(ms / 1000); const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const remainingSeconds = seconds % 60; let result = ""; if (hours > 0) { result += `${hours}h`; } if (minutes > 0) { result += `${minutes}m`; } if (remainingSeconds > 0) { result += `${remainingSeconds}s`; } if (result === "") { return "0s"; // 시간이 0ms인 경우 } return result.trim(); }