var selectedPdServiceId; // 제품(서비스) 아이디 var selectedVersionId; // 선택된 버전 아이디 var pdServiceListData; var versionListData; var resourceDataTable; // var selectedIndex; // 데이터테이블 선택한 인덱스 var selectedPage; // 데이터테이블 선택한 인덱스 //////////////////////////////////////////////////////////////////////////////////////// //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/lightblue4/docs/lib/widgster/widgster.js", "../reference/lightblue4/docs/lib/slimScroll/jquery.slimscroll.min.js", "../reference/jquery-plugins/select2-4.0.2/dist/css/select2_lightblue4.css", "../reference/jquery-plugins/lou-multi-select-0.9.12/css/multiselect-lightblue4.css", "../reference/jquery-plugins/multiple-select-1.5.2/dist/multiple-select-bluelight.css", "../reference/jquery-plugins/select2-4.0.2/dist/js/select2.min.js", "../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.min.js" ], [ // lightblue4 "../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" ], [ //날짜 검색 "../reference/light-blue/lib/bootstrap-datepicker.js", "../reference/jquery-plugins/datetimepicker-2.5.20/build/jquery.datetimepicker.min.css", "../reference/jquery-plugins/datetimepicker-2.5.20/build/jquery.datetimepicker.full.min.js", //chart Colors "./js/common/colorPalette.js", // Apache Echarts "../reference/jquery-plugins/echarts-5.4.3/dist/echarts.min.js", "./js/common/chart/eCharts/donutChart.js", "../reference/jquery-plugins/timerStyles.js" ], // 추가적인 플러그인 그룹들을 이곳에 추가하면 됩니다.(그룹 최대 4개) ]; loadPluginGroupsParallelAndSequential(pluginGroups) .then(function() { console.log('모든 플러그인 로드 완료'); //사이드 메뉴 처리 $('.widget').widgster(); setSideMenu("sidebar_menu_report", "sidebar_menu_report_alm_project"); //coming soon $("#count-down").TimeCircles( { circle_bg_color: "#f8f8f8", use_background: true, bg_width: .2, fg_width: 0.013, time: { Days: { color: "#f8f8f8" }, Hours: { color: "#f8f8f8" }, Minutes: { color: "#f8f8f8" }, Seconds: { color: "#f8f8f8" } } } ); $(".top-menu-div-progress").matchHeight({ target: $(".top-menu-div") }); //날짜 dateTimePicker(); renderAll(mockData); }) .catch(function(e) { console.error('플러그인 로드 중 오류 발생'); console.error(e); }); }//.execDocReady //////////////////////////////////////// // 기간 설정 세팅 //////////////////////////////////////// function dateTimePicker() { $('#date_timepicker_start').datetimepicker({ format: 'Y-m-d', // 날짜 및 시간 형식 지정 formatDate: 'Y/m/d', timepicker: false, theme: 'dark', lang: "kr", onSelectTime: function(current_time, $input) { $('#date_timepicker_end').datetimepicker('setOptions', { minDate: current_time }); }, onShow: function(ct) { this.setOptions({ maxDate: $('#date_timepicker_end').val() ? $('#date_timepicker_end').val() : false }); } }); $('#date_timepicker_end').datetimepicker({ format: 'Y-m-d', // 날짜 및 시간 형식 지정 formatDate: 'Y/m/d', timepicker: false, theme: 'dark', lang: "kr", onSelectTime: function(current_time, $input) { $('#date_timepicker_start').datetimepicker('setOptions', { maxDate: current_time }); }, onShow: function(ct) { this.setOptions({ minDate: $('#date_timepicker_start').val() ? $('#date_timepicker_start').val() : false }); } }); } //////////////////////////////////////// // 선택한 버전 - min,max 날짜 세팅 //////////////////////////////////////// function setEdgeDateRange(versionData) { if (!versionData || Object.keys(versionData).length === 0) { console.log("[ fullDataSheet :: setEdgeDateRange ] :: versionData 가 없습니다."); return false; } let minMaxDate = versionData.reduce((acc, curr) => { const startDate = new Date(curr.start_date); const endDate = new Date(curr.end_date); if (!acc.min || startDate < acc.min) { acc.min = startDate; } if (!acc.max || endDate > acc.max) { acc.max = endDate; } return acc; }, { min: null, max: null }); console.log("[ fullDataSheet :: setEdgeDateRange ] :: " + "minMaxDate.min => " + minMaxDate.min+ ", minMaxDate.max => " +minMaxDate.max); $('#date_timepicker_start').datetimepicker('setOptions', { value: minMaxDate.min }); $('#date_timepicker_end').datetimepicker('setOptions', { value: minMaxDate.max }); } //////////////////////////////////////// // 카드 덱 //////////////////////////////////////// const mockData = [ { productId: 1, productName: '제품1', versions: [ { versionId: 10, versionName: 'v1.0', dDay: 5, projects: [ { projectId: '100001_X1', projectName: '사용자 관리', isReq: { true: 1, false: 2 }, status: { open: 2, 'in-progress': 1, resolved: 0, closed: 0 } }, { projectId: '100002_Y2', projectName: '데이터 처리', isReq: { true: 0, false: 3 }, status: { open: 1, 'in-progress': 2, resolved: 1, closed: 0 } }, { projectId: '100003_Z3', projectName: '알림 서비스', isReq: { true: 2, false: 1 }, status: { open: 0, 'in-progress': 1, resolved: 2, closed: 1 } } ] }, { versionId: 11, versionName: 'v1.1', dDay: 0, projects: [ { projectId: '100004_AA', projectName: '인증', isReq: { true: 1, false: 2 }, status: { open: 0, 'in-progress': 0, resolved: 2, closed: 1 } }, { projectId: '100005_BB', projectName: '로그', isReq: { true: 3, false: 0 }, status: { open: 1, 'in-progress': 1, resolved: 1, closed: 0 } } ] }, { versionId: 12, versionName: 'v1.2', dDay: 7, projects: [ { projectId: '100006_CC', projectName: '스케줄러', isReq: { true: 2, false: 0 }, status: { open: 0, 'in-progress': 2, resolved: 3, closed: 0 } } ] } ] }, { productId: 2, productName: '제품2', versions: [ { versionId: 20, versionName: 'v2.0', dDay: 3, projects: [ { projectId: '200001_D1', projectName: '주문 처리', isReq: { true: 3, false: 2 }, status: { open: 0, 'in-progress': 2, resolved: 2, closed: 1 } }, { projectId: '200002_E2', projectName: '결제', isReq: { true: 1, false: 4 }, status: { open: 2, 'in-progress': 0, resolved: 1, closed: 1 } } ] }, { versionId: 21, versionName: 'v2.1', dDay: 1, projects: [ { projectId: '200003_F3', projectName: '리포팅', isReq: { true: 2, false: 3 }, status: { open: 1, 'in-progress': 1, resolved: 2, closed: 2 } } ] }, { versionId: 22, versionName: 'v2.2', dDay: 4, projects: [ { projectId: '200004_G4', projectName: '알림', isReq: { true: 4, false: 1 }, status: { open: 1, 'in-progress': 3, resolved: 1, closed: 0 } } ] } ] }, { productId: 3, productName: '제품3', versions: [ { versionId: 30, versionName: 'v3.0', dDay: 10, projects: [ { projectId: '300001_H1', projectName: '캐싱', isReq: { true: 5, false: 1 }, status: { open: 3, 'in-progress': 2, resolved: 0, closed: 0 } }, { projectId: '300002_I2', projectName: '검색', isReq: { true: 2, false: 2 }, status: { open: 0, 'in-progress': 4, resolved: 1, closed: 1 } } ] }, { versionId: 31, versionName: 'v3.1', dDay: 0, projects: [ { projectId: '300003_J3', projectName: '통계', isReq: { true: 3, false: 3 }, status: { open: 1, 'in-progress': 3, resolved: 2, closed: 2 } }, { projectId: '300004_K4', projectName: '모니터링', isReq: { true: 0, false: 5 }, status: { open: 0, 'in-progress': 1, resolved: 3, closed: 3 } } ] }, { versionId: 32, versionName: 'v3.2', dDay: 1, projects: [ { projectId: '300005_L5', projectName: '배치 작업', isReq: { true: 1, false: 1 }, status: { open: 1, 'in-progress': 0, resolved: 0, closed: 5 } } ] } ] } ]; function createCardHTML({ chartId, dDay, versionName, projectName, status }) { return `

D - ${dDay}   [${versionName}] ${projectName}

진척률
63.74%
달성률
107.9
171
전체
101
계획
109
완료
0
지연
`; } function renderAll(mockData) { const container = document.getElementById('productAccordion'); container.innerHTML = ''; mockData.forEach(product => { const section = document.createElement('section'); section.classList.add('widget'); section.innerHTML = `

${product.productName}

`; container.appendChild(section); // Widgster 플러그인 재바인딩 $(section).widgster(); const wrapper = section.querySelector('.card-wrapper'); product.versions.forEach(version => { version.projects.forEach(project => { const chartId = `chart-${product.productId}-${version.versionId}-${project.projectId}`; wrapper.insertAdjacentHTML( 'beforeend', createCardHTML({ chartId, dDay: version.dDay, versionName: version.versionName, projectName: project.projectName, status: project.status }) ); drawDonut(chartId, project.status); }); }); }); window.addEventListener('resize', () => { document.querySelectorAll('.chart-area').forEach(dom => { const chartInstance = echarts.getInstanceByDom(dom); if (chartInstance) chartInstance.resize(); }); }); } function drawDonut(id, status) { const chartDom = document.getElementById(id); const chart = echarts.init(chartDom); const data = Object.entries(status) .filter(([_, v]) => v > 0) .map(([k, v]) => ({ name: k, value: v })); chart.setOption({ backgroundColor: 'transparent', tooltip: { trigger: "item", formatter: "{b}: {c} ({d}%)" }, legend: { top: "bottom", textStyle: { color: "#fff", fontSize: 12 } }, series: [ { type: "pie", radius: ["35%", "65%"], center: ['50%', '38%'], avoidLabelOverlap: false, itemStyle: { borderRadius: 5, borderWidth: 2 }, label: { show: false }, labelLine: { show: false }, data: data } ] }); }