Index: controltower/css/common.css =================================================================== diff -u --- controltower/css/common.css (revision 0) +++ controltower/css/common.css (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,499 @@ +@font-face { + font-family: "Nanum Gothic"; + font-style: normal; + font-weight: 400; + src: url("../../reference/light-blue/css/font/NanumGothic/nanum-gothic-v11-latin_korean-regular.eot"); /* IE9 Compat Modes */ + src: local("NanumGothic"), + url("../../reference/light-blue/css/font/NanumGothic/nanum-gothic-v11-latin_korean-regular.eot?#iefix") + format("embedded-opentype"), + /* IE6-IE8 */ url("../../reference/light-blue/css/font/NanumGothic/nanum-gothic-v11-latin_korean-regular.woff2") + format("woff2"), + /* Super Modern Browsers */ + url("../../reference/light-blue/css/font/NanumGothic/nanum-gothic-v11-latin_korean-regular.woff") format("woff"), + /* Modern Browsers */ + url("../../reference/light-blue/css/font/NanumGothic/nanum-gothic-v11-latin_korean-regular.ttf") + format("truetype"), + /* Safari, Android, iOS */ + url("../../reference/light-blue/css/font/NanumGothic/nanum-gothic-v11-latin_korean-regular.svg#NanumGothic") + format("svg"); /* Legacy iOS */ +} +html, +body { + font-family: "Nanum Gothic" !important; +} +body { + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY3g9IjEwJSIgY3k9IjAiIHI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9InJnYmEoMTAyLCAxMDUsIDEwNCwgMC45MCkiLz48c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0icmdiYSg5MywgMTEyLCAxMTksIDAuODkpIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSJyZ2JhKDE2MCwgMTc0LCAxNTAsIDAuOTApIi8+PC9yYWRpYWxHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4="), + url("../../reference/light-blue/img/bgnoise_lg_dark.png"); + background-color: rgba(102, 105, 104, 0.9); + background: radial-gradient( + farthest-side ellipse at 10% 0, + rgba(139, 129, 118, 0.9), + rgba(78, 76, 71, 0.89), + rgba(102, 98, 92, 0.9) + ), + url("../../reference/light-blue/img/bgnoise_lg_dark.png"); + background: -webkit-radial-gradient( + 10% 0, + farthest-side ellipse, + rgba(139, 129, 118, 0.9), + rgba(78, 76, 71, 0.89), + rgba(102, 98, 92, 0.9) + ), + url("../../reference/light-blue/img/bgnoise_lg_dark.png"); + background: -moz-radial-gradient( + 10% 0, + farthest-side ellipse, + rgba(139, 129, 118, 0.9), + rgba(78, 76, 71, 0.89), + rgba(102, 98, 92, 0.9) + ), + url("../../reference/light-blue/img/bgnoise_lg_dark.png"); + padding-bottom: 10px; + background-attachment: fixed; +} + +/* 스크롤 테마 */ +body::-webkit-scrollbar { + width: 8px; /* 스크롤바의 너비 */ + height: 8px; +} + +body::-webkit-scrollbar-thumb { + height: 30%; /* 스크롤바의 길이 */ + background: #313131; /* 스크롤바의 색상 */ + + border-radius: 10px; +} + +body::-webkit-scrollbar-track { + background-color: #4b4b4b; /*스크롤바 뒷 배경 색상*/ +} + +p { + margin: 0; + /* text-align: center; 공통으로 텍스트가 가운데로 정렬되는것은 제어하기가 어려워서 주석처리 */ +} + +/* Font */ +.jstree-default-context { + font-family: "Nanum Gothic" !important; + font-size: 12px; + color: #f8f8f8; +} +.font10 { + font-family: "Nanum Gothic" !important; + font-size: 10px; + color: #f8f8f8; +} +.font11 { + font-family: "Nanum Gothic" !important; + font-size: 11px; + color: #f8f8f8; +} +.font12 { + font-family: "Nanum Gothic" !important; + font-size: 12px; + color: #f8f8f8; +} +.font13 { + font-family: "Nanum Gothic" !important; + font-size: 13px; + color: #f8f8f8; +} +.font14 { + font-family: "Nanum Gothic" !important; + font-size: 14px; + color: #f8f8f8; +} +.font15 { + font-family: "Nanum Gothic" !important; + font-size: 15px; + color: #f8f8f8; +} +.font16 { + font-family: "Nanum Gothic" !important; + font-size: 16px; + color: #f8f8f8; +} +.font17 { + font-family: "Nanum Gothic" !important; + font-size: 17px; + color: #f8f8f8; +} +.font18 { + font-family: "Nanum Gothic" !important; + font-size: 18px; + color: #f8f8f8; +} + +.row { + overflow: hidden; + clear: both; +} + +#topicon { + width: 36px; + height: 35px; + position: fixed; + right: 1%; + bottom: 15px; + z-index: 200; + transition: 0.3s; + cursor: pointer; + opacity: 0; + border-radius: 50%; + overflow: hidden; + padding-left: -1px; + animation: doongdoong 1.3s linear infinite; +} + +@keyframes doongdoong { + 0% { + bottom: 15px; + } + 50% { + bottom: 10px; + } + 100% { + bottom: 15px; + } +} + +.widgetheader { + border-radius: 3px; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + padding: 5px 5px 1px 5px; + color: #f8f8f8; + margin-bottom: 5px; + position: relative; +} + +.breadcrumb { + padding: 0px; + margin: 3px; + list-style: none; + background-color: transparent; + border-radius: 3px; +} + +.content .content-footer { + position: initial; + bottom: 0px; + color: #d2d2d2; +} + +/* 그라디언트 보더 */ +.gradient_left_border { + border-left: 1px dashed transparent; + border-image: linear-gradient(0turn, rgb(0 0 0 / 0%), #979797, rgb(0 0 0 / 0%)); + border-image-slice: 1; +} + +.gradient_right_border { + border-right: 1px dashed transparent; + border-image: linear-gradient(0turn, rgb(0 0 0 / 0%), #979797, rgb(0 0 0 / 0%)); + border-image-slice: 1; +} +.gradient_bottom_border { + border-bottom: 1px solid transparent; + border-image: linear-gradient(0.25turn, rgb(0 0 0 / 0%), #979797, rgb(0 0 0 / 0%)); + border-image-slice: 1; +} +.gradient_middle_border { + border-bottom: 1px solid transparent; + border-image: linear-gradient(0.25turn, rgb(0 0 0 / 0%), #666666, rgb(0 0 0 / 0%)); + border-image-slice: 1; +} + +blockquote { + padding: 9px 0px 9px 18px !important; + margin: 9px 0 9px !important; + font-size: 16.25px; + border-left: 5px solid rgba(51, 51, 51, 0.425); +} + +.widget-controls { + position: absolute; + z-index: 1; + top: 3px !important; + right: 0; + font-size: 12px; + word-spacing: 1px; +} + +.alert-created { + width: max-content; + background-size: 15px 2px, 15px 2px, 2px 15px, 2px 15px; + padding: 1px; + animation: border-dance 7s infinite linear; + border-radius: 10px; +} + +@media (min-width: 1200px) { + .content { + position: relative; + padding: 30px 2.5641%; + -webkit-transition: margin-top 0.35s ease, opacity 0.2s; + -o-transition: margin-top 0.35s ease, opacity 0.2s; + transition: margin-top 0.35s ease, opacity 0.2s; + max-width: none; + width: auto; + opacity: 1; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .content { + position: relative; + padding: 30px 2.5641%; + -webkit-transition: margin-top 0.35s ease, opacity 0.2s; + -o-transition: margin-top 0.35s ease, opacity 0.2s; + transition: margin-top 0.35s ease, opacity 0.2s; + max-width: none; + width: auto; + opacity: 1; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .content { + position: relative; + padding: 30px 2.5641%; + -webkit-transition: margin-top 0.35s ease, opacity 0.2s; + -o-transition: margin-top 0.35s ease, opacity 0.2s; + transition: margin-top 0.35s ease, opacity 0.2s; + max-width: none; + width: auto; + opacity: 1; + } +} +@media (max-width: 767px) { + .content { + position: relative; + padding: 75px 2.5641%; + -webkit-transition: margin-top 0.35s ease, opacity 0.2s; + -o-transition: margin-top 0.35s ease, opacity 0.2s; + transition: margin-top 0.35s ease, opacity 0.2s; + max-width: none; + width: auto; + opacity: 1; + } +} + +/*****************/ +/** jNotify CSS **/ +/*****************/ +#jNotify { + position: absolute !important; + -webkit-transition: background-color 0.4s !important; + -o-transition: background-color 0.4s !important; + transition: background-color 0.4s !important; + border-radius: 5px !important; + border-color: transparent !important; + background-color: rgba(52, 52, 52, 0.425) !important; + margin-bottom: 1em !important; + color: #f8f8f8 !important; + font-weight: 500 !important; + + background: #d8e6fc url("../info.png") no-repeat 15px center; + padding: 10px; + padding-left: 50px; + margin: 15px; + z-index: 99999; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-border-radius: 5px; +} +#jNotify a { + color: #35517c !important; + text-decoration: none; +} + +/******************/ +/** jSuccess CSS **/ +/******************/ +#jSuccess { + position: absolute !important; + -webkit-transition: background-color 0.4s !important; + -o-transition: background-color 0.4s !important; + transition: background-color 0.4s !important; + border-radius: 5px !important; + border-color: transparent !important; + background-color: rgba(52, 52, 52, 0.425) !important; + margin-bottom: 1em !important; + color: #f8f8f8 !important; + font-weight: 500 !important; + + background: #e6efc2 url("../success.png") no-repeat 15px center; + padding: 10px; + padding-left: 50px; + margin: 15px; + z-index: 99999; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-border-radius: 5px; +} +#jSuccess a { + color: #264409 !important; + text-decoration: none; +} + +/****************/ +/** jError CSS **/ +/****************/ +#jError { + position: absolute !important; + -webkit-transition: background-color 0.4s !important; + -o-transition: background-color 0.4s !important; + transition: background-color 0.4s !important; + border-radius: 5px !important; + border-color: transparent !important; + background-color: rgba(52, 52, 52, 0.425) !important; + margin-bottom: 1em !important; + color: #f8f8f8 !important; + font-weight: 500 !important; + + background: #fbe3e4 url("../error.png") no-repeat 15px center; + padding: 10px; + padding-left: 50px; + margin: 15px; + z-index: 99999; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-border-radius: 5px; +} +#jError a { + color: #8a1f11 !important; + text-decoration: none; +} + +/** OVERLAY **/ +#jOverlay { + width: 100%; + height: 100%; + position: fixed; + top: 0; + left: 0; + z-index: 99998; +} + +.mailbox-content .form-email-compose .control-group { + margin-bottom: 10px; +} + +.fileupload-buttonbar .btn, +.fileupload-buttonbar .toggle { + margin-bottom: 5px; + background: rgba(51, 51, 51, 0.4); + border-color: transparent; + color: #fff; + text-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + -webkit-transition: background-color 0.2s; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.fileinput-button { + position: relative; + overflow: hidden; + float: left; + margin-right: 4px; + color: #fff; + text-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; + border-color: #c5c5c5; + border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25); + padding: 2px 10px; + font-size: 11.05px; + line-height: 1.9; + border-radius: 0; + display: inline-block; + margin-bottom: 0; + font-weight: 300; + text-align: center; + vertical-align: middle; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 4px 12px; + font-size: 13px; + line-height: 20px; + border-radius: 1px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; +} +.fileinput-button input { + position: absolute; + top: 0; + right: 0; + margin: 0; + opacity: 0; + filter: alpha(opacity=0); + transform: translate(-300px, 0) scale(4); + font-size: 23px; + direction: ltr; + cursor: pointer; +} +.fileupload-loading { + position: absolute; + left: 50%; + width: 128px; + height: 128px; + display: none; +} +.dropzone { + border: 1px dashed #eee; + margin-top: 10px; + font-size: 13px; + color: #eee; + line-height: 100px; + vertical-align: middle; +} + +.tooltip-inner { + max-width: 100% !important; +} + +.flex { + display: flex; +} +.flex-space-between { + justify-content: space-between; +} + +.widget-controls > a:hover { + color: rgba(255, 255, 255, 0.6); + text-decoration: none; +} + +.carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #e5603b; +} + +.modal-content { + max-height: calc(100vh - 100px); + overflow-y: auto; + overflow-x: hidden; +} + +/* 헤더 사람아이콘 */ +.account-picture img { + width: 40px; + margin-right: 5px; +} + +.img-circle { + border-radius: 50%; +} \ No newline at end of file Index: controltower/css/override.css =================================================================== diff -u --- controltower/css/override.css (revision 0) +++ controltower/css/override.css (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,1955 @@ +@import "common.css"; + +.notifications .alert a { + color: #f8f8f8; + font-weight: 700; + margin-left: 5px; +} + +/* 스크롤 테마 */ +::-webkit-scrollbar { + width: 8px; /* 스크롤바의 너비 */ + height: 8px; +} +::-webkit-scrollbar-thumb { + height: 30%; /* 스크롤바의 길이 */ + background: #313131; /* 스크롤바의 색상 */ + + border-radius: 10px; +} +::-webkit-scrollbar-track { + background-color: #4b4b4b; /*스크롤바 뒷 배경 색상*/ +} +.slimScrollBar { + background: #784a3d !important; +} + +/* btn */ +.btn { + transition: background-color 0.2s; +} +.btn-transparent.active { + color: white; + background: rgba(51, 51, 51, 0.55); + color: #ffffff; + background-color: #e5603b; + border-color: rgba(0, 0, 0, 0.15); +} +.btn:focus, +.btn.focus, +.btn:active:focus, +.btn:active.focus, +.btn.active:focus, +.btn.active.focus { + outline: 0px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +/* 멀티 셀렉트 할때 번지는 값 픽스 */ +.btn-block + .btn-block { + margin-top: 0px !important; +} + +/* 멀티 셀렉트 */ +.search-input { + width: 100%; + background: rgba(51, 51, 51, 0.4) !important; + border: 1px solid rgba(51, 51, 51, 0.425) !important; +} +.select2-search__field::-webkit-input-placeholder, +.select2-search__field::placeholder { + color: #999 !important; + padding-left: 6px; +} + +/* 데이터그리드 왼쪽 상단 로우 개수 선택하는 옵션 배경값 변경 */ +select option { + background: #3b3d40 !important; +} + +/*! Light */ +#light { + background-color: #000; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.8); + overflow: hidden; + padding: 0 0 4px; + width: 40px; + margin-left: 30px; + transform: rotate(270deg); +} + +#light span { + border-radius: 50px; + display: block; + height: 30px; + margin: 4px auto 0; + opacity: 0.5; + width: 30px; +} + +/*! Light colours */ +#red { + background-color: red; +} + +#orange { + background-color: orange; +} + +#green { + background-color: green; +} + +/*! Active states */ +#light span.active { + opacity: 1; +} + +#light #red.active { + box-shadow: 0 0 10px red; +} + +#light #orange.active { + box-shadow: 0 0 10px orange; +} + +#light #green.active { + box-shadow: 0 0 10px green; +} + +/* Dashboard 시작 */ +.c3-tooltip { + color: black !important; +} + +.c3-chart-arc path { + stroke-width: 0.4px; +} +/* Dashboard 종료 */ + +/* Analysis 분석 시작 */ +@media (max-width: 1200px) { + #quality-img { + display: none; + } +} + +.card-widget { + border: 0; + position: relative; +} + +.card { + margin-bottom: 1rem; +} + +.card { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + min-width: 0; + word-wrap: break-word; + background-clip: border-box; + border: 0 solid rgba(0, 0, 0, 0.125); + border-radius: 0.25rem; +} + +.widget-user .widget-user-image > img { + height: auto; + width: 200px; +} + +.widget-user .widget-user-image { + left: 50%; + margin-left: -100px; + position: absolute; + top: 300px; +} + +.widget-user .widget-user-header { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; + height: 135px; + padding: 1rem; + text-align: center; +} + +.img-circle { + border-radius: 50%; +} + +img { + vertical-align: middle; + border-style: none; +} + +/* fade in - out box 처리 */ +.fade-in-box { + animation: fadein 1s; + -moz-animation: fadein 1s; /* Firefox */ + -webkit-animation: fadein 1s; /* Safari and Chrome */ + -o-animation: fadein 1s; /* Opera */ +} + +@keyframes fadein { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@-moz-keyframes fadein { + /* Firefox */ + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@-webkit-keyframes fadein { + /* Safari and Chrome */ + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@-o-keyframes fadein { + /* Opera */ + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.fade-out-box { + animation: fadeout 3s; + -moz-animation: fadeout 3s; /* Firefox */ + -webkit-animation: fadeout 3s; /* Safari and Chrome */ + -o-animation: fadeout 3s; /* Opera */ + animation-fill-mode: forwards; +} + +@keyframes fadeout { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +@-moz-keyframes fadeout { + /* Firefox */ + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +@-webkit-keyframes fadeout { + /* Safari and Chrome */ + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +@-o-keyframes fadeout { + /* Opera */ + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +/* 유니타이핑 */ +#blinker { + -webkit-animation: blink 1.2s step-end infinite; + -moz-animation: blink 1.2s step-end infinite; + animation: blink 1.2s step-end infinite; +} +@keyframes blink { + from, + to { + opacity: 0; + } + 50% { + opacity: 1; + } +} +@-webkit-keyframes blink { + from, + to { + opacity: 0; + } + 50% { + opacity: 1; + } +} +@-moz-keyframes blink { + from, + to { + opacity: 0; + } + 50% { + opacity: 1; + } +} + +.darkBack { + background: rgba(51, 51, 51, 0.425) !important; + border: 1px solid rgba(51, 51, 51, 0.425) !important; +} +.searchDarkBack { + background: url(../../reference/lightblue4/docs/img/search-white.png) 5px 5px no-repeat rgba(51, 51, 51, 0.4) !important; + border: 1px solid rgba(51, 51, 51, 0.425) !important; +} + +/*데이터피커 css 처리*/ +.xdsoft_datetimepicker .xdsoft_label { + display: inline; + position: relative; + z-index: 9999; + margin: 0; + padding: 5px 3px; + font-size: 12px; + line-height: 20px; + font-weight: bold; + background-color: #fff; + float: left; + width: 182px; + text-align: center; + cursor: pointer; +} + +.xdsoft_datetimepicker .xdsoft_calendar th:first-child { + color: #ef7979 !important; +} + +.xdsoft_datetimepicker .xdsoft_calendar th:last-child { + color: #a0a0ff !important; +} + +.xdsoft_day_of_week0 { + color: #ef7979 !important; +} + +.xdsoft_day_of_week6 { + color: #a0a0ff !important; +} + +.dd { + position: relative; + display: block; + margin: 0; + padding: 0; + max-width: 600px; + list-style: none; + font-size: 13px; + line-height: 20px; +} + +.dd-list { + display: block; + position: relative; + margin: 0; + padding: 0; + list-style: none; +} + +.dd-list .dd-list { + padding-left: 30px; +} + +.dd-collapsed .dd-list { + display: none; +} + +.dd-item, +.dd-empty, +.dd-placeholder { + display: block; + position: relative; + margin: 0; + padding: 0; + min-height: 20px; + font-size: 13px; + line-height: 20px; +} + +.dd-handle { + display: block; + margin: 5px 0; + padding: 5px 10px; + color: #f8f8f8; + text-decoration: none; + background: rgba(51, 51, 51, 0.4); + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.dd-item > button { + display: block; + position: relative; + cursor: pointer; + float: left; + width: 25px; + height: 20px; + margin: 5px 0; + padding: 0; + text-indent: 100%; + white-space: nowrap; + overflow: hidden; + border: 0; + background: transparent; + font-size: 12px; + line-height: 1; + text-align: center; + font-weight: bold; + color: #f8f8f8; +} + +.dd-item > button:before { + content: "+"; + display: block; + position: absolute; + width: 100%; + text-align: center; + text-indent: 0; +} + +.dd-item > button[data-action="collapse"]:before { + content: "-"; +} + +.dd-placeholder, +.dd-empty { + margin: 5px 0; + padding: 0; + min-height: 30px; + background: rgba(51, 51, 51, 0.2); + border: 1px dashed rgba(255, 255, 255, 0.6); + box-sizing: border-box; + -moz-box-sizing: border-box; +} + +.dd-empty { + border: 1px dashed rgba(255, 255, 255, 0.6); + min-height: 100px; + background-size: 60px 60px; + background-position: 0 0, 30px 30px; +} + +.dd-dragel { + position: absolute; + pointer-events: none; + z-index: 9999; +} + +.dd-dragel > .dd-item .dd-handle { + margin-top: 0; +} + +.dd-dragel .dd-handle { + -webkit-box-shadow: 2px 4px 6px 0 rgba(0, 0, 0, 0.1); + box-shadow: 2px 4px 6px 0 rgba(0, 0, 0, 0.1); +} + +.dd-hover > .dd-handle { + background: #2ea8e5 !important; +} + +.nestable-lists { + display: block; + clear: both; + padding: 30px 0; + width: 100%; + border: 0; + border-top: 2px solid #ddd; + border-bottom: 2px solid #ddd; +} + +@media only screen and (min-width: 700px) { + .dd + .dd { + margin-left: 2%; + } +} +.dd-hover > .dd-handle { + background: #2ea8e5 !important; +} + +/* +* aside +*/ +.side-nav .category-wrap { + margin: 0; + border: none; + border-radius: 0; +} +.side-nav li a, +.side-nav .category-label { + color: inherit; + transition: background-color 0.2s; + text-decoration: none; + display: block; + padding: 10px; + border-radius: 6px; +} +.category-wrap li a { + padding: 4px 10px 4px 35px; +} + +.nav-tabs > li.active > a { + color: #a4c6ff !important; +} + +.widget-content { + margin: 10px 0 15px; +} + +.widget-content > div { + margin-top: 10px; +} + +.control-group p { + text-align: left; +} + +.control-label { + float: left; + width: 160px; + padding-top: 5px; + text-align: right; +} + +/* +* 데이터테이블 커스텀 +*/ +table thead tr th { + overflow: hidden; + white-space: nowrap; +} + +table tbody tr td { + border-bottom: 1px solid rgba(68, 68, 68, 0.7); + box-sizing: border-box; +} + +.dataTables_scrollBody::-webkit-scrollbar { + height: 10px; +} + +.dataTables_scrollBody:hover::-webkit-scrollbar-track { + background-color: #414141; +} + +.dataTables_scrollBody:hover::-webkit-scrollbar-thumb { + background-color: #784a3d; +} + +.dataTables_scrollBody::-webkit-scrollbar-track, +.dataTables_scrollBody::-webkit-scrollbar-thumb { + background-color: transparent; +} + +.dataTables_scrollBody::-webkit-scrollbar-thumb { + border-radius: 5px; +} + +.ribbon { + /* adjust the below to control the shape */ + --d: 5px; + --w: 100px; + --c: #333; + /**/ + + position: absolute; + top: 0; + right: 0; + transform: translate(29.29%, -100%) rotate(45deg); /* 29.29% = 100%*(1 - cos(45deg)) */ + color: #fff; + text-align: center; + width: var(--w); + transform-origin: bottom left; + padding: 5px 0 calc(var(--d) + 5px); + background: linear-gradient(rgba(0, 0, 0, 0.6) 0 0) bottom/100% var(--d) no-repeat var(--c); + clip-path: polygon( + 0 100%, + 0 calc(100% - var(--d)), + 50% calc(100% - var(--d) - var(--w) / 2), + 100% calc(100% - var(--d)), + 100% 100%, + calc(100% - var(--d)) calc(100% - var(--d)), + var(--d) calc(100% - var(--d)) + ); +} + +.landing { + padding: 0; +} + +/* +* Component: Timeline +* ------------------- +*/ +.timeline { + position: relative; + margin: 0 0 30px 0; + padding: 0; + list-style: none; +} +.timeline:before { + content: ""; + position: absolute; + top: 0; + bottom: 0; + width: 4px; + background: #ddd; + left: 31px; + margin: 0; + border-radius: 2px; +} +.timeline > li { + position: relative; + margin-right: 10px; + margin-bottom: 15px; +} +.timeline > li:before, +.timeline > li:after { + content: " "; + display: table; +} +.timeline > li:after { + clear: both; +} +.timeline > li > .timeline-item { + background: rgba(51, 51, 51, 0.3); + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1); + border-radius: 3px; + margin-top: 0; + color: #f8f8f8; + margin-left: 60px; + padding: 0; + position: relative; +} +.timeline > li > .timeline-item > .time { + color: #999; + float: right; + padding: 10px; + font-size: 12px; +} +.timeline > li > .timeline-item > .timeline-header { + margin: 0; + color: #555; + padding: 10px; + font-size: 13px; + line-height: 1.1; +} +.timeline > li > .timeline-item > .timeline-header > a { + font-weight: 600; +} +.timeline > li > .timeline-item > .timeline-body, +.timeline > li > .timeline-item > .timeline-footer { + padding: 10px; +} +.timeline > li > .fa, +.timeline > li > .glyphicon, +.timeline > li > .ion { + width: 30px; + height: 30px; + font-size: 15px; + line-height: 30px; + position: absolute; + color: #000; + background: #d2d6de; + border-radius: 50%; + text-align: center; + left: 18px; + top: 0; +} +.timeline > .time-label > span { + font-weight: 400; + padding: 5px; + display: inline-block; + background-color: #fff; + border-radius: 4px; +} +.timeline-inverse > li > .timeline-item { + background: rgba(51, 51, 51, 0.3); + border-left: 2px solid rgba(26, 26, 26, 0.425); + -webkit-box-shadow: none; + box-shadow: none; +} +.timeline-inverse > li > .timeline-item > .timeline-header { + border-bottom-color: #ddd; +} + +.timeline-inverse .arrow { + display: block; + position: absolute; + top: 10px; + left: -7px; + width: 0; + height: 0; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-right: 5px solid rgba(26, 26, 26, 0.425); +} + +.modalDarkBack { + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY3g9IjEwJSIgY3k9IjAiIHI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9InJnYmEoMTAyLCAxMDUsIDEwNCwgMC45MCkiLz48c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0icmdiYSg5MywgMTEyLCAxMTksIDAuODkpIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSJyZ2JhKDE2MCwgMTc0LCAxNTAsIDAuOTApIi8+PC9yYWRpYWxHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4="), + url("../../reference/light-blue/img/bgnoise_lg_dark.png"); + background-color: rgba(102, 105, 104, 0.9); + padding-bottom: 10px; + border: 2px dotted rgb(151 151 151 / 95%) !important; + background: linear-gradient( + -45deg, + rgb(59 59 59 / 93%), + rgb(74 78 91 / 91%), + rgb(83 83 83 / 90%), + rgb(40, 40, 40, 91%) + ); + background-size: 400% 400%; + -webkit-animation: gradient 15s ease infinite; + animation: gradient 15s ease infinite; +} + +@-webkit-keyframes gradient { + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } +} + +@keyframes gradient { + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } +} + +.tooltip-inner { + max-width: 100% !important; +} + +/* +* Datepicker +*/ +.datepicker { + top: 0; + left: 0; + padding: 4px; + margin-top: 1px; + color: #555555; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + -ms-border-radius: 1px; + -o-border-radius: 1px; + border-radius: 1px; +} + +.datepicker:before { + content: ""; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; + top: -7px; + left: 6px; +} + +.datepicker:after { + content: ""; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid white; + position: absolute; + top: -6px; + left: 7px; +} + +.datepicker > div { + display: none; +} + +.datepicker table { + width: 100%; + margin: 0; +} + +.datepicker td, +.datepicker th { + text-align: center; + width: 20px; + height: 20px; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + -ms-border-radius: 1px; + -o-border-radius: 1px; + border-radius: 1px; +} + +.datepicker td.day:hover { + background: #f8f8f8; + cursor: pointer; +} + +.datepicker td.day.disabled { + color: #f8f8f8; +} + +.datepicker td.old, +.datepicker td.new { + color: white; +} + +.datepicker td.active, +.datepicker td.active:hover { + background: #618fb0; + color: #fff; +} + +.datepicker td span { + display: block; + width: 47px; + height: 54px; + line-height: 54px; + float: left; + margin: 2px; + cursor: pointer; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + -ms-border-radius: 1px; + -o-border-radius: 1px; + border-radius: 1px; +} + +.datepicker td span:hover { + background: #eeeeee; +} + +.datepicker td span.active { + background: #618fb0; + color: #fff; +} + +.datepicker td span.old { + color: #999999; +} + +.datepicker th.switch { + width: 145px; +} + +.datepicker th.next, +.datepicker th.prev { + font-size: 19.5px; +} + +.datepicker thead tr:first-child th { + cursor: pointer; +} + +.datepicker thead tr:first-child th:hover { + background: #eeeeee; +} + +.project-date { + font-size: 10px; + color: #a4c6ff; +} + +.day-progress { + position: absolute; + top: 75%; + left: 50%; + translate: -50% -50%; + font-size: 14px; + font-weight: 600; +} + +.timeline:before { + left: 0px !important; + background: none; +} + +.time_element { + overflow-x: scroll; + white-space: nowrap; +} + +/** +* Chart +*/ +.echart-no-data { + position: relative; +} + +.echart-no-data .message { + position: absolute; + transform: translateY(-50%); + text-align: center; + width: 100%; + top: 50%; + left: 0; +} + +svg.overlay { + background-color: transparent; +} + +svg .node { + cursor: pointer; +} + +svg .node rect { + fill-opacity: 0.9; + shape-rendering: crispEdges; +} + +svg .node text { + pointer-events: none; + font-size: 12px; +} + +svg .link { + fill: none; + stroke: #ccc; + stroke-width: 1.5px; + stroke-opacity: 0.2; +} + +svg .link:hover { + stroke-opacity: 0.5; +} + +svg .templink { + fill: none; + stroke: red; + stroke-width: 3px; +} +svg .ghostCircle.show { + display: block; +} + +.dashboard-top-section { + min-height: 230px; +} + +.ms-choice { + height: 16px; + margin-top: unset; +} + +.needle, +.needle-center { + fill: #f1f2f6; +} + +#total-icon-legend { + position: absolute; + top: 250px; + right: 10px; +} + +#total-icon-legend > div { + display: flex; + align-items: center; + margin-bottom: 0.3em; +} + +#total-icon-legend > div:last-child { + margin-bottom: 0; +} + +#total-icon-legend > div > .text { + padding-top: 3px; + font-size: 10px; +} + +.circle { + display: inline-block; + background-color: red; + width: 11px; + height: 11px; + border-radius: 50px; + margin-top: 4px; + margin-right: 8px; + border: 1px solid white; +} + +.c3-bars path { + stroke: white; + stroke-width: 0.5px; +} + +@media (max-width: 768px) { + #chart-product-manpower svg { + position: absolute; + top: 100%; + } +} + +#chart-product-manpower { + position: relative; + height: 780px; +} + +#chart-product-manpower svg { + position: absolute; + top: 60%; + left: 50%; + transform: translate(-50%, -50%); +} + +.xlarge { + height: 500px !important; +} + +.chart-footer { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; /* 아이템을 왼쪽으로 정렬 */ + align-content: flex-start; /* 아이템을 위쪽으로 정렬 */ + width: 100%; +} +.chart-footer .footer-item { + border-top: 2px solid; + box-sizing: border-box; + width: 33.33%; /* 기본 너비 설정 */ + padding: 1px 2px; + background: rgba(51, 51, 51, 0.4); +} +.chart-footer .footer-item .item-name, +.chart-footer .footer-item .item-value { + text-align: center; + width: 100%; + margin-top: 2px; +} +.chart-footer .footer-item .item-value { + font-weight: bold; +} + +.chat-footer button { + margin-top: 0; +} + +#chart-manpower-requirement, +#chart-manpower-requirement-canvaswidget, +#chart-manpower-requirement-canvas { + width: 100% !important; +} + +#chart-manpower-requirement-label { + width: 100% !important; + position: relative !important; +} + +/* +* tree bar +*/ +#tree_bar_container .link { + fill: none; + stroke: #ccc; + stroke-opacity: 0.4; + stroke-width: 1px; +} +#tree_bar_container text { + font-family: "Arial Black", Gadget, sans-serif; + fill: white; + font-weight: bold; + font-size: 12px; + text-shadow: none; +} + +#tree_bar_container .xAxis .tick text { + fill: white; +} +#tree_bar_container .grid .tick line { + stroke: grey; + stroke-dasharray: 5, 10; + opacity: 0.7; +} +#tree_bar_container .grid path { + stroke-width: 0; +} + +#tree_bar_container .node circle { + fill: #999; +} +#tree_bar_container .node--internal circle { + fill: #555; +} + +#tree_bar_container .node--internal .root { + transform: translateX(10px); +} + +/* gant */ +#shcedule_update { + height: 28px; +} + +.project-progress .progress-group { + display: flex; + align-items: flex-start; + margin-bottom: 10px; +} + +.progress-group label { + flex-shrink: 0; + width: 150px; + line-height: 30px; + text-align: right; + margin-right: 5px; +} + +.progress-group .progress-desc { + display: flex; + align-items: flex-start; +} + +.progress-group .progress-desc .icon { + width: 38px; + height: 30px; +} + +.progress-group .progress-desc .progress-input { + flex-shrink: 0; + display: flex; + width: 125px; + align-items: center; +} + +.project-progress input { + width: 63px !important; + margin-right: 2px; + padding: 5px !important; + text-align: right; +} + +.project-progress .input-group-addon.input-desc { + display: flex; + width: auto; + text-align: left; + line-height: 18px; +} +.project-progress .input-group-addon .fa { + line-height: 15px; +} + +.project-progress .input-desc .font11 { + margin-left: 5px; + white-space: normal; + word-break: keep-all; +} + +/* vertical timeline chart */ +#vertical-timeline { + overflow-y: auto; + height: 732px; + padding-right: 20px; + margin: 0px; +} + +.timeline-container { + margin-bottom: 20px; +} + +.timeline-container ul { + margin: 0; + list-style: none; + position: relative; + color: #fff; + font-size: 13px; + padding: 15px 0 0 75px; +} + +.timeline-container ul:before { + content: ""; + width: 1px; + height: 100%; + position: absolute; + border-left: 2px dashed #fff; +} + +.timeline-container .session { + position: relative; + margin-left: 30px; + background-color: rgba(51, 51, 51, 1); + padding: 14px; + border-radius: 6px; + box-shadow: 0 0 4px rgba(0, 0, 0, 0.12), 0 2px 2px rgba(0, 0, 0, 0.08); +} + +.timeline-container .session:not(:first-child) { + margin-top: 40px; +} + +.timeline-container .session > span { + width: 2px; + height: 100%; + background: #fff; + left: -30px; + top: 0; + position: absolute; +} + +.timeline-container .session > span:before { + content: ""; + width: 10px; + height: 10px; + border-radius: 50%; + border: 2px solid #fff; + position: absolute; + background: #5470c6ff; + left: -4px; + top: 0; +} + +.timeline-container .session .time-range { + height: 100%; +} + +.timeline-container .session .time-range .date { + position: absolute; + font-size: 10px; + top: 0; + left: -74px; + font-weight: bold; + line-height: normal; +} + +.timeline-container .session > span:after { + top: calc(100% - 5px); +} + +.timeline-container .session-content .version { + font-weight: 600; + font-size: 14px; +} + +.timeline-container .session-content .summary { + margin-top: 5px; + font-weight: 300; +} + +.timeline-container .session-content .issuekey { + margin-top: 5px; + font-weight: 600; + font-size: 12px; +} + +.tree-container.widget.large, +.tree-container.widget.large .body { + height: auto; +} + +.vertical-chevron-up, +.vertical-chevron-down { + position: absolute; + left: 48%; + transform: translateY(-20px); + font-size: 20px; + cursor: pointer; +} + +.vertical-chevron-down { + transform: translateY(20px); +} + +.fa-chevron-up:hover, +.fa-chevron-down:hover { + opacity: 80%; +} + +@media screen and (max-width: 1295px) { + .timeline-period { + flex: 1 1 auto; + margin-bottom: 10px; + } +} + +.chat-message .chat-message-body { + margin-left: 0px !important; + padding: 8px 10px; + background: rgba(51, 51, 51, 0.3); + border-radius: 3px; + position: relative; +} + +.chat-message-body.on-left .arrow { + border-left: 5px solid #e5603b; +} + +.chat-message .chat-message-body.arrow:before { + content: ""; + display: block; + position: absolute; + top: 21px; + left: -7px; + width: 0; + height: 0; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-right: 5px solid #a4c6ff; +} + +.detail_qna .chat-message .sender { + display: flex; + flex-direction: column; + justify-content: center; +} + +.detail_qna .chat-message-body .arrow { + top: calc(50% - 5px); +} + +.detail_qna .chat-message .chat-message-body { + margin-left: 63px !important; +} + +.detail_qna .chat-message .chat-message-body.on-left { + margin-left: 0px !important; + border-right: 2px solid #e5603b; +} + +.detail_qna .chat-message-body .action-group { + margin-top: 15px; +} + +.detail_qna .chat-message-body .action-group button { + margin-right: 5px; + border: 0; + background-color: transparent; +} + +.detail_qna .date-separator { + text-align: center; + width: 180px; + margin: 30px auto; + padding: 6px; + font-size: 15px; + background: rgba(51, 51, 51, 0.3); + border-radius: 15px; +} + +.detail_qna .edit-text-area { + width: 100%; + resize: vertical; + background: transparent; +} + +.detail_qna .eidt-comment, +.detail_qna .edit-group { + display: none; +} + +.detail_qna .empty-message { + display: flex; + height: 550px; + justify-content: center; + align-items: center; +} + +.widget > .carousel { + margin: 0 -12px 5px; +} + +.carousel-control.left, +.carousel-control.right { + background: none; +} +.carousel-control i { + position: absolute; + top: 50%; + left: 50%; + z-index: 5; + display: inline-block; + width: 20px; + height: 45px; + margin-left: -10px; + margin-top: -10px; +} + +.carousel-indicators.outer { + bottom: -20px; +} +.carousel-indicators li { + background-color: rgba(51, 51, 51, 0.4); +} + +.service-portfolio .filter-options-wrap { + margin: 20px 0; +} +.service-portfolio .filter-option { + position: relative; + margin-bottom: 8px; + padding-left: 13px; + cursor: pointer; +} + +.service-portfolio .filter-active:before { + content: ""; + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 3px; + background-color: #e5603b; +} + +.service-portfolio .portfolio-wrap { + display: flex; + margin: 20px 0; +} + +.service-portfolio .portfolio-item { + float: none; +} + +.service-portfolio .portfolio-item-wrap { + position: relative; + height: 0; + padding-bottom: 100%; +} + +.service-portfolio .portfolio-item-wrap img { + width: 100%; +} + +.service-portfolio .portfolio-info { + opacity: 1; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + text-align: center; + z-index: 3; + transition: all ease-in-out 0.3s; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + overflow-wrap: anywhere; +} + +.service-portfolio .portfolio-item-wrap:before { + content: ""; + background: rgba(40, 40, 40, 0.5); + position: absolute; + left: 5px; + right: 5px; + top: 5px; + bottom: 5px; + transition: all ease-in-out 0.3s; + z-index: 2; + opacity: 0; +} + +.service-portfolio .portfolio-info { + opacity: 0; + transition: all ease-in-out 0.3s; +} + +.service-portfolio .portfolio-info h4, +.service-portfolio .portfolio-info p { + font-size: 12px; +} + +.service-portfolio .portfolio-info .portfolio-links a { + color: #fff; + margin: 5px 2px 0; + font-size: 20px; + display: inline-block; + transition: 0.3s; +} + +.service-portfolio .portfolio-info .portfolio-links a:hover { + color: #148af9; +} + +.service-portfolio .portfolio-item-wrap:hover:before { + top: -10px; + left: -10px; + right: -10px; + bottom: -10px; + opacity: 1; +} + +.service-portfolio .portfolio-item-wrap:hover .portfolio-info { + opacity: 1; +} + +.req-table, +.req-select { + background: rgba(51, 51, 51, 0.8) !important; + border: 1px solid rgba(51, 51, 51, 0.825) !important; +} + +.req-table.dropdown-menu a:hover, +.req-table.dropdown-menu .active a, +.req-select.dropdown-menu a:hover, +.req-select.dropdown-menu .active a { + background: none; +} + +.req-table.dropdown-menu a:hover, +.req-select.dropdown-menu a:hover, +#select2-selected_pdService-container .select2-selection__placeholder, +.multiple-select .ms-choice > span.placeholder { + color: #f8f8f8; +} +.req-table.dropdown-menu .active a, +.req-select.dropdown-menu .active a, +#disabled_input_pdservice.form-control { + color: #a4c6ff; +} + +.req-select { + min-width: auto; +} + +#reqDataTable { + padding-top: 0; + margin-bottom: 0; + max-height: 745px; + background: 0 none; + overflow: auto; +} + +#reqDataTable .reqTable { + width: max-content; + table-layout: fixed; +} + +#reqDataTable .reqTable th { + padding: 20px 10px 10px; + text-align: center; + position: sticky; + top: 0; + z-index: 1; + background-color: rgba(51, 51, 51, 0.9); +} + +#reqDataTable .reqTable td { + padding: 5px 10px; + text-align: center; +} + +#reqDataTable .reqTable td.depth1, +#reqDataTable .reqTable td.depth2, +#reqDataTable .reqTable td.depth3, +#reqDataTable .reqTable td.content { + text-align: left; +} + +#reqDataTable .reqTable .tbody input { + width: 100%; + border: 0 none; + background: 0 none; +} + +#reqDataTable .reqTable .tbody tr:nth-child(even) { + background-color: rgba(51, 51, 51, 0.325); +} +#reqDataTable .reqTable .tbody tr:first-child { + height: 37px !important; +} +#reqDataTable .reqTable .tbody tr td { + position: relative; + border-right: 2px solid #515256; +} + +#reqDataTable .reqTable { + cursor: default; +} + +#reqDataTable .reqTable th.version, +#reqDataTable .reqTable th.category, +#reqDataTable .reqTable th.id, +#reqDataTable .reqTable th.status, +#reqDataTable .reqTable th.priority, +#reqDataTable .reqTable th.difficulty, +#reqDataTable .reqTable th.createDate, +#reqDataTable .reqTable th.startDate, +#reqDataTable .reqTable th.endDate, +#reqDataTable .reqTable th.progress { + cursor: pointer; +} + +#reqDataTable .reqTable td.content { + cursor: text; +} + +#reqDataTable .reqTable th.version:after, +#reqDataTable .reqTable th.category:after, +#reqDataTable .reqTable th.id:after, +#reqDataTable .reqTable th.status:after, +#reqDataTable .reqTable th.priority:after, +#reqDataTable .reqTable th.difficulty:after, +#reqDataTable .reqTable th.createDate:after, +#reqDataTable .reqTable th.startDate:after, +#reqDataTable .reqTable th.endDate:after, +#reqDataTable .reqTable th.progress:after { + content: ""; + display: inline-block; + width: 19px; + height: 19px; + margin-left: 10px; + vertical-align: middle; + background-repeat: no-repeat; + background-position: center; + background-image: url(../img/datatable/sort_both.png); +} + +#reqDataTable .reqTable th.asc:after { + background-image: url(../img/datatable/sort_asc.png); +} + +#reqDataTable .reqTable th.desc:after { + background-image: url(../img/datatable/sort_desc.png); +} +#reqDataTable .root { + padding-left: 25px !important; + text-align: left !important; +} + +#reqDataTable .pivotTable { + min-width: 120%; +} + +#reqDataTable .pivotTable .highlight { + color: #a4c6ff; +} + +#reqDataTable .pivot-toggle { + margin-right: 3px; + padding: 0 3px; + background-color: transparent; +} +#reqDataTable .pivot-toggle .fa { + vertical-align: text-bottom; + font-size: 14px; + color: #a4c6ff; +} +#reqDataTable .pivot-toggle .fa-minus-square { + display: none; +} +#reqDataTable .pivot-toggle.active .fa-plus-square { + display: none; +} +#reqDataTable .pivot-toggle.active .fa-minus-square { + display: block; +} + +/* cost 분석 */ + +/* 비용 입력 */ +.cost-versions { + margin: 30px 0; + /*padding-left: 20px;*/ +} + +.cost-version, +.cost-input-complete { + margin-right: 10px; + padding: 3px 7px; + font-size: 11px; + font-weight: bold; + background-color: #5470c6ff; + border: none; + border-radius: 5px; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 3px 10px 0 rgba(0, 0, 0, 0.19); +} + +.cost-input-complete { + font-size: 15px; + background-color: rgb(51, 51, 51); + box-shadow: none; + margin: 0; +} + +.cost-version:hover, +.cost-input-complete:hover { + background-color: #39393b; +} + +.cost-input-version, +.cost-input-manpower { + margin-bottom: 20px; + border-radius: 3px; + padding: 5px; + margin-bottom: 30px; + background: rgba(51, 51, 51, 0.425); + color: #f8f8f8; +} + +.cost-version-info { + width: 30%; + margin: 10px 0 10px 0; + padding: 20px; + border-radius: 7px; + background-color: #4b4a4a; +} + +.cost-version-info div { + padding-top: 10px; +} + +.cost-input, +.annual-income-input { + color: black; + width: 50%; + text-align: center; + border: none; + border-radius: 5px; + padding: 5px; + background: rgba(157, 156, 156, 0.22); +} + +.version-input { + width: 70%; +} + +.dt-center { + text-align: center; +} + +.more { + display: inline-block; + border: 1px solid rgba(255, 255, 255, 0.3); + letter-spacing: 0; + z-index: 1; + position: relative; + margin-top: 10px; + color: #fff; + font-size: 13px; +} + +.animated-button1 { + display: inline-block; + -webkit-transform: translate(0%, 0%); + transform: translate(0%, 0%); + overflow: hidden; + color: #fff; + font-size: 12px; + text-decoration: none; +} + +.animated-button1::before { + content: ""; + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + background-color: #8593ad; + opacity: 0; + -webkit-transition: 0.2s opacity ease-in-out; + transition: 0.2s opacity ease-in-out; +} + +.animated-button1 span { + position: absolute; +} + +@keyframes animateTop { + 0% { + -webkit-transform: translateX(100%); + transform: translateX(100%); + } + + 100% { + -webkit-transform: translateX(-100%); + transform: translateX(-100%); + } +} + +.animated-button1 span:nth-child(1) { + top: 0px; + left: 0px; + width: 100%; + height: 1px; + background: -webkit-gradient(linear, right top, left top, from(rgba(43, 8, 8, 0)), to(#fff)); + background: linear-gradient(to left, rgba(43, 8, 8, 0), #fff); + -webkit-animation: 2s animateTop linear infinite; + animation: 2s animateTop linear infinite; +} + +@keyframes animateRight { + 0% { + -webkit-transform: translateY(100%); + transform: translateY(100%); + } + + 100% { + -webkit-transform: translateY(-100%); + transform: translateY(-100%); + } +} + +.animated-button1 span:nth-child(2) { + top: 0px; + right: 0px; + height: 100%; + width: 1px; + background: -webkit-gradient(linear, left bottom, left top, from(rgba(43, 8, 8, 0)), to(#fff)); + background: linear-gradient(to top, rgba(43, 8, 8, 0), #fff); + -webkit-animation: 2s animateRight linear -1s infinite; + animation: 2s animateRight linear -1s infinite; +} + +@keyframes animateBottom { + 0% { + -webkit-transform: translateX(-100%); + transform: translateX(-100%); + } + + 100% { + -webkit-transform: translateX(100%); + transform: translateX(100%); + } +} + +.animated-button1 span:nth-child(3) { + bottom: 0px; + left: 0px; + width: 100%; + height: 1px; + background: -webkit-gradient(linear, left top, right top, from(rgba(43, 8, 8, 0)), to(#fff)); + background: linear-gradient(to right, rgba(43, 8, 8, 0), #fff); + -webkit-animation: 2s animateBottom linear infinite; + animation: 2s animateBottom linear infinite; +} + +@keyframes animateLeft { + 0% { + -webkit-transform: translateY(-100%); + transform: translateY(-100%); + } + + 100% { + -webkit-transform: translateY(100%); + transform: translateY(100%); + } +} + +.animated-button1 span:nth-child(4) { + top: 0px; + left: 0px; + height: 100%; + width: 1px; + background: -webkit-gradient(linear, left top, left bottom, from(rgba(43, 8, 8, 0)), to(#fff)); + background: linear-gradient(to bottom, rgba(43, 8, 8, 0), #fff); + -webkit-animation: 2s animateLeft linear -1s infinite; + animation: 2s animateLeft linear -1s infinite; +} + +.modal-dialog .modal-content { + padding: 20px; +} + +.modal-dialog .widget-controls { + top: 20px !important; + right: 20px; +} + +@media (min-width: 768px) { + .modal-dialog { + width: 80%; + } +} + +.page-header .search-query { + width: 200px; +} +.page-header .search-query:focus { + width: 240px; +} + +#nav-search-button { + display: inline-block; + color: rgba(51, 51, 51, 0.5); + width: 40px; + padding: 0; + font-size: 19.5px; + outline: 0; + background: none; + text-align: center; + vertical-align: middle; + line-height: 36px; + text-shadow: none; +} + +#nav-search-button.highlight, +#nav-search-button.highlight a { + background: rgba(51, 51, 51, 0.5); + color: #b8b8b8; + border-radius: 3px; + font-size: 17px; + width: 30px; + line-height: 30px; +} + +/* 칸반 보드 */ +.kanban-top { + width: 100%; + margin-bottom: 30px; +} + +.kanban-top:last-child { + margin-bottom: 0; +} + +.kanban-container { + color: black; +} + +.kanban-item { + display: flex; + justify-content: space-between; + align-items: flex-end; +} + +.kanban-drag { + height: 550px !important; + overflow: auto; +} + +.show-info { + cursor: pointer; +} \ No newline at end of file Index: controltower/html/index/content-container.html =================================================================== diff -u --- controltower/html/index/content-container.html (revision 0) +++ controltower/html/index/content-container.html (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,987 @@ +
+
+
+

+ + + Feed + + 412 +

+ +
+
+
+
+ 1. 제품(서비스) 선택 +
+ +
+
+
+
+ + + + + +
+ +
+ +
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+ John Doe + commented on + What Makes Good Code Good + . +
+
3 h
+
+
+
+
+ +
+
+
+ Merge request #42 + has been approved by + Jessica Lori + . +
+
10 h
+
+
+
+
+ +
+
+
+ New user + Greg Wilson + registered. +
+
Today
+
+
+
+
+ +
+
+
+ Server fail level raises above normal. + See logs + for details. +
+
Yesterday
+
+
+
+
+ +
+
+
+ Database usage report + is ready. +
+
Yesterday
+
+
+
+
+ +
+
+
+ Order #233985 + needs additional processing. +
+
Wednesday
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ + Last logged-in users +
+
    +
  • + +
    + +
    Product Designer
    +
    Last logged-in: Mar 20, 18:46
    +
    +
  • +
  • + +
    + +
    Software Engineer
    +
    Last logged-in: Mar 23, 9:02
    +
    +
  • +
  • + +
    + +
    Chief Officer
    +
    Last logged-in: Jun 6, 15:34
    +
    +
  • +
  • + +
    + +
    Financial Assistant
    +
    Last logged-in: Jun 8, 17:20
    +
    +
  • +
  • + +
    + +
    Sales Manager
    +
    Last logged-in: Jun 8, 9:13
    +
    +
  • +
+
+
+
+ + Popular contacts +
+ +
+ +
+
+
+
+

Server Overview

+
+ 2 days ago +
+
+
+
    +
  • +
    CPU
    +
    +
    60% / 37°C / 3.3 Ghz
    +
    +
    +
    +
    +
  • +
  • +
    Mem
    +
    +
    29% / 4GB (16 GB)
    +
    +
    +
    +
    +
  • +
  • +
    LAN
    +
    +
    + 6 Mb/s + +   3 Mb/s + +
    +
    +
    +
    +
    +
  • +
+
+
+
+ +
+
+
+

+ + + Visits + + Based on a three months data +

+ +
+
+ +
+
+
  • +
    +
    + +
    + 선택된 제품(서비스) : + + 선택되지 않음 + +
    +
    +
    +
  • +
    +
    + +
    + +
    + + +
    +
    +
    + +
    +
    +
    +
    +
    + + Total Traffic +
    +
    + 24 541 + +
    +
    +
    +
    + + Unique Visits +
    +
    + 14 778 + +
    +
    +
    +
    + + Revenue +
    +
    + $3 583.18 + +
    +
    +
    +
    + + Total Sales +
    +
    + $59 871.12 + +
    +
    +
    +
    +
    +
    +
    +
    +

    + Traffic Sources + One month tracking +

    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    SourceAmountChangeTarget
    Direct713+53900
    Refer562+84500
    Social148-12180
    Search653+23876
    Internal976+101844
    +
    +
    +
    +
    +

    Chat

    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    4 min
    +
    +
    + + +
    + Hey Sam, how is it going? But I must explain to you how all this mistaken idea of denouncing of a + pleasure and praising pain was born +
    +
    +
    +
    +
    +
    + +
    +
    3 min
    +
    +
    + + +
    + Pretty good. Doing my homework.. No one rejects, dislikes, or avoids pleasure itself, because it is + pleasure, but because +
    +
    +
    +
    +
    +
    + +
    +
    2 min
    +
    +
    + + +
    + Any chance to go out? To take a trivial example, which of us ever undertakes laborious physical + exercise, except to obtain some advantage +
    +
    +
    +
    +
    +
    + +
    +
    2 min
    +
    +
    + + +
    + .. Maybe 40-50 mins. I don't know exactly. On the other hand, we denounce with righteous indignation and + dislike men who are so beguiled +
    +
    +
    +
    +
    +
    + +
    +
    1 min
    +
    +
    + + +
    Anyway sounds great! These cases are perfectly simple and easy to distinguish.
    +
    +
    +
    + +
    +
    +
    +
    Index: controltower/html/index/content-header.html =================================================================== diff -u --- controltower/html/index/content-header.html (revision 0) +++ controltower/html/index/content-header.html (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,13 @@ +

    + Dashboard + Statistics and more + +

    FishEye: Tag 5cd07d4d43536675e4294d68d4c75c61207ab65a refers to a dead (removed) revision in file `controltower/html/template/content-footer.html'. FishEye: No comparison available. Pass `N' to diff? Index: controltower/html/template/page-header.html =================================================================== diff -u --- controltower/html/template/page-header.html (revision 0) +++ controltower/html/template/page-header.html (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,241 @@ + + + + + + + Index: controltower/html/template/page-logo.html =================================================================== diff -u --- controltower/html/template/page-logo.html (revision 0) +++ controltower/html/template/page-logo.html (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,7 @@ +

    + + + +

    Index: controltower/html/template/page-sidebar.html =================================================================== diff -u --- controltower/html/template/page-sidebar.html (revision 0) +++ controltower/html/template/page-sidebar.html (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,234 @@ + + + + + + + + + Index: controltower/img/313_logo.png =================================================================== diff -u Binary files differ Index: controltower/index.html =================================================================== diff -u --- controltower/index.html (revision 0) +++ controltower/index.html (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,439 @@ + + + + A-RMS By 313DEVGRP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    +
    + +
    + + +
    +
    + +
    + + 로딩 + 어플리케이션 API Data를 가져오는 중입니다... + +
    + +
    + 맨위로 +
    + + + + + + + + + + + + + + Index: controltower/js/common.js =================================================================== diff -u --- controltower/js/common.js (revision 0) +++ controltower/js/common.js (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,1930 @@ +//////////////////////////////////////////////////////////////////////////////////////// +//Document Ready +//////////////////////////////////////////////////////////////////////////////////////// +$(function () { + var str = window.location.href; + if (str.indexOf("php") > 0) { + console.table("313DEVGRP 커뮤니티에 오신것을 환영합니다."); + runScript(); + } else { + authUserCheck(); + } +}); + +function runScript() { + // Page load & 상단 페이지 로드 프로그래스바 + topbarConfig(); + topbar.show(); + setTimeout(function () { + $(".container").fadeIn("slow"); + topbar.hide(); + }, 2000); + + /* 맨위로 아이콘 */ + rightBottomTopForwardIcon(); + + var urlParams = new URL(location.href).searchParams; + var onlyContents = urlParams.get("withoutLayer"); + if (isEmpty(onlyContents)) { + $("body").removeAttr("class"); + } else { + $("body").addClass("sidebar-hidden"); + $("header.page-header").hide(); + } + + $(document).on("shown.bs.tab", "a[data-toggle='tab']", function () { + window.dispatchEvent(new Event("resize")); + }); + + if (ajax_setup()) { + $(".loader").removeClass("hide"); + + var page = urlParams.get("page"); + if (isEmpty(page)) { + page = "index"; + } + if (includeLayout(page)) { + $.getScript("js/" + page + ".js", function () { + /* 로그인 인증 여부 체크 함수 */ + execDocReady(); + dwr_login(userName, userName); + }); + } + } +} + +function widgsterWrapper() { + var height; + + $.fn.widgster.Constructor.prototype.fullscreen = function () { + var e = $.Event("fullscreen.widgster"); + + this.$element.trigger(e); + + if (e.isDefaultPrevented()) return; + + this.$element.css({ + position: "fixed", + top: 0, + right: 0, + bottom: 0, + left: 0, + margin: 0, + overflow: "auto", + "z-index": 10000 + }); + + var body = this.$element.find(".body"); + var siblingsHeight = body + .siblings() + .toArray() + .reduce(function (acc, cur) { + return (acc += cur.clientHeight); + }, 0); + var margin = + parseInt(body.css("margin-top")) + + parseInt(body.css("margin-bottom")) + + parseInt(this.$element.css("padding-top")) + + parseInt(this.$element.css("padding-bottom")) + + parseInt(this.$element.css("margin-top")) + + parseInt(this.$element.css("margin-bottom")); + + // height = body.css("height"); + body.css("height", "calc(100% - " + (siblingsHeight + margin) + "px)"); + + $("body").css("overflow", "hidden"); + + this.wasCollapsed = this.collapsed; + this.expand(false); + + this.$fullscreen.hide(); + this.$restore.show(); + + this.$collapse.hide(); + this.$expand.hide(); + + this.$element.addClass("fullscreened"); + + this.$element.addClass("modalDarkBack"); + + this.$element.trigger($.Event("fullscreened.widgster")); + + return false; + }; + + $.fn.widgster.Constructor.prototype.restore = function () { + var e = $.Event("restore.widgster"); + + this.$element.trigger(e); + + if (e.isDefaultPrevented()) return; + + this.$element.css({ + position: "", + top: "", + right: "", + bottom: "", + left: "", + margin: "", + overflow: "", + "z-index": "" + }); + + this.$element.find(".body").css("height", height); + $("body").css("overflow", ""); + + this.$fullscreen.show(); + this.$restore.hide(); + + if (this.collapsed) { + this.$collapse.hide(); + this.$expand.show(); + } else { + this.$collapse.show(); + this.$expand.hide(); + } + + this.wasCollapsed && this.collapse(false); + + this.$element.removeClass("fullscreened"); + + this.$element.removeClass("modalDarkBack"); + + this.$element.trigger($.Event("restored.widgster")); + + return false; + }; +} + +function 로드_완료_이후_실행_함수() { + 톱니바퀴_초기설정(); + loadLocale(); + widgsterWrapper(); + 검색_이벤트_트리거(); + + 우측_상단_사용자_정보_설정(); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// 우측_상단_사용자_정보_설정 +//////////////////////////////////////////////////////////////////////////////////////// +function 우측_상단_사용자_정보_설정() { + + var str = window.location.href; + if (str.indexOf("php") > 0) { + var account_html = "not supported"; + $("#login_id").append(account_html); + }else { + var account_html = "\"" + userName + "\""; + $("#login_id").append(account_html); + } +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// 플러그인 로드 모듈 ( 병렬 시퀀스 ) +//////////////////////////////////////////////////////////////////////////////////////// +function loadPlugin(url) { + return new Promise(function (resolve, reject) { + if (isJavaScriptFile(url)) { + $(".spinner").html( + '로딩 ' + + getFileNameFromURL(url) + + " 자바스크립트를 다운로드 중입니다..." + ); + $.ajax({ + url: url, + dataType: "script", + cache: true, + success: function () { + // The request was successful + + console.log("[ common :: loadPlugin ] :: url = " + url + " 자바 스크립트 플러그인 로드 성공"); + resolve(); // Promise를 성공 상태로 변경 + }, + error: function () { + // The request failed + console.error("[ common :: loadPlugin ] :: url = " + url + " 플러그인 로드 실패"); + reject(); // Promise를 실패 상태로 변경 + } + }); + } else { + $(".spinner").html( + '로딩 ' + + getFileNameFromURL(url) + + " 스타일시트를 다운로드 중입니다..." + ); + $("", { + rel: "stylesheet", + type: "text/css", + href: url + }).appendTo("head"); + console.log("[ common :: loadPlugin ] :: url = " + url + " 스타일시트 플러그인 로드 성공"); + resolve(); + } + }); +} + +function getFileNameFromURL(url) { + var parts = url.split("/"); + return parts[parts.length - 1]; +} + +function isJavaScriptFile(filename) { + return filename.endsWith(".js"); +} + +function loadPluginGroupSequentially(group) { + return group.reduce(function (promise, url) { + return promise.then(function () { + return loadPlugin(url); + }); + }, Promise.resolve()); +} + +function loadPluginGroupsParallelAndSequential(groups) { + var promises = groups.map(function (group) { + return loadPluginGroupSequentially(group); + }); + return Promise.all(promises).then(function () { + 로드_완료_이후_실행_함수(); + }); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// include 레이아웃 html 파일을 로드하는 함수 +//////////////////////////////////////////////////////////////////////////////////////// +function includeLayout(page) { + var includeArea = $("[data-include]"); + var self, url; + $.each(includeArea, function () { + self = $(this); + url = self.data("include"); + console.log("[ common :: includeLayout ] url = " + url); + + var hrefLink = window.location.href; + var urlParams = new URL(location.href).searchParams; + var mode = urlParams.get("mode"); + + if (url.indexOf("content-header") !== -1) { + url = "html/" + page + "/content-header.html"; + self.load(url, function () { + self.removeAttr("data-include"); + }); + } else if (url.indexOf("content-container") !== -1) { + url = "html/" + page + "/content-container.html"; + self.load(url, function () { + self.removeAttr("data-include"); + }); + } else if (url.indexOf("page-sidebar") !== -1) { + if (mode == "detail" || hrefLink.indexOf("detail.html") > 0) { + url = "/arms/html/detail/page-sidebar.html"; + self.load(url, function () { + self.removeAttr("data-include"); + }); + } else { + url = "/arms/html/template/page-sidebar.html"; + self.load(url, function () { + self.removeAttr("data-include"); + }); + } + } else { + self.load(url, function () { + self.removeAttr("data-include"); + }); + } + }); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////////////// +//인증관련 공통 변수 +//////////////////////////////////////////////////////////////////////////////////////// +var userName; +var fullName; +var userApplicationRoles; +var userAttributes; +var userEnabled; +var userGroups; +var userID; +var userRealmRoles; +var permissions; +var userEmail; + +//////////////////////////////////////////////////////////////////////////////////////// +// 상단 페이지 로드 프로그래스바 설정 +//////////////////////////////////////////////////////////////////////////////////////// +function topbarConfig() { + topbar.config({ + autoRun: true, + barThickness: 3, + barColors: { + 0: "rgba(26, 188, 156, .9)", + ".25": "rgba(52, 152, 219, .9)", + ".50": "rgba(241, 196, 15, .9)", + ".75": "rgba(230, 126, 34, .9)", + "1.0": "rgba(211, 84, 0, .9)" + }, + shadowBlur: 10, + shadowColor: "rgba(0, 0, 0, .6)" + }); +} + +//////////////////////////////////////////////////////////////////////////////////////// +//슬림스크롤 +//////////////////////////////////////////////////////////////////////////////////////// +function makeSlimScroll(targetElement) { + $(targetElement).slimScroll({ + height: "250px", + railVisible: true, + railColor: "#222", + railOpacity: 0.3, + wheelStep: 10, + allowPageScroll: false, + disableFadeOut: false + }); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// 맨위로 아이콘 +//////////////////////////////////////////////////////////////////////////////////////// +function rightBottomTopForwardIcon() { + $("#topicon").click(function () { + $("html, body").animate({ scrollTop: 0 }, 400); + return false; + }); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// 로그인 인증 여부 체크 함수 +//////////////////////////////////////////////////////////////////////////////////////// +function authUserCheck() { + var str = window.location.href; + if (str.indexOf("community") > 0) { + runScript(); + } else { + $.ajax({ + url: "/auth-user/me", + type: "GET", + timeout: 7313, + global: false, + statusCode: { + 200: function (json) { + console.log("[ common :: authUserCheck ] userName = " + json.preferred_username); + console.log("[ common :: authUserCheck ] sub = " + json.sub); + console.log(json.realm_access.roles); + userName = json.preferred_username; + permissions = json.realm_access.roles; + userID = json.sub; + userEmail = json.email; + fullName = json.name; + + runScript(); + }, + 401: function (json) { + $(".loader").addClass("hide"); + jError("클라이언트가 인증되지 않았거나, 유효한 인증 정보가 부족하여 요청이 거부되었습니다."); + location.href = "/oauth2/authorization/middle-proxy"; + return false; + }, + 403: function (json) { + jError("서버가 해당 요청을 이해했지만, 권한이 없어 요청이 거부되었습니다."); + return false; + } + } + }); + + return true; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// 사용자 정보 로드 함수 +//////////////////////////////////////////////////////////////////////////////////////// +function getUserInfo() { + $.ajax({ + url: "/auth-user/search-user/" + userName, + data: { + sendData: "" + }, + type: "GET", + progress: true, + statusCode: { + 200: function (json) { + console.log("authUserCheck length = :: " + json.length); + if (json.length > 1) { + jError("중복된 사용자가 있습니다."); + } else if (json.length == 0) { + jError("사용자 정보가 조회되지 않습니다."); + } else { + userApplicationRoles = json[0].applicationRoles; + userAttributes = json[0].attributes; + userEnabled = json[0].enabled; + userGroups = json[0].groups; + userID = json[0].id; + userRealmRoles = json[0].realmRoles; + console.log("authUserCheck :: userApplicationRoles = " + userApplicationRoles); + console.log("authUserCheck :: userAttributes = " + userAttributes); + console.log("authUserCheck :: userEnabled = " + userEnabled); + console.log("authUserCheck :: userGroups = " + userGroups); + console.log("authUserCheck :: userID = " + userID); + console.log("authUserCheck :: userRealmRoles = " + userRealmRoles); + } + } + } + }); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// 유틸 : 말줄임표 +//////////////////////////////////////////////////////////////////////////////////////// +function getStrLimit(inputStr, limitCnt) { + if (isEmpty(inputStr)) { + return ""; + } else if (inputStr.length >= limitCnt) { + return inputStr.substr(0, limitCnt) + "..."; + } else { + return inputStr; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +//서버 바인딩 할 수가 없어서 프로토타입 목적으로 json 을 만들어서 로드하는 함수 +//////////////////////////////////////////////////////////////////////////////////////// +var getJsonForPrototype = function (url, bindTemplate) { + ajaxGet(url).then(function (data) { + bindTemplate(data); + }); +}; +var ajaxGet = (url) => + $.ajax({ + url, + type: "GET", + global: false, + statusCode: { + 200: function (data) { + return data.responseJSON; + } + } + }); + +function dateFormat(timestamp) { + var d = new Date(timestamp), // Convert the passed timestamp to milliseconds + yyyy = d.getFullYear(), + mm = ("0" + (d.getMonth() + 1)).slice(-2), // Months are zero based. Add leading 0. + dd = ("0" + d.getDate()).slice(-2), // Add leading 0. + hh = d.getHours(), + h = hh, + min = ("0" + d.getMinutes()).slice(-2), // Add leading 0. + ampm = "AM", + time; + + if (hh > 12) { + h = hh - 12; + ampm = "PM"; + } else if (hh === 12) { + h = 12; + ampm = "PM"; + } else if (hh == 0) { + h = 12; + } + + // ie: 2013-02-18, 8:35 AM + time = yyyy + "년" + mm + "월" + dd + "일 - " + h + ":" + min + " " + ampm; + + return time; +} + +function getToday() { + var date = new Date(); + return date.getFullYear() + "/" + ("0" + (date.getMonth() + 1)).slice(-2) + "/" + ("0" + date.getDate()).slice(-2); +} + +// 최대값, 최소값 +function maxValue(arr) { + if (isEmpty(arr)) { + return []; + } else { + return arr.reduce((max, val) => (max > val ? max : val)); + } +} + +function minValue(arr) { + if (isEmpty(arr)) { + return []; + } else { + return arr.reduce((min, val) => (min < val ? min : val)); + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// --- 왼쪽 사이드 메뉴 설정 --- // +//////////////////////////////////////////////////////////////////////////////////////// +function setSideMenu(categoryName, listName, collapse) { + console.log("[ common :: setSideMenu ] :: categoryName → " + categoryName + ", listName → " + listName); + + setTimeout(function () { + //jira_icon + if (categoryName === "sidebar_menu_jira") { + $("#side_jira_neutral_icon").removeClass("hidden"); + $("#side_jira_white_icon").addClass("hidden"); + } else { + $("#side_jira_neutral_icon").addClass("hidden"); + $("#side_jira_white_icon").removeClass("hidden"); + } //.jira_icon + + $(`#${categoryName}`).css({ color: "#a4c6ff" }); + $(`#${categoryName}`).css({ "font-weight": "900" }); + + if (isEmpty(listName)) { + console.log("[ common :: setSideMenu ] :: listName → is null"); + } else { + $(`#${listName}`).addClass("active"); + $(`#${listName}`).css({ color: "#a4c6ff" }); + $(`#${listName}`).css({ "font-weight": "900" }); + } + $(".spinner").html( + " 어플리케이션 API Data를 가져오는 중입니다..." + ); + }, 1000); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// -- jstree build 설정 -- // +//////////////////////////////////////////////////////////////////////////////////////// +function jsTreeBuild(jQueryElementID, serviceNameForURL) { + console.log("common :: jsTreeBuild : ( jQueryElementID ) → " + jQueryElementID); + console.log("common :: jsTreeBuild : ( serviceNameForURL ) → " + serviceNameForURL); + + console.log("common :: jsTreeBuild : ( href ) → " + $(location).attr("href")); + console.log("common :: jsTreeBuild : ( protocol ) → " + $(location).attr("protocol")); + console.log("common :: jsTreeBuild : ( host ) → " + $(location).attr("host")); + console.log("common :: jsTreeBuild : ( pathname ) → " + $(location).attr("pathname")); + console.log("common :: jsTreeBuild : ( search ) → " + $(location).attr("search")); + console.log("common :: jsTreeBuild : ( hostname ) → " + $(location).attr("hostname")); + console.log("common :: jsTreeBuild : ( port ) → " + $(location).attr("port")); + + $(jQueryElementID) + .bind("before.jstree", function (e, data) { + $("#alog").append(data.func + "
    "); + $("li:not([rel='drive']).jstree-open > a > .jstree-icon").css( + "background-image", + "url(../reference/jquery-plugins/jstree-v.pre1.0/themes/toolbar_open.png)" + ); + $("li:not([rel='drive']).jstree-closed > a > .jstree-icon").css( + "background-image", + "url(../reference/jquery-plugins/jstree-v.pre1.0/themes/ic_explorer.png)" + ); + }) + .jstree({ + // List of active plugins + plugins: ["themes", "json_data", "ui", "crrm", "dnd", "search", "types"], + themes: { theme: ["lightblue4"] }, + //contextmenu + contextmenu: { + items: { + // Could be a function that should return an object like this one + create: { + separator_before: true, + separator_after: true, + label: "Create", + action: false, + submenu: { + create_file: { + seperator_before: false, + seperator_after: false, + label: "File", + action: function (obj) { + this.create(obj, "last", { + attr: { + rel: "default" + } + }); + } + }, + create_folder: { + seperator_before: false, + seperator_after: false, + label: "Folder", + action: function (obj) { + this.create(obj, "last", { + attr: { + rel: "folder" + } + }); + } + } + } + }, + ccp: { + separator_before: false, + separator_after: true, + label: "Edit", + action: false, + submenu: { + cut: { + seperator_before: false, + seperator_after: false, + label: "Cut", + action: function (obj) { + this.cut(obj, "last", { + attr: { + rel: "default" + } + }); + } + }, + paste: { + seperator_before: false, + seperator_after: false, + label: "Paste", + action: function (obj) { + this.paste(obj, "last", { + attr: { + rel: "folder" + } + }); + } + }, + + changeType: { + seperator_before: false, + seperator_after: false, + label: "Change Type", + submenu: { + toFile: { + seperator_before: false, + seperator_after: false, + label: "toFile", + action: function (obj) { + this.set_type("default"); + } + }, + toFolder: { + seperator_before: false, + seperator_after: false, + label: "toFolder", + action: function (obj) { + this.set_type("folder"); + } + } + } + } + } + } + } + }, + + // I usually configure the plugin that handles the data first + // This example uses JSON as it is most common + json_data: { + // This tree is ajax enabled - as this is most common, and maybe a bit more complex + // All the options are almost the same as jQuery's AJAX (read the docs) + ajax: { + // the URL to fetch the data + url: serviceNameForURL + "/getChildNode.do", + cache: false, + // the `data` function is executed in the instance's scope + // the parameter is the node being loaded + // (may be -1, 0, or undefined when loading the root nodes) + data: function (n) { + // the result is fed to the AJAX request `data` option + console.log("[ common :: jsTreeBuild ] :: json data load = " + JSON.stringify(n)); + return { + c_id: n.attr ? n.attr("id").replace("node_", "").replace("copy_", "") : 1 + }; + }, + success: function (n) { + jSuccess("Product(service) Data Load Complete"); + $(jQueryElementID).jstree("search", $("#text").val()); + } + } + }, + // Configuring the search plugin + search: { + // As this has been a common question - async search + // Same as above - the `ajax` config option is actually jQuery's AJAX object + + /** + * v1 : 검색 버튼 클릭 시 API 호출 후 응답 데이터를 jstree 에 바인딩 + ajax: { + url: serviceNameForURL + "/searchNode.do", + // You get the search string as a parameter + data: function (str) { + return { + searchString: str + }; + }, + success: function (n) { + jSuccess("search data complete"); + } + } + */ + + /** + * v2 : 검색 버튼 클릭 시 jstree 노드 필터링을 통해 검색 + */ + show_only_matches: true, + search_callback: function (str, node) { + return node.data().search(str); + } + }, + // Using types - most of the time this is an overkill + // read the docs carefully to decide whether you need types + types: { + // I set both options to -2, as I do not need depth and children count checking + // Those two checks may slow jstree a lot, so use only when needed + max_depth: -2, + max_children: -2, + // I want only `drive` nodes to be root nodes + // This will prevent moving or creating any other type as a root node + valid_children: ["drive"], + types: { + // The default type + default: { + // I want this type to have no children (so only leaf nodes) + // In my case - those are files + valid_children: "none", + // If we specify an icon for the default type it WILL OVERRIDE the theme icons + icon: { + image: "../reference/jquery-plugins/jstree-v.pre1.0/themes/attibutes.png" + } + }, + // The `folder` type + folder: { + // can have files and other folders inside of it, but NOT `drive` nodes + valid_children: ["default", "folder"], + icon: { + image: "../reference/jquery-plugins/jstree-v.pre1.0/themes/ic_explorer.png" + } + }, + // The `drive` nodes + drive: { + // can have files and folders inside, but NOT other `drive` nodes + valid_children: ["default", "folder"], + icon: { + image: "../reference/jquery-plugins/jstree-v.pre1.0/themes/home.png" + }, + // those prevent the functions with the same name to be used on `drive` nodes + // internally the `before` event is used + start_drag: false, + move_node: false, + delete_node: false, + remove: false + } + } + }, + // UI & core - the nodes to initially select and open will be overwritten by the cookie plugin + + // the UI plugin - it handles selecting/deselecting/hovering nodes + ui: { + // this makes the node with ID node_4 selected onload + initially_select: ["node_4"] + }, + // the core plugin - not many options here + core: { + // just open those two nodes up + // as this is an AJAX enabled tree, both will be downloaded from the server + initially_open: ["node_2", "node_3"] + } + }) + .bind("create.jstree", function (e, data) { + $.post( + serviceNameForURL + "/addNode.do", + { + ref: data.rslt.parent.attr("id").replace("node_", "").replace("copy_", ""), + c_position: data.rslt.position, + c_title: data.rslt.name, + c_type: data.rslt.obj.attr("rel") + }, + function (r) { + if (r.status) { + $(data.rslt.obj).attr("id", "node_" + r.id); + jNotify("Notification : Add Node, Complete !"); + } else { + $.jstree.rollback(data.rlbk); + } + $(jQueryElementID).jstree("refresh"); + } + ); + }) + .bind("remove.jstree", function (e, data) { + data.rslt.obj.each(function () { + $.ajax({ + async: false, + type: "POST", + url: serviceNameForURL + "/removeNode.do", + data: { + c_id: this.id.replace("node_", "").replace("copy_", "") + }, + success: function (r) { + jNotify("Notification : Remove Node, Complete !"); + $(jQueryElementID).jstree("refresh"); + } + }); + }); + }) + .bind("rename.jstree", function (e, data) { + $.post( + serviceNameForURL + "/alterNode.do", + { + c_id: data.rslt.obj.attr("id").replace("node_", "").replace("copy_", ""), + c_title: data.rslt.new_name, + c_type: data.rslt.obj.attr("rel") + }, + function (r) { + if (!r.status) { + $.jstree.rollback(data.rlbk); + } + jSuccess("Rename Node Complete"); + $(jQueryElementID).jstree("refresh"); + } + ); + }) + .bind("set_type.jstree", function (e, data) { + $.post( + serviceNameForURL + "/alterNodeType.do", + { + c_id: data.rslt.obj.attr("id").replace("node_", "").replace("copy_", ""), + c_title: data.rslt.new_name, + c_type: data.rslt.obj.attr("rel") + }, + function (r) { + jSuccess("Node Type Change"); + $(jQueryElementID).jstree("refresh"); + } + ); + }) + .bind("move_node.jstree", function (e, data) { + data.rslt.o.each(function (i) { + console.log("##### move :::", data); + $.ajax({ + async: false, + type: "POST", + url: serviceNameForURL + "/moveNode.do", + data: { + c_id: $(this).attr("id").replace("node_", "").replace("copy_", ""), + ref: data.rslt.cr === -1 ? 1 : data.rslt.np.attr("id").replace("node_", "").replace("copy_", ""), + c_position: data.rslt.cp + i, + c_title: data.rslt.name, + copy: data.rslt.cy ? 1 : 0, + multiCounter: i + }, + success: function (r) { + if (r.status) { + $.jstree.rollback(data.rlbk); + } else { + $(data.rslt.oc).attr("id", "node_" + r.id); + if (data.rslt.cy && $(data.rslt.oc).children("UL").length) { + data.inst.refresh(data.inst._get_parent(data.rslt.oc)); + } + } + + jNotify("Notification : Move Node Complete !"); + + $(jQueryElementID).jstree("refresh"); + } + }); + }); + }) + .bind("select_node.jstree", function (event, data) { + // `data.rslt.obj` is the jquery extended node that was clicked + if ($.isFunction(jsTreeClick)) { + console.log("[ jsTreeBuild :: select_node ] :: data.rslt.obj.data('id')" + data.rslt.obj.attr("id")); + console.log("[ jsTreeBuild :: select_node ] :: data.rslt.obj.data('rel')" + data.rslt.obj.attr("rel")); + console.log("[ jsTreeBuild :: select_node ] :: data.rslt.obj.data('class')" + data.rslt.obj.attr("class")); + console.log("[ jsTreeBuild :: select_node ] :: data.rslt.obj.children('a')" + data.rslt.obj.children("a")); + console.log("[ jsTreeBuild :: select_node ] :: data.rslt.obj.children('ul')" + data.rslt.obj.children("ul")); + jsTreeClick(data.rslt.obj); + } + }) + .bind("loaded.jstree", function (event, data) { + // 성능 이슈로 자동으로 전부 펼치기 닫음. + // setTimeout(function () { + // $(jQueryElementID).jstree("open_all"); + // }, 1500); + + $(jQueryElementID).slimscroll({ + height: "545px" + }); + }); + + $("#mmenu input, #mmenu button").click(function () { + switch (this.id) { + case "add_default": + case "add_folder": + $(jQueryElementID).jstree("create", null, "last", { + attr: { + rel: this.id.toString().replace("add_", "") + } + }); + break; + case "search": + $(jQueryElementID).jstree("search", document.getElementById("text").value); + break; + case "text": + break; + default: + $(jQueryElementID).jstree(this.id); + break; + } + }); + + $("#mmenu .form-search").submit(function (event) { + event.preventDefault(); + + $(jQueryElementID).jstree("search", document.getElementById("text").value); + }); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// UTIL : 널 체크 +//////////////////////////////////////////////////////////////////////////////////////// +var isEmpty = function (value) { + if ( + typeof value === "undefined" || + value == "" || + value == null || + value == undefined || + (value != null && typeof value == "object" && !Object.keys(value).length) + ) { + return true; + } else { + return false; + } +}; + +//////////////////////////////////////////////////////////////////////////////////////// +//데이터 테이블 +//////////////////////////////////////////////////////////////////////////////////////// +function dataTable_build( + jquerySelector, + ajaxUrl, + jsonRoot, + columnList, + rowsGroupList, + columnDefList, + selectList, + orderList, + buttonList, + isServerSide, + scrollY, + data, + isAjax = true +) { + var jQueryElementID = jquerySelector; + var reg = /[\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\"]/gi; + var jQueryElementStr = jQueryElementID.replace(reg, ""); + + var responsiveRender = { + details: { + renderer: function (api, rowIdx, columns) { + var outer = ""; + var data = $.map(columns, function (col, i) { + return col.hidden + ? "
    " + + "
    " + + col.title + + "
    " + + "
    " + + col.data + + "
    " + + "
    " + : ""; + }).join(""); + outer += data; + outer += ""; + data = outer; + + return data ? $("").append(data) : false; + } + } + }; + + console.log("[ common :: dataTableBuild ] :: jQueryElementStr → " + jQueryElementStr); + console.log("[ common :: dataTableBuild ] :: jQueryElementID → " + jQueryElementID); + console.log("[ common :: dataTableBuild ] :: columnList → " + columnList); + console.log("[ common :: dataTableBuild ] :: rowsGroupList → " + rowsGroupList); + console.log("[ common :: dataTableBuild ] :: href → " + $(location).attr("href")); + console.log("[ common :: dataTableBuild ] :: protocol → " + $(location).attr("protocol")); + console.log("[ common :: dataTableBuild ] :: host → " + $(location).attr("host")); + console.log("[ common :: dataTableBuild ] :: pathname → " + $(location).attr("pathname")); + console.log("[ common :: dataTableBuild ] :: search → " + $(location).attr("search")); + console.log("[ common :: dataTableBuild ] :: hostname → " + $(location).attr("hostname")); + console.log("[ common :: dataTableBuild ] :: port → " + $(location).attr("port")); + console.log("[ common :: dataTableBuild ] :: ajaxUrl → " + ajaxUrl); + + var options = { + serverSide: isServerSide, + stateSave: false, + stateDuration: -1, + destroy: true, + processing: true, + responsive: false, + columns: columnList, + rowsGroup: rowsGroupList, + columnDefs: columnDefList, + select: selectList, + order: orderList, + buttons: buttonList, + scrollX: true, + scrollY: scrollY, + // lengthMenu: [[3, 5, 7, 10], [3, 5, 7, 10]], + language: { + processing: "", + loadingRecords: + ' 데이터를 처리 중입니다.' + }, + initComplete: function (settings, json) { + console.log("dataTableBuild :: drawCallmakeSlimScrollback"); + if ($.isFunction(dataTableCallBack)) { + //데이터 테이블 그리고 난 후 시퀀스 이벤트 + dataTableCallBack(settings, json); + } + }, + drawCallback: function (tableInfo) { + console.log("dataTableBuild :: drawCallback"); + if ($.isFunction(dataTableDrawCallback)) { + //데이터 테이블 그리고 난 후 시퀀스 이벤트 + dataTableDrawCallback(tableInfo); + } + } + }; + + if (isAjax) { + options.ajax = { + url: ajaxUrl, + dataSrc: jsonRoot + }; + } else { + options.data = data; + } + + var tempDataTable = $(jQueryElementID).DataTable(options); + + /*var tempDataTable = $(jQueryElementID).DataTable({ + ajax: { + url: ajaxUrl, + dataSrc: jsonRoot + }, + serverSide: isServerSide, + stateSave: false, + stateDuration: -1, + destroy: true, + processing: true, + responsive: false, + columns: columnList, + rowsGroup: rowsGroupList, + columnDefs: columnDefList, + select: selectList, + order: orderList, + buttons: buttonList, + scrollX: true, + scrollY: scrollY, + language: { + processing: "", + loadingRecords: + ' 데이터를 처리 중입니다.' + }, + initComplete: function (settings, json) { + console.log("dataTableBuild :: drawCallmakeSlimScrollback"); + if ($.isFunction(dataTableCallBack)) { + //데이터 테이블 그리고 난 후 시퀀스 이벤트 + dataTableCallBack(settings, json); + } + }, + drawCallback: function (tableInfo) { + console.log("dataTableBuild :: drawCallback"); + if ($.isFunction(dataTableDrawCallback)) { + //데이터 테이블 그리고 난 후 시퀀스 이벤트 + dataTableDrawCallback(tableInfo); + } + } + });*/ + + $(jQueryElementID + " tbody").on("click", "tr", function () { + if ($(this).hasClass("selected")) { + $(this).removeClass("selected"); + } else { + tempDataTable.$("tr.selected").removeClass("selected"); + $(this).addClass("selected"); + } + + var selectedData = tempDataTable.row(this).data(); + selectedData.selectedIndex = $(this).closest("tr").index(); + + var info = tempDataTable.page.info(); + selectedData.selectedPage = info.page; + + dataTableClick(tempDataTable, selectedData); + }); + + // ----- 데이터 테이블 빌드 이후 스타일 구성 ------ // + //datatable 좌상단 datarow combobox style + $(".dataTables_length").find("select:eq(0)").addClass("darkBack"); + $(".dataTables_length").find("select:eq(0)").css("min-height", "30px"); + //min-height: 30px; + + // ----- 데이터 테이블 빌드 이후 별도 스타일 구성 ------ // + //datatable 좌상단 datarow combobox style + $("body") + .find("[aria-controls='" + jQueryElementStr + "']") + .css("width", "50px"); + $(".dataTables_filter input[type=search]").css("width", "100px"); + $("select[name=" + jQueryElementStr + "]").css("width", "50px"); + + $.fn.dataTable.ext.errMode = function (settings, helpPage, message) { + console.log(message); + jError("Notification : Ajax Error, retry plz !"); + }; + + return tempDataTable; +} + +//////////////////////////////////////////////////////////////////////////////////////// +//공통 AJAX setup 처리 +//////////////////////////////////////////////////////////////////////////////////////// +function ajax_setup() { + $(document) + .ajaxStart(function () { + $(".loader").removeClass("hide"); + }) + .ajaxSend(function (event, jqXHR, ajaxOptions) { + //$(".loader").addClass("hide"); + }) + .ajaxSuccess(function (event, jqXHR, ajaxOptions, data) { + //$(".loader").addClass("hide"); + }) + .ajaxError(function (event, jqXHR, ajaxSettings, thrownError) { + $(".loader").addClass("hide"); + if (jqXHR.status == 401) { + jError("클라이언트가 인증되지 않았거나, 유효한 인증 정보가 부족하여 요청이 거부되었습니다.", { + /** + * [options] + * autoHide / Boolean Default : true - jNotify closed after TimeShown ms or by clicking on it + * clickOverlay / Boolean Default : false - If false, disables closing jNotify by clicking on the background overlay. + * MinWidth / Integer Default : 200 - In pixel, the min-width css property of the boxes. + * TimeShown / Integer Default : 1500 - In ms, time of the boxes appearances. + * ShowTimeEffect / Integer Default : 200 - In ms, duration of the Show effect + * HideTimeEffect / Integer Default : 200 - In ms, duration of the Hide effect + * LongTrip / Integer Default : 15 - Length of the move effect ('top' and 'bottom' verticals positions only) + * HorizontalPosition / String Default : right - Horizontal position. Can be set to 'left', 'center', 'right' + * VerticalPosition / String Default : top - Vertical position. Can be set to 'top', 'center', 'bottom'. + * ShowOverlay / Boolean Default : true - If true, a background overlay appears behind the jNotify boxes + * ColorOverlay / String Default : #000 - Color of the overlay background (only Hex. color code) + * OpacityOverlay / Integer Default : 0.3 - Opacity CSS property of the overlay background. From 0 to 1 max. + */ + autoHide: true, // added in v2.0 + TimeShown: 3000, + HorizontalPosition: "center", + VerticalPosition: "top" + // onCompleted : function(){ // added in v2.0 + // alert('jNofity is completed !'); + // } + }); + location.href = "/oauth2/authorization/middle-proxy"; + } else if (jqXHR.status == 403) { + jError("서버가 해당 요청을 이해했지만, 권한이 없어 요청이 거부되었습니다.", { + /** + * [options] + * autoHide / Boolean Default : true - jNotify closed after TimeShown ms or by clicking on it + * clickOverlay / Boolean Default : false - If false, disables closing jNotify by clicking on the background overlay. + * MinWidth / Integer Default : 200 - In pixel, the min-width css property of the boxes. + * TimeShown / Integer Default : 1500 - In ms, time of the boxes appearances. + * ShowTimeEffect / Integer Default : 200 - In ms, duration of the Show effect + * HideTimeEffect / Integer Default : 200 - In ms, duration of the Hide effect + * LongTrip / Integer Default : 15 - Length of the move effect ('top' and 'bottom' verticals positions only) + * HorizontalPosition / String Default : right - Horizontal position. Can be set to 'left', 'center', 'right' + * VerticalPosition / String Default : top - Vertical position. Can be set to 'top', 'center', 'bottom'. + * ShowOverlay / Boolean Default : true - If true, a background overlay appears behind the jNotify boxes + * ColorOverlay / String Default : #000 - Color of the overlay background (only Hex. color code) + * OpacityOverlay / Integer Default : 0.3 - Opacity CSS property of the overlay background. From 0 to 1 max. + */ + autoHide: true, // added in v2.0 + TimeShown: 3000, + HorizontalPosition: "center", + VerticalPosition: "top" + // onCompleted : function(){ // added in v2.0 + // alert('jNofity is completed !'); + // } + }); + location.href = "/oauth2/authorization/middle-proxy"; + } else if (jqXHR.status == 500) { + jError("서버가 해당 요청을 이해했지만, 실행 할 수 없습니다."); + } + }) + .ajaxComplete(function (event, jqXHR, ajaxOptions) { + Ladda.stopAll(); + }) + .ajaxStop(function () { + $(".loader").addClass("hide"); + }); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////////////// +//공통 AJAX SAMPLE +//////////////////////////////////////////////////////////////////////////////////////// +function ajax_sample() { + $.ajax({ + url: "요청을 보낼 URL", + type: "요청 type(GET 혹은 POST)을 명시", + data: "서버로 보내지는 데이터", + contentType: "서버로 보내지는 데이터의 content-type, 기본값은 application/x-www-form-urlencoded", + dataType: "서버 응답으로 받는 데이터 타입", + statusCode: { + 200: function (data) { + ////////////////////////////////////////////////////////// + console.log("ajax_build :: url = " + ajaxUrl); + for (var key in data) { + var value = data[key]; + console.log(key + "=" + value); + } + + var loopCount = 3; + for (var i = 0; i < loopCount; i++) { + console.log("loop check i = " + i); + } + ////////////////////////////////////////////////////////// + jSuccess("신규 제품 등록이 완료 되었습니다."); + } + }, + beforeSend: function () { + //$("#regist_pdservice").hide(); 버튼 감추기 + }, + complete: function () { + //$("#regist_pdservice").show(); 버튼 보이기 + }, + error: function (e) { + jError("신규 제품 등록 중 에러가 발생했습니다."); + } + }); +} + +//데이터 테이블 하위에 상세 리스트 보이는거 지우기 +function hideDetail_Datagrid() { + $("#hostTable") + .DataTable() + .rows() + .every(function () { + // If row has details expanded + if (this.child.isShown()) { + // Collapse row details + this.child.hide(); + $(this.node()).removeClass("shown"); + } + }); +} + +////////////////////////////////////////// +// 페이지 이동 처리 +////////////////////////////////////////// +function goToTemplatePage(pageName) { + let current_page = getPageName(this.location.search); + console.log("[common :: goToTemplatePage] :: current_page => " + current_page); + if(current_page === "searchEngine") { + console.log("[common :: goToTemplatePage] :: 검색페이지"); + } else { + console.log("[common :: goToTemplatePage] :: pageName => " + pageName); + window.location.href = "template.html?page=" + pageName; + } +} + +////////////////////////////////////////// +// 검색어 포함 페이지 이동 처리 +////////////////////////////////////////// +function goToTemplatePageWithSearchString(pageName, searchString) { + console.log("[common :: goToTemplatePageWithSearchString] :: pageName => " + pageName+", 검색어 => " + searchString); + let current_page = getPageName(this.location.search); + + if(current_page === "searchEngine") { + console.log("[common :: goToTemplatePageWithSearchString] :: current_page => " + current_page); + console.log("[common :: goToTemplatePageWithSearchString] :: 검색페이지"); + $("#search-input").val(searchString); + $("#search-button").click(); + } else { + console.log("[common :: goToTemplatePageWithSearchString] :: 검색어와 함께 페이지 이동"); + window.location.href = "/arms/template.html?page=" + pageName+"&searchString="+searchString; + } +} + +function laddaBtnSetting(라따적용_클래스이름_배열) { + for (i = 0; i < 라따적용_클래스이름_배열.length; i++) { + // add css + $(라따적용_클래스이름_배열[i]).addClass("ladda-button"); + + // Bind progress buttons and simulate loading progress + Ladda.bind(라따적용_클래스이름_배열[i], { + callback: function (instance) { + var progress = 0; + var interval = setInterval(function () { + progress = Math.min(progress + 0.1, 1); + instance.setProgress(progress); + + if (progress === 1) { + instance.stop(); + clearInterval(interval); + } + }, 250); + } + }); + } +} + +class UrlBuilder { + constructor() { + this.baseUrl = ""; + this.queryParams = {}; + } + + setBaseUrl(url) { + this.baseUrl = url; + return this; + } + + addQueryParam(key, value) { + this.queryParams[key] = value; + return this; + } + + build() { + const queryString = new URLSearchParams(this.queryParams).toString(); + return `${this.baseUrl}?${queryString}`; + } +} + +function getCookie(cname) { + var name = cname + "="; + var decodedCookie = decodeURIComponent(document.cookie); + var ca = decodedCookie.split(";"); + for (var i = 0; i < ca.length; i++) { + var c = ca[i]; + while (c.charAt(0) == " ") { + c = c.substring(1); + } + if (c.indexOf(name) == 0) { + return c.substring(name.length, c.length); + } + } + return ""; +} + +///////////////////////////////// +//투어가이드모드 쿠키 - 가져오기 +///////////////////////////////// +function getTourGuideMode() { + let tourGuideMode = getCookie("tourGuideMode"); + if (tourGuideMode) { + return tourGuideMode; + } else { + //쿠키가 없을 때, "on"으로 체크 + setTourGuideMode("on"); + return getCookie("tourGuideMode"); + } +} + +///////////////////////////////// +//투어가이드 쿠키 저장/수정 +///////////////////////////////// +function setTourGuideMode(mode) { + console.log("[ common :: setTourGuideMode ] :: mode → " + mode); + $.cookie("tourGuideMode", mode, { expires: 7 }); + return mode; +} + +function tourGuideStart() { + let pageName = getPageName(this.location.search); + console.log("[ common :: tourGuideStart ] :: pageName → " + pageName); + let tg = TourGuideApi.makeInstance(pageName); + tg.start(); +} + +function checkTourGuideMode() { + let tourGuideMode = getTourGuideMode(); + + if (!checkMobileDevice()) { + if (tourGuideMode === "off") { + console.log("common :: checkTourGuideMode : tourGuideMode is Off"); + } else { + //mode 가 없거나 on 일때 + console.log("common :: checkTourGuideMode : tourGuideMode is On"); + setTourGuideMode("on"); + setTimeout(function () { + tourGuideStart(); + }, 1200); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +//톱니바퀴(config) 투어가이드 이벤트리스너 +//////////////////////////////////////////////////////////////////////////////////////// +function tourGuideEventListener() { + console.log("common :: tourGuideEventListener : tourGuideEventListener 시작"); + let tgm = getCookie("tourGuideMode"); + if (tgm === "off") { + $("#tourGuideButtons #tour_guide_off").addClass("active"); + } else { + $("#tourGuideButtons #tour_guide_on").addClass("active"); + } + + $("#tourGuideButtons button").click(function () { + let $active_label = $(this).text().toLowerCase(); + console.log($active_label); + if ($active_label === "on") { + setTourGuideMode("on"); + } else { + setTourGuideMode("off"); + } + }); +} + +function getPageName() { + const queryString = location.search; + const params = new URLSearchParams(queryString); + const page = params.get("page"); + + if (!isEmpty(page)) { // page param의 위치 + return page; + } + return "페이지 이름 없음"; //페이지 이름이 없을 경우. +} + +//////////////////////////////////////////////////////////////////////// +// 모바일 디바이스인지 확인 +//////////////////////////////////////////////////////////////////////// +function checkMobileDevice() { + // 모바일 기기에서 접근했는지 확인 + const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); + console.log("[ common :: checkMobileDevice] isMobile → " + isMobile); + return isMobile; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// 헤더 :: 톱니바퀴 대응함수 +//////////////////////////////////////////////////////////////////////////////////////// +function 톱니바퀴_초기설정() { + //settings + var $settings = $("#settings"), + $sidebarSettings = $("#sidebar-settings"), + settingsState = { + sidebar: "left", + sidebarState: "auto", + displaySidebar: true + }, + $pageHeader = $(".page-header"), + $body = $("body"), + popoverReallyHide = function () { + $settings.data("bs.popover").hoverState = "out"; //yeah. cool BS3 fix. popover programmatic APi works only on HOVER + $settings.popover("hide"); + }, + popoverClose = function (e) { + var $popover = $settings.siblings(".popover"); + if ($popover.length && !$.contains($popover[0], e.target)) { + popoverReallyHide(); + $(document).off("click", popoverClose); + } + }, + sidebarSide = function (side) { + if (side == "right") { + $body.addClass("sidebar-on-right"); + } else { + $body.removeClass("sidebar-on-right"); + } + }, + sidebarState = function (state, triggerResize) { + var $template = $("#sidebar-settings-template"); + triggerResize = triggerResize == undefined ? true : false; + if (!$template[0]) { + return; + } + $sidebarSettings.html(_.template($template.html())({ sidebarState: state })); + if (state == "auto") { + $(".sidebar, .side-nav, .wrap, .logo").removeClass("sidebar-icons"); + } else { + $(".sidebar, .side-nav, .wrap, .logo").addClass("sidebar-icons"); + } + if (triggerResize) { + triggerChartsResize(); + } + }, + displaySidebar = function (display, triggerResize) { + triggerResize = triggerResize == undefined ? true : false; + if (display == true) { + $body.removeClass("sidebar-hidden"); + } else { + $body.addClass("sidebar-hidden"); + } + if (triggerResize) { + triggerChartsResize(); + } + }; + + sidebarSide(settingsState.sidebar); + sidebarState(settingsState.sidebarState, false); + displaySidebar(settingsState.displaySidebar, false); + + if (!$settings[0]) { + return; + } + + $settings + .popover({ + template: + '
    ' + + '
    ' + + '
    ' + + '
    ' + + "
    " + + "
    ", + html: true, + animation: false, + placement: "bottom", + content: function () { + if (typeof _ === "undefined") { + return "미지원"; + } + return _.template($("#settings-template").html())(settingsState); + } + }) + .click(function (e) { + //close all open dropdowns + $(".page-header .dropdown.open .dropdown-toggle").dropdown("toggle"); + // need to remove popover on anywhere-click + $(document).on("click", popoverClose); + $(this).focus(); + tourGuideEventListener(); // 투어가이드 이벤트리스너 설정. + return false; + }); + + $(".page-header .dropdown-toggle").click(function () { + popoverReallyHide(); + $(document).off("click", popoverClose); + }); + //sidevar left/right + $pageHeader.on("click", ".popover #sidebar-toggle .btn", function () { + var $this = $(this), + side = $this.data("value"); + sidebarSide(side); + settingsState.sidebar = side; + localStorage.setItem("settings-state", JSON.stringify(settingsState)); + }); + + //sidebar visibility + $pageHeader.on("click", ".popover #display-sidebar-toggle .btn", function () { + var $this = $(this), + display = $this.data("value"); + displaySidebar(display); + settingsState.displaySidebar = display; + localStorage.setItem("settings-state", JSON.stringify(settingsState)); + }); + + //sidebar state {active, icons} + $sidebarSettings.on("click", ".btn", function () { + var $this = $(this), + state = $this.data("value"); + if (state == "icons") { + closeNavigation(); + } + sidebarState(state); + settingsState.sidebarState = state; + localStorage.setItem("settings-state", JSON.stringify(settingsState)); + }); + + //close navigation if sidebar in icons state + if (($("#sidebar").is(".sidebar-icons") || $(window).width() < 1049) && $(window).width() > 767) { + closeNavigation(); + } + + //imitate buttons radio behavior + $pageHeader.on("click", ".popover [data-toggle='buttons-radio'] .btn:not(.active)", function () { + var $this = $(this), + $buttons = $this.parent().find(".btn"); + $buttons.removeClass("active"); + setTimeout(function () { + $this.addClass("active"); + }, 0); + }); +} + +/** + * A global object containing theme specific colors, screen variables & color functions. + * @type Object + */ +window.LightBlue = { + screens: { + "xs-max": 767, + "sm-min": 768, + "sm-max": 991, + "md-min": 992, + "md-max": 1199, + "lg-min": 1200 + }, + + isScreen: function (size) { + var screenPx = window.innerWidth; + return ( + (screenPx >= this.screens[size + "-min"] || size == "xs") && + (screenPx <= this.screens[size + "-max"] || size == "lg") + ); + }, + + getScreenSize: function () { + var screenPx = window.innerWidth; + if (screenPx <= this.screens["xs-max"]) return "xs"; + if (screenPx >= this.screens["sm-min"] && screenPx <= this.screens["sm-max"]) return "sm"; + if (screenPx >= this.screens["md-min"] && screenPx <= this.screens["md-max"]) return "md"; + if (screenPx >= this.screens["lg-min"]) return "lg"; + }, + + //credit http://stackoverflow.com/questions/1507931/generate-lighter-darker-color-in-css-using-javascript + changeColor: function (color, ratio, darker) { + var pad = function (num, totalChars) { + var pad = "0"; + num = num + ""; + while (num.length < totalChars) { + num = pad + num; + } + return num; + }; + // Trim trailing/leading whitespace + color = color.replace(/^\s*|\s*$/, ""); + + // Expand three-digit hex + color = color.replace(/^#?([a-f0-9])([a-f0-9])([a-f0-9])$/i, "#$1$1$2$2$3$3"); + + // Calculate ratio + var difference = Math.round(ratio * 256) * (darker ? -1 : 1), + // Determine if input is RGB(A) + rgb = color.match( + new RegExp( + "^rgba?\\(\\s*" + + "(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])" + + "\\s*,\\s*" + + "(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])" + + "\\s*,\\s*" + + "(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])" + + "(?:\\s*,\\s*" + + "(0|1|0?\\.\\d+))?" + + "\\s*\\)$", + "i" + ) + ), + alpha = !!rgb && rgb[4] != null ? rgb[4] : null, + // Convert hex to decimal + decimal = !!rgb + ? [rgb[1], rgb[2], rgb[3]] + : color + .replace(/^#?([a-f0-9][a-f0-9])([a-f0-9][a-f0-9])([a-f0-9][a-f0-9])/i, function () { + return parseInt(arguments[1], 16) + "," + parseInt(arguments[2], 16) + "," + parseInt(arguments[3], 16); + }) + .split(/,/), + returnValue; + + // Return RGB(A) + return !!rgb + ? "rgb" + + (alpha !== null ? "a" : "") + + "(" + + Math[darker ? "max" : "min"](parseInt(decimal[0], 10) + difference, darker ? 0 : 255) + + ", " + + Math[darker ? "max" : "min"](parseInt(decimal[1], 10) + difference, darker ? 0 : 255) + + ", " + + Math[darker ? "max" : "min"](parseInt(decimal[2], 10) + difference, darker ? 0 : 255) + + (alpha !== null ? ", " + alpha : "") + + ")" + : // Return hex + [ + "#", + pad(Math[darker ? "max" : "min"](parseInt(decimal[0], 10) + difference, darker ? 0 : 255).toString(16), 2), + pad(Math[darker ? "max" : "min"](parseInt(decimal[1], 10) + difference, darker ? 0 : 255).toString(16), 2), + pad(Math[darker ? "max" : "min"](parseInt(decimal[2], 10) + difference, darker ? 0 : 255).toString(16), 2) + ].join(""); + }, + lighten: function (color, ratio) { + return this.changeColor(color, ratio, false); + }, + darken: function (color, ratio) { + return this.changeColor(color, ratio, true); + } +}; +function triggerChartsResize() { + try { + if (window.onresize) { + window.onresize(); + } + } catch (e) { + //just swallow it + } + $(window).trigger("resize"); +} + +function targetLink(path) { + const params = {}; + + window.location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi, (str, key, value) => { + if (!isEmpty(path) && key === "page") { + params[key] = path; + } else { + params[key] = value; + } + }); + params["mode"] = "detail"; + + location.href = `/arms/detail.html?${new URLSearchParams(params).toString()}`; +} + +function gnuboardLink(bo_table) { + const params = {}; + + window.location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi, (str, key, value) => { + if (!isEmpty(bo_table) && key === "page") { + params[key] = "index"; + } else { + if (key == "wr_id") { + console.log("skip"); + } else { + params[key] = value; + } + } + }); + + delete params["wr_id"]; + params["bo_table"] = bo_table; + params["mode"] = "detail"; + + location.href = `/php/gnuboard5/bbs/board.php?${new URLSearchParams(params).toString()}`; +} + +function gnuboardList(param) { + const params = {}; + var userMode = false; + window.location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi, (str, key, value) => { + if (key == "mode") { + if (value == "detail") { + userMode = true; + } + } + params[key] = value; + }); + + if (userMode) { + params["mode"] = "detail"; + location.href = param + `&${new URLSearchParams(params).toString()}`; + } else { + location.href = param; + } +} + +function gnuboardIndex() { + const params = {}; + + window.location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi, (str, key, value) => { + if (key == "wr_id") { + console.log("skip"); + } else { + params[key] = value; + } + }); + params["page"] = "index"; + params["mode"] = "detail"; + + location.href = `/php/gnuboard5/index.php?${new URLSearchParams(params).toString()}`; +} +//////////////////////////////////////////////////////////////////////////////////////// +// 국제화 설정 +//////////////////////////////////////////////////////////////////////////////////////// +function loadLocale() { + const locale = getCookie("locale"); + changeLocale(locale || "ko"); +} + +function changeLocale(locale) { + const allowedLocale = ["ko", "jp", "en"]; + const selectedLocale = allowedLocale.includes(locale) ? locale : "ko"; + const $localeMenu = $(".locale-menu"); + $localeMenu.find(".locale-item").removeClass("active"); + $localeMenu.find(".locale-selector[data-key=" + selectedLocale + "]").closest(".locale-item").addClass("active"); + setCookie("locale", selectedLocale, 365); + setLocale(selectedLocale); +} + +function setLocale(locale = "ko") { + $.ajax({ + url: `/arms/locales/${locale}.json`, + async: false, + dataType: "json" + }).done(function (data) { + bindLocaleText(flattenObject(data)); + }); +} + +function bindLocaleText(locales) { + const targets = document.querySelectorAll("[data-locale]"); + + targets.forEach((tag) => { + const content = locales[tag.dataset.locale]; + if (content === undefined) { + console.warn("해당 키에 대한 국제화 문자열이 없습니다.", tag.dataset.locale); + return; + } + if (isIncludeHTMLTag(content)) { + tag.innerHTML = sanitizeHTML(content); + } else { + tag.textContent = content; + } + }); +} + +function isIncludeHTMLTag(content) { + return /<\/?[a-z][\s\S]*>/i.test(content); +} + +function sanitizeHTML(content) { + const allowedTags = ['span', 'small', 'strong', 'p', 'b', 'ul', 'li', 'br']; + return content.replace(/<(\w+)[^>]*>|<\/(\w+)>/g, (match, openTag, closeTag) => { + const tagName = (openTag || closeTag).toLowerCase(); + if (allowedTags.includes(tagName)) { + return match.replace(/ on\w+="[^"]*"| on\w+='[^']*'/g, ''); // 이벤트 핸들러 속성 제거 + } + return ''; // 허용되지 않은 태그 제거 + }); +} + +function flattenObject(obj, parentKey) { + let result = {}; + + Object.entries(obj).forEach(([key, value]) => { + const _key = parentKey ? parentKey + "." + key : key; + if (typeof value === "object") { + result = { ...result, ...flattenObject(value, _key) }; + } else { + result[_key] = value; + } + }); + + return result; +} + +///////////////////////////////////// +// 쿠키 설정 +///////////////////////////////////// +function setCookie(name, value, exp = 1) { + const path = "/arms"; + const date = new Date(); + date.setTime(date.getTime() + exp * 24 * 60 * 60 * 1000); + document.cookie = `${name}=${value};expires=${date.toUTCString()};path=${path}`; +} + +///////////////////////////////////// +// 검색_이벤트_트리거 +///////////////////////////////////// +function 검색_이벤트_트리거() { + $("#nav-search-input").on("focus", function(event) { + $("#nav-search-button").addClass("highlight"); + }); + + $("#nav-search-input").on("blur", function(event) { + $("#nav-search-button").removeClass("highlight"); + }); + // nav 검색창 + $("#search_form").on("submit", function (event) { + event.preventDefault(); + + let 검색어 = $("#nav-search-input").val().trim(); + if (검색어) { + console.log("[page-header :: nav-search-start] :: 검색어 입력 값 => " + 검색어); + setParameter("searchString", 검색어); + goToTemplatePageWithSearchString("searchEngine", 검색어); + } else { + console.log("[page-header :: nav-search-start] :: 검색어가 없습니다. 검색페이지로 이동합니다"); + goToTemplatePage("searchEngine"); + } + }); + + $("#nav-search-button").on("click", function (event) { + $("#search_form").trigger("submit"); + }); +} + +///////////////////////////////////////////// +// URL 파라미터값 찾기 +///////////////////////////////////////////// +function getParameter(param) { + param = param.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); + let regex = new RegExp("[\\?&]" + param + "=([^&#]*)"), + results = regex.exec(location.search); + return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); +} + +///////////////////////////////////////////// +// URL 파라미터값 수정 +///////////////////////////////////////////// +function setParameter(param, value) { + var url = new URL(window.location.href); + url.searchParams.set(param, value); + // Replace the currnt URL without reloading the page + window.history.pushState({path:url.href}, '', url.href); +} \ No newline at end of file Index: controltower/js/common/colorPalette.js =================================================================== diff -u --- controltower/js/common/colorPalette.js (revision 0) +++ controltower/js/common/colorPalette.js (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,147 @@ +colorPalette = { + colorPalette0: { + timeline: ["#FF8360", "#F4B374", "#E8E288", "#B3D885", "#7DCE82", "#5DD5AB", "#3CDBD3", "#1EEDE4", "#00FFF5"], + treeMap: ["#FF8360", "#F4B374", "#E8E288", "#B3D885", "#7DCE82", "#5DD5AB", "#3CDBD3", "#1EEDE4", "#00FFF5"] + }, + colorPalette1: { + timeline: [ + "#8EDF8A", + "#3ABAA1", + "#2C919D", + "rgba(7,202,209,0.7)", + "rgba(89,173,246,0.7)", + "rgba(156,148,255,0.7)", + "#A1AACE" + ], + treeMap: [ + "rgba(142,223,138,0.9)", + "rgba(58,186,161,0.9)", + "rgba(44,145,157,0.9)", + "rgba(7,202,209,0.7)", + "rgba(89,173,246,0.7)", + "rgba(156,148,255,0.7)", + "#A1AACE" + ] + }, + colorPalette2: { + timeline: ["#A3CEF1", "#879CB3", "#447199", "#E7ECEF", "#82B2D6", "#6096BA", "#274C77", "#97ADBD", "#8B8C89"], + treeMap: ["#A3CEF1", "#879CB3", "#447199", "#E7ECEF", "#82B2D6", "#6096BA", "#274C77", "#97ADBD", "#8B8C89"] + }, + colorPalette3: { + timeline: [ + "rgba(227,26,27,0.66)", + "rgba(55,125,184,0.62)", + "rgba(77,175,74,0.65)", + "rgba(255,127,0,0.7)", + "rgba(255,255,51,0.71)", + "rgba(151,78,163,0.73)", + "rgba(166,86,40,0.7)" + ], + treeMap: [ + "rgba(227,26,27,0.66)", + "rgba(55,125,184,0.62)", + "rgba(77,175,74,0.65)", + "rgba(255,127,0,0.7)", + "rgba(255,255,51,0.71)", + "rgba(151,78,163,0.73)", + "rgba(166,86,40,0.7)" + ] + }, + colorPalette4: { + timeline: ["#C6DEA6", "#A2CEB5", "#7EBDC3", "#A6C7AD", "#CED097", "#ACAE85", "#898C73", "#676A61"], + treeMap: ["#C6DEA6", "#A2CEB5", "#7EBDC3", "#A6C7AD", "#CED097", "#ACAE85", "#898C73", "#676A61"] + }, + + colorPalette5: { + timeline: ["#22AED1", "#5BB3C8", "#93B7BE", "#6C7F86", "#9F7832", "#FAA916", "#8DD353", "#20FC8F"], + treeMap: ["#22AED1", "#5BB3C8", "#93B7BE", "#6C7F86", "#9F7832", "#FAA916", "#8DD353", "#20FC8F"] + }, + colorPalette6: { + timeline: ["#58636A", "#6C7F86", "#809BA2", "#93B7BE", "#77B5C3", "#5BB3C8", "#3FB1CD", "#22AED1"], + treeMap: ["#58636A", "#6C7F86", "#809BA2", "#93B7BE", "#77B5C3", "#5BB3C8", "#3FB1CD", "#22AED1"] + }, + colorPalette7: { + timeline: ["#626277", "#766C86", "#8C7693", "#A4809E", "#BD89A5", "#6D5054", "#D09EA5"], + treeMap: ["#626277", "#766C86", "#8C7693", "#A4809E", "#BD89A5", "#6D5054", "#D09EA5"] + } +}; + +var dashboardPalette = { + dashboardPalette01: { + projectProgressColor: ["#e49400", "#e47e00", "#e46900", "#e45300", "#e43d00"], + appProgressColor: ["#138808", "#e46700", "#3D4049"], + statusPerWaveColor: ["#2f3238", "#E49400", "#e47a00", "#e46700", "#e43d00", "#148e08"], + inventoryPerWaveColor: ["#55DDE0", "#32658A", "#2F4858", "#F6AE2D", "#F48923", "#f25a19"], + strategyPerWaveColor: ["#e49400", "#e47e00", "#e46900", "#e45300", "#e43d00", "#f25a19"], + migGroupPerWaveColor: ["#3457D5", "#5D8AA8", "#1F305E"] + }, + dashboardPalette02: { + projectProgressColor: [ + "#E49400", + "#B09102", + "#7C8E04", + "#488B06", + "#138808", + "#488B06", + "#7C8E04", + "#B09102", + "#E49400" + ], + appProgressColor: ["#e46700", "#3D4049", "#138808"], + statusPerWaveColor: ["#2f3238", "#E49400", "#e47a00", "#e46700", "#e43d00", "#148e08"], + inventoryPerWaveColor: ["#182E3D", "#4A8FBD", "#82A5BD", "#5E7788", "#5D8AA8", "#2c5571"], + strategyPerWaveColor: ["#e49400", "#e47e00", "#e46900", "#e45300", "#e43d00", "#f25a19"], + migGroupPerWaveColor: ["#3457D5", "#5D8AA8", "#2c5571", "#1F305E"] + }, + dashboardPalette03: { + projectProgressColor: ["rgba(55,71,85)", "rgba(200,96,54)"], + appProgressColor: ["rgba(55,71,85)", "rgba(200,96,54)", "rgba(87,86,86)"], + statusPerWaveColor: [ + "rgba(87,86,86)", + "rgba(200,96,54)", + "rgba(170,91,61)", + "rgba(130,84,70)", + "rgba(90,78,78)", + "rgba(55,71,85)" + ], + inventoryPerWaveColor: [ + "rgba(55,71,85)", + "rgba(74,75,82)", + "rgba(90,78,78)", + "rgba(109,81,74)", + "rgba(149,81,74)", + "rgba(200,96,54)" + ], + strategyPerWaveColor: [ + "rgba(55,71,85)", + "rgba(55,71,85)", + "rgba(55,71,85)", + "rgba(55,71,85)", + "rgba(55,71,85)", + "rgba(55,71,85)" + ], + migGroupPerWaveColor: ["#6886A1", "#3F5161", "#374755", "#26313B"] + }, + dashboardPalette04: { + projectProgressColor: [ + "#E49400", + "#B09102", + "#7C8E04", + "#488B06", + "#138808", + "#488B06", + "#7C8E04", + "#B09102", + "#E49400" + ], + appProgressColor: ["#e46700", "#3D4049", "#138808"], + statusPerWaveColor: ["#2f3238", "#E49400", "#e47200", "#e45000", "#e44400", "#148e08"], + inventoryPerWaveColor: ["#264961", "#4A8FBD", "#82A5BD", "#5E7788", "#5D8AA8", "#2c5571"], + inventoryDotColor: "#bfdef3", + inventoryDotStrokeColor: "#182E3D", + inventoryPathColor: "#182E3D", + strategyPerWaveColor: ["#E49400", "#e47200", "#e45000", "#e44400"], + strategyPathColor: "#1F305E", + migGroupPerWaveColor: ["#3457D5", "#5D8AA8", "#2c5571", "#1F305E"] + } +}; Index: controltower/js/common/dwrChat.js =================================================================== diff -u --- controltower/js/common/dwrChat.js (revision 0) +++ controltower/js/common/dwrChat.js (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,83 @@ +document.write(''); +document.write(''); +document.write(''); + +const makeSaveChatHistory = () => { + const chat_history = []; + return (userId, username, message, time) => { + chat_history.push({ userId, username, message, time }); + if (chat_history.length > 10) { + chat_history.shift(); // 첫 번째 요소 제거 (가장 오래된 메시지) + } + console.log("chatHistory -> " + JSON.stringify(chat_history)); + return chat_history; + }; +}; + +const saveChatHistory = makeSaveChatHistory(); + +function dwr_callback(userId, username, message, time) { + const lastMessage = { userId, username, message, time }; + saveChatHistory(userId, username, message, time); + + if (message.indexOf("Engine]") >= 0){ + Messenger().post({ + message: message, + type: 'success', + showCloseButton: true + }); + } + + if (message.indexOf("Server]") >= 0){ + $(".notifications.pull-right").addClass("alert-created"); + const alertDiv = $('
    ').addClass('alert pull-right'); + const closeButton = $('').addClass('close').attr('data-dismiss', 'alert').text('×'); + const infoIcon = $('').addClass('fa fa-info-circle').css("color","#a4c6ff").css('margin-right', '5px').css('vertical-align','middle'); + alertDiv.append(closeButton, infoIcon, lastMessage.message); + $(".notifications.pull-right .alert").remove(); + $(".notifications.pull-right").append(alertDiv); + } + +} + +function dwr_login(userId,username){ + dwr.engine.setActiveReverseAjax(true); + dwr.engine.setNotifyServerOnPageUnload(true); + dwr.engine.setErrorHandler(function () { + Messenger().post({ + message: "서버와의 실시간 네트워크 통신에 문제를 감지했습니다. ( 재시도 합니다 )", + type: 'error', + showCloseButton: true + }); + }); + Chat.login(userId,username); + + buildMessage(); +} + +function buildMessage() { + var theme = 'air'; + + $.globalMessenger({ theme: theme }); + Messenger.options = { theme: theme }; + + //Messenger().post("Thanks for checking out Messenger!"); + + + var loc = ['bottom', 'right']; + + var $lsel = $('.location-selector'); + + var update = function(){ + var classes = 'messenger-fixed'; + + for (var i=0; i < loc.length; i++) + classes += ' messenger-on-' + loc[i]; + + $.globalMessenger({ extraClasses: classes, theme: theme }); + Messenger.options = { extraClasses: classes, theme: theme }; + }; + + update(); + +} \ No newline at end of file Index: controltower/js/common/table.js =================================================================== diff -u --- controltower/js/common/table.js (revision 0) +++ controltower/js/common/table.js (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,252 @@ +(function ($) { + "use strict"; + + var Table = function (selector) { + this.$selector = $(selector); + this.selector = selector; + this.table; + this.selectedData; + this.onDataTableClick; + this.onInit; + }; + + Table.prototype.onToggleCheckAll = function (element) { + if (!element) return; + + var tr = this.table.rows().nodes(); + var isChecked = $(element).prop("checked"); + console.log(isChecked); + + if (isChecked) { + this.table.rows().select(); + } else { + this.table.rows().deselect(); + } + + $.each(tr, function () { + $(this).find('input[type="checkbox"]').prop("checked", isChecked); + }); + }; + + Table.prototype.onToggleCheckbox = function (element) { + var tr = $(element); + var checkbox = tr.find('input[type="checkbox"]'); + var isChecked = tr.hasClass("selected"); + + checkbox.prop("checked", isChecked); + }; + + Table.prototype.onRowClick = function (element, multi) { + var tr = $(element); + this.selectedData = this.table.row(tr).data(); + + if (tr.hasClass("selected")) { + tr.removeClass("selected"); + + if ($.isFunction(this.onDeselect)) { + this.onDeselect(this.selectedData, element); + } + + this.selectedData = null; + } else { + if (!multi) { + this.table.$("tr.selected").removeClass("selected"); + } + tr.addClass("selected"); + + if ($.isFunction(this.onDataTableClick)) { + this.onDataTableClick(this.selectedData, element); + } + } + }; + + Table.prototype.dataTableExtendBuild = function (params) { + var responsive = { + details: { + renderer: function (api, rowIdx, columns) { + var outer = "
    "; + + return outer ? $("
    "; + + var data = $.map(columns, function (col, i) { + return col.hidden + ? `
    +
    + ${col.title} +
    +
    + ${col.data} +
    ` + : ``; + }).join(``); + outer += data; + outer += "
    ").append(outer) : false; + } + } + }; + var tableBuildParams = $.extend(true, {}, params, { responsive: responsive }); + + this.dataTableBuild(tableBuildParams); + }; + + Table.prototype.dataTableBuild = function (params) { + var self = this; + var defaults = { + data: [], + stateSave: true, + destroy: true, + processing: true, + serverSide: false, + scrollX: true, + responsive: false, + columns: this.columns, + rowsGroup: null, + columnDefs: [], + isAddCheckbox: false, + isDeleteUtil: false, + select: {}, + pagingType: "simple_numbers", + oLanguage: { + oPaginate: { + sNext: '', + sPrevious: '' + } + }, + order: [[0, "asc"]], + buttons: [ + "copy", + { + extend: "csv", + charset: "UTF-8", + bom: true + }, + "excel", + "print", + { + extend: "pdfHtml5", + orientation: "landscape", + pageSize: "LEGAL" + } + ], + language: { + processing: "", + loadingRecords: + ' 데이터를 처리 중입니다.' + } + }; + + var tableBuildParams = $.extend({}, defaults, params); + + tableBuildParams.initComplete = function () { + var dataTableLength = $(".dataTables_length").find("select:eq(0)"); + var tableWrapper = $(self.selector + "_wrapper"); + + dataTableLength.addClass("darkBack"); + dataTableLength.children().css("background", "#3B3D40"); + dataTableLength.css("border-radius", "5px"); + dataTableLength.css("min-height", "30px"); + tableWrapper.css("border-top", "1px solid rgba(51, 51, 51, 0.3)"); + tableWrapper.css("padding-top", "5px"); + + tableWrapper.find("input[type=search]").css("width", "80px"); + + if (tableBuildParams.isDeleteUtil) { + $(self.selector + "_length").remove(); + $(self.selector + "_filter").remove(); + $(self.selector + "_info").remove(); + $(self.selector + "_paginate").remove(); + } + + if ($.isFunction(self.onInit)) { + self.onInit(); + } + }; + + if (tableBuildParams.isAddCheckbox) { + tableBuildParams.columnDefs = [ + { + targets: 0, + orderable: false, + searchable: false, + data: null, + defaultContent: "", + className: "select-checkbox" + }, + { targets: 1, aDataSort: [1] } + ].concat(tableBuildParams.columnDefs); + + tableBuildParams.columns = [ + { + data: null, + title: '', + render: function () { + return ''; + }, + className: "dt-body-center" + } + ].concat(tableBuildParams.columns); + + tableBuildParams.select = { style: "multi" }; + } + + this.table = this.$selector.DataTable(tableBuildParams); + + $(this.selector + " tbody").on("click", "tr", function () { + self.onRowClick(this, tableBuildParams.isAddCheckbox); + + if (tableBuildParams.isAddCheckbox) { + self.onToggleCheckbox(this); + } + }); + + if (tableBuildParams.isAddCheckbox) { + $(this.selector + "_wrapper .dataTables_scrollHead thead").on("change", 'input[name="checkall"]', function () { + self.onToggleCheckAll(this); + }); + } + + $.fn.dataTable.ext.errMode = function () { + jError("Notification : Ajax Error, retry plz !"); + }; + }; + + Table.prototype.clear = function () { + this.table.clear(); + }; + + Table.prototype.addRows = function (rows) { + this.table.rows.add(rows).draw(false); + }; + + Table.prototype.reDraw = function (rows) { + this.selectedData = null; + this.clear(); + this.addRows(rows); + }; + + Table.prototype.empty = function () { + this.table.destroy(); + this.$selector.empty(); + }; + + Table.prototype.removeRows = function (callback) { + var selectedRows = this.table.rows({ selected: true }); + var selectedDatas = selectedRows.data().toArray(); + + selectedRows.remove().draw(); + + if ($.isFunction(callback)) { + callback(selectedDatas); + } + }; + + Table.prototype.getSelectedDataList = function () { + return this.table.rows({ selected: true }).data().toArray(); + }; + + Table.prototype.getDatas = function () { + return this.table.rows().data().toArray(); + }; + + $.fn.Table = Table; +})(jQuery); Index: controltower/js/common/tourGuide/tgApi.js =================================================================== diff -u --- controltower/js/common/tourGuide/tgApi.js (revision 0) +++ controltower/js/common/tourGuide/tgApi.js (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,54 @@ +const TourGuideApi = (function () { + + const makeInstance = function (pageName) { + let tg = new tourguide.TourGuideClient({ + exitOnClickOutside: false, + steps: fetchSteps(pageName) + }); + return tg; + } + + const fetchSteps = function (pageName) { + let steps; + console.log("[ tgApi :: TourGuideApi.fetchSteps ] :: pageName → " + pageName); + switch (pageName) { + case 'dashboard': + break; + //Product Service + case 'pdService': + steps = TgGroup.tg_pdService(); + break; + case 'pdServiceVersion': + break; + //Jira + case 'jiraServer': + break; + case 'jiraConnection': + break; + + //Requirement + case 'reqAdd': + break; + case 'reqStatus': + break; + + //Analysis + case 'analysisGantt': + break; + case 'analysisResource': + break; + case 'analysisTime': + break; + default: + console.log("[ tgApi :: TourGuideApi.fetchSteps ] :: pageName → " + pageName + " :: 일치하는 케이스 없음"); + + } //end of switch + if (steps === undefined) { + return TgGroup.sampleStep(pageName); + } + return steps; + }; + + return {fetchSteps : fetchSteps, + makeInstance :makeInstance}; // 내부 함수 key : value ( function ) +})(); \ No newline at end of file Index: controltower/js/common/tourGuide/tgGroup.js =================================================================== diff -u --- controltower/js/common/tourGuide/tgGroup.js (revision 0) +++ controltower/js/common/tourGuide/tgGroup.js (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,119 @@ +var TgGroup = ( function () { + var sampleStep = function (pageName) { + const steps = [ + { + title: '
    선택한 페이지 - '+pageName+'
    ', + content: '
    페이지명과 범주를 확인할 수 있습니다.
    ', + target: ".widgetheader" + }, + { + title: '
    투어가이드 설정 On/Off
    ', + content: '
    페이지가 새로 로드 될 때마다 실행됩니다.
    ' + + '가이드를 끄시려면 TourGuide Off로 설정해주세요.
    ', + target: "#settings" + } + ]; + return steps; + }; + var tg_dashboard = function () { + const steps = [{ + content: "This is a short guide to get you set up and show you where things are", + title: "Welcome aboard", + target: "#firstStep" + }, + { + content: "Register New Product(or Service) that you want to manage", + title: "Register Product(or Service) Button", + target: "#modal_popup_id" + } + ]; + + return steps; + }; + + var tg_pdService = function () { + const steps = [ + { + title: '
    제품서비스 목록
    ', + content: '
    등록한 제품서비스 목록 입니다.
    ' + + '제품서비스 명을 선택하시면 상세 정보를 확인할 수 있습니다.
    ', + target: "#firstSection" + }, + { + title: '
    제품서비스 등록
    ', + content: '
    새로운 제품 또는 서비스를 등록할 수 있습니다.
    ', + target: "#modal_popup_id" + }, + { + title: '
    제품서비스 상세
    ', + content: '
    목록에서 선택한 제품서비스의 상세 정보 확인
    ' + + '편집하고 삭제할 수 있습니다.
    ', + target: "#secondSection" + }, + { + title: '
    투어가이드 설정 On/Off
    ', + content: '
    페이지가 새로 로드 될 때마다 실행됩니다.
    ' + + '가이드를 끄시려면 TourGuideOff로 설정해주세요.
    ', + target: "#settings" + } + ]; + + return steps; + }; + + var tg_pdServiceVersion = function () { + + }; + var tg_jiraConnection = function () { + + }; + var tg_pdServiceJira = function () { + + }; + + var tg_reqAdd = function () { + + }; + + var tg_reqStatus = function () { + + }; + var tg_analysisGantt = function () { + + }; + + + var tg_analysisTime = function () { + + }; + var tg_analysisScope = function () { + + }; + var tg_analysisResource = function () { + + }; + var tg_analysisCost = function () { + + }; + + return { tg_dashboard : tg_dashboard, + + tg_pdService : tg_pdService, + tg_pdServiceVersion : tg_pdServiceVersion, + + tg_jiraConnection : tg_jiraConnection, + tg_pdServiceJira : tg_pdServiceJira, + + tg_reqAdd : tg_reqAdd, + tg_reqStatus : tg_reqStatus, + + tg_analysisGantt : tg_analysisGantt, + tg_analysisTime : tg_analysisTime, + tg_analysisScope : tg_analysisScope, + tg_analysisResource : tg_analysisResource, + tg_analysisCost : tg_analysisCost, + + sampleStep : sampleStep + }; // 내부함수 key : value + } +)(); Index: controltower/js/index.js =================================================================== diff -u --- controltower/js/index.js (revision 0) +++ controltower/js/index.js (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1,1043 @@ +//////////////////////////////////////////////////////////////////////////////////////// +//Page 전역 변수 +//////////////////////////////////////////////////////////////////////////////////////// +var selectId; // 제품 아이디 +var selectName; // 제품 이름 +var selectedIndex; // 데이터테이블 선택한 인덱스 +var selectedPage; // 데이터테이블 선택한 인덱스 +var selectVersion; // 선택한 버전 아이디 +var dataTableRef; // 데이터테이블 참조 변수 + +//////////////////////////////////////////////////////////////////////////////////////// +//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/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"], + + [ "../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"], + + [ "../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/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/pdfmake.min.js", + "../reference/jquery-plugins/dataTables-1.10.16/extensions/Buttons/js/vfs_fonts.js" + ] + // 추가적인 플러그인 그룹들을 이곳에 추가하면 됩니다. + ]; + + loadPluginGroupsParallelAndSequential(pluginGroups) + .then(function() { + + console.log('모든 플러그인 로드 완료'); + + // 사이드 메뉴 색상 설정 + $('.widget').widgster(); + setSideMenu("sidebar_menu_product", "sidebar_menu_product_manage"); + + }) + .catch(function() { + console.error('플러그인 로드 중 오류 발생'); + }); + +} + +//////////////////////////////////////////////////////////////////////////////////////// +// 탭 클릭 이벤트 처리 +//////////////////////////////////////////////////////////////////////////////////////// +function tab_click_event() { + $('a[data-toggle="tab"]').on("shown.bs.tab", function (e) { + var target = $(e.target).attr("href"); // activated tab + console.log(target); + + if (target == "#dropdown1") { + + $("#pdservice_details_popup_div").addClass("hidden"); + $("#pdservice_update_div").addClass("hidden"); + $("#pdservice_delete_div").removeClass("hidden"); + + $(".body-middle").hide(); + $(".pdservice-image-row").hide(); + $(".file-delete-btn").hide(); + if (isEmpty(selectId)) { + jError("선택된 제품(서비스)가 없습니다. 오류는 무시됩니다."); + } else { + $("#delete_text").text($("#pdservice_table").DataTable().rows(".selected").data()[0].c_title); + } + } else if (target == "#report") { + $(".pdservice-image-row").show(); + $(".file-delete-btn").show(); + $("#pdservice_details_popup_div").addClass("hidden"); + $("#pdservice_delete_div").addClass("hidden"); + $("#pdservice_update_div").removeClass("hidden"); + + } else { + $("#pdservice_details_popup_div").removeClass("hidden"); + $("#pdservice_update_div").addClass("hidden"); + $("#pdservice_delete_div").addClass("hidden"); + $(".pdservice-image-row").hide(); + $(".file-delete-btn").hide(); + + if (selectId == undefined) { + $(".body-middle").hide(); + } else { + $(".body-middle").show(); + } + } + }); +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// --- 신규 제품(서비스) 등록 팝업 및 팝업 띄울때 사이즈 조정 -- // +//////////////////////////////////////////////////////////////////////////////////////// +function popup_size_setting(){ + console.log("popup_size_setting() is activated"); + $("#modal_popup_id").click(function () { + console.log("modal_popup_id clicked"); + var height = $(document).height() - 600; + + //모달 초기화 + $("#my_modal2").on("hidden.bs.modal", function (e) { + $(this).find('form')[0].reset(); + $("#popup_editview_pdservice_owner").val(null).trigger("change"); + $("#popup_editview_pdservice_reviewers").val(null).trigger("change"); + CKEDITOR.instances.modal_editor.setData("

    제품(서비스)의 기획서 및 Project Charter 의 내용을 기록합니다.

    "); //에디터 초기화 + }); + + $(".modal-body") + .find(".cke_contents:eq(0)") + .css("height", height + "px"); + }); + + // 팝업하여 편집 + $("#extend_modal_popup_id").click(function () { + var height = $(document).height() - 1000; + $(".modal-body") + .find(".cke_contents:eq(0)") + .css("height", height + "px"); + + // 데이터 셋팅 + var editorData = CKEDITOR.instances.input_pdservice_editor.getData(); + console.log(editorData); + CKEDITOR.instances.extend_modal_editor.setData(editorData); + CKEDITOR.instances.extend_modal_editor.setReadOnly(false); + + var selectedId = $("#pdservice_table").DataTable().rows(".selected").data()[0].c_id; + console.log("selectedId →" + selectedId); + + // 제품(서비스) 이름 + $("#extend_editview_pdservice_name").val($("#editview_pdservice_name").val()); + + // 오너 + // clear + $("#extend_editview_pdservice_owner").val(null).trigger("change"); + + // 부모 페이지에서 데이터 로드 + var owner = "none"; + if ($("#editview_pdservice_owner").select2("data")[0] != undefined) { + owner = $("#editview_pdservice_owner").select2("data")[0].text; + } + + // Modal 창에 데이터 셋팅 + if (owner == null || owner == "none") { + console.log("pdServiceDataTableClick :: json.c_pdservice_owner empty"); + } else { + var newOption = new Option(owner, owner, true, true); + $("#extend_editview_pdservice_owner").append(newOption).trigger("change"); + } + + // 리뷰어 + //clear + $("#extend_editview_pdservice_reviewers").val(null).trigger("change"); + + var reviewer01 = "none"; + var reviewer02 = "none"; + var reviewer03 = "none"; + var reviewer04 = "none"; + var reviewer05 = "none"; + + if ($("#editview_pdservice_reviewers").select2("data")[0] != undefined) { + reviewer01 = $("#editview_pdservice_reviewers").select2("data")[0].text; + } + if ($("#editview_pdservice_reviewers").select2("data")[1] != undefined) { + reviewer02 = $("#editview_pdservice_reviewers").select2("data")[1].text; + } + if ($("#editview_pdservice_reviewers").select2("data")[2] != undefined) { + reviewer03 = $("#editview_pdservice_reviewers").select2("data")[2].text; + } + if ($("#editview_pdservice_reviewers").select2("data")[3] != undefined) { + reviewer04 = $("#editview_pdservice_reviewers").select2("data")[3].text; + } + if ($("#editview_pdservice_reviewers").select2("data")[4] != undefined) { + reviewer05 = $("#editview_pdservice_reviewers").select2("data")[4].text; + } + + var reviewer01Option = new Option(reviewer01, reviewer01, true, true); + var reviewer02Option = new Option(reviewer02, reviewer02, true, true); + var reviewer03Option = new Option(reviewer03, reviewer03, true, true); + var reviewer04Option = new Option(reviewer04, reviewer04, true, true); + var reviewer05Option = new Option(reviewer05, reviewer05, true, true); + + var multifyValue = 1; + if (reviewer01 == null || reviewer01 == "none") { + console.log("extend_modal_popup_id Click :: reviewer01 empty"); + } else { + multifyValue = multifyValue + 1; + $("#extend_editview_pdservice_reviewers").append(reviewer01Option); + } + if (reviewer02 == null || reviewer02 == "none") { + console.log("extend_modal_popup_id Click :: reviewer02 empty"); + } else { + multifyValue = multifyValue + 1; + $("#extend_editview_pdservice_reviewers").append(reviewer02Option); + } + if (reviewer03 == null || reviewer03 == "none") { + console.log("extend_modal_popup_id Click :: reviewer03 empty"); + } else { + multifyValue = multifyValue + 1; + $("#extend_editview_pdservice_reviewers").append(reviewer03Option); + } + if (reviewer04 == null || reviewer04 == "none") { + console.log("extend_modal_popup_id Click :: reviewer04 empty"); + } else { + multifyValue = multifyValue + 1; + $("#extend_editview_pdservice_reviewers").append(reviewer04Option); + } + if (reviewer05 == null || reviewer05 == "none") { + console.log("extend_modal_popup_id Click :: reviewer05 empty"); + } else { + multifyValue = multifyValue + 1; + $("#extend_editview_pdservice_reviewers").append(reviewer05Option); + } + + $("#extend_editview_pdservice_reviewers").trigger("change"); + + $("#extend_editview_pdservice_reviewer").css("height", "20px"); + setTimeout(function () { + var heightValue = $("#extend_editview_pdservice_reviewer").height(); + var resultValue = heightValue + 20 * multifyValue; + $("#extend_editview_pdservice_reviewer").css("height", resultValue + "px"); + }, 250); + }); + // 팝업 - readOnly + $("#extend_modal_readOnly").click(function () { + var height = $(document).height() - 1000; + $(".modal-body") + .find(".cke_contents:eq(0)") + .css("height", height + "px"); + + // 데이터 셋팅 + var editorData = CKEDITOR.instances.input_pdservice_editor.getData(); + CKEDITOR.instances.extend_modal_editor.setData(editorData); + CKEDITOR.instances.extend_modal_editor.setReadOnly(true); // 읽기전용 + + var selectedId = $("#pdservice_table").DataTable().rows(".selected").data()[0].c_id; + console.log("selectedId →" + selectedId); + + // 제품(서비스) 이름 + $("#extend_editview_pdservice_name").val($("#editview_pdservice_name").val()); + + // 오너 + // clear + $("#extend_editview_pdservice_owner").val(null).trigger("change"); + + // 부모 페이지에서 데이터 로드 + var owner = "none"; + if ($("#editview_pdservice_owner").select2("data")[0] != undefined) { + owner = $("#editview_pdservice_owner").select2("data")[0].text; + } + + // Modal 창에 데이터 셋팅 + if (owner == null || owner == "none") { + console.log("pdServiceDataTableClick :: json.c_pdservice_owner empty"); + } else { + var newOption = new Option(owner, owner, true, true); + $("#extend_editview_pdservice_owner").append(newOption).trigger("change"); + } + + // 리뷰어 + //clear + $("#extend_editview_pdservice_reviewers").val(null).trigger("change"); + + var reviewer01 = "none"; + var reviewer02 = "none"; + var reviewer03 = "none"; + var reviewer04 = "none"; + var reviewer05 = "none"; + + if ($("#editview_pdservice_reviewers").select2("data")[0] != undefined) { + reviewer01 = $("#editview_pdservice_reviewers").select2("data")[0].text; + } + if ($("#editview_pdservice_reviewers").select2("data")[1] != undefined) { + reviewer02 = $("#editview_pdservice_reviewers").select2("data")[1].text; + } + if ($("#editview_pdservice_reviewers").select2("data")[2] != undefined) { + reviewer03 = $("#editview_pdservice_reviewers").select2("data")[2].text; + } + if ($("#editview_pdservice_reviewers").select2("data")[3] != undefined) { + reviewer04 = $("#editview_pdservice_reviewers").select2("data")[3].text; + } + if ($("#editview_pdservice_reviewers").select2("data")[4] != undefined) { + reviewer05 = $("#editview_pdservice_reviewers").select2("data")[4].text; + } + + var reviewer01Option = new Option(reviewer01, reviewer01, true, true); + var reviewer02Option = new Option(reviewer02, reviewer02, true, true); + var reviewer03Option = new Option(reviewer03, reviewer03, true, true); + var reviewer04Option = new Option(reviewer04, reviewer04, true, true); + var reviewer05Option = new Option(reviewer05, reviewer05, true, true); + + var multifyValue = 1; + if (reviewer01 == null || reviewer01 == "none") { + console.log("extend_modal_popup_id Click :: reviewer01 empty"); + } else { + multifyValue = multifyValue + 1; + $("#extend_editview_pdservice_reviewers").append(reviewer01Option); + } + if (reviewer02 == null || reviewer02 == "none") { + console.log("extend_modal_popup_id Click :: reviewer02 empty"); + } else { + multifyValue = multifyValue + 1; + $("#extend_editview_pdservice_reviewers").append(reviewer02Option); + } + if (reviewer03 == null || reviewer03 == "none") { + console.log("extend_modal_popup_id Click :: reviewer03 empty"); + } else { + multifyValue = multifyValue + 1; + $("#extend_editview_pdservice_reviewers").append(reviewer03Option); + } + if (reviewer04 == null || reviewer04 == "none") { + console.log("extend_modal_popup_id Click :: reviewer04 empty"); + } else { + multifyValue = multifyValue + 1; + $("#extend_editview_pdservice_reviewers").append(reviewer04Option); + } + if (reviewer05 == null || reviewer05 == "none") { + console.log("extend_modal_popup_id Click :: reviewer05 empty"); + } else { + multifyValue = multifyValue + 1; + $("#extend_editview_pdservice_reviewers").append(reviewer05Option); + } + + $("#extend_editview_pdservice_reviewers").trigger("change"); + + $("#extend_editview_pdservice_reviewer").css("height", "20px"); + setTimeout(function () { + var heightValue = $("#extend_editview_pdservice_reviewer").height(); + var resultValue = heightValue + 20 * multifyValue; + $("#extend_editview_pdservice_reviewer").css("height", resultValue + "px"); + }, 250); + }); +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// --- select2 (사용자 자동완성 검색 ) 설정 --- // +//////////////////////////////////////////////////////////////////////////////////////// +function select2_setting() { + $(".js-data-example-ajax").select2({ + maximumSelectionLength: 5, + width: "resolve", + ajax: { + url: function (params) { + return "/auth-user/search-user/" + params.term; + }, + dataType: "json", + delay: 250, + //data: function (params) { + // return { + // q: params.term, // search term + // page: params.page, + // }; + //}, + processResults: function (data, params) { + // parse the results into the format expected by Select2 + // since we are using custom formatting functions we do not need to + // alter the remote JSON data, except to indicate that infinite + // scrolling can be used + params.page = params.page || 1; + + return { + results: data, + pagination: { + more: params.page * 30 < data.total_count + } + }; + }, + cache: true + }, + placeholder: "리뷰어 설정을 위한 계정명을 입력해 주세요", + minimumInputLength: 1, + templateResult: formatUser, + templateSelection: formatUserSelection + }); +} + +////////////////////////////////////////////////////////////////////¸//////////////////// +// --- select2 (사용자 자동완성 검색 ) templateResult 설정 --- // +//////////////////////////////////////////////////////////////////////////////////////// +function formatUser(jsonData) { + console.log("formatUser"); + console.log(jsonData) + var $container = $( + "
    " + + "
    " + + "
    " + + "
    " + + "
    " + + "
    " + ); + + $container.find(".select2-result-jsonData__username").text(jsonData.username); + $container.find(".select2-result-jsonData__id").text(jsonData.id); + + return $container; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// --- select2 (사용자 자동완성 검색 ) templateSelection 설정 --- // +//////////////////////////////////////////////////////////////////////////////////////// +function formatUserSelection(jsonData) { + console.log("formatUserSelection"); + console.log(jsonData) + if (jsonData.id == "") { + jsonData.text = "placeholder"; + } else { + if (jsonData.username == undefined) { + jsonData.text = jsonData.id; + } else { + jsonData.text = "[" + jsonData.username + "] - " + jsonData.id; + } + } + return jsonData.text; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// --- file upload --- // +//////////////////////////////////////////////////////////////////////////////////////// +function file_upload_setting() { + + // Initialize the jQuery File Upload widget: + var $fileupload = $("#fileupload"); + $fileupload.fileupload({ + // Uncomment the following to send cross-domain cookies: + //xhrFields: {withCredentials: true}, + autoUpload: true, + url: "/auth-user/api/arms/pdService/uploadFileToNode.do", + dropZone: $("#dropzone") + }); + + + $("#fileupload").bind("fileuploadsubmit", function (e, data) { + // The example input, doesn't have to be part of the upload form: + var input = $("#fileIdlink"); + data.formData = { pdservice_link: input.val() }; + if (!data.formData.pdservice_link) { + data.context.find("button").prop("disabled", false); + input.focus(); + return false; + } + }); + +} + +//////////////////////////////////////////////////////////////////////////////////////// +// --- 데이터 테이블 설정 --- // +//////////////////////////////////////////////////////////////////////////////////////// +function dataTableLoad() { + // 데이터 테이블 컬럼 및 열그룹 구성 + var columnList = [ + { name: "c_id", title: "제품(서비스) 아이디", data: "c_id", visible: false }, + { + name: "c_title", + title: "제품(서비스) 이름", + data: "c_title", + render: function (data, type, row, meta) { + if (type === "display") { + return '"; + } + return data; + }, + className: "dt-body-left", + visible: true + } + ]; + var rowsGroupList = []; + var columnDefList = []; + var selectList = {}; + var orderList = [[0, "asc"]]; + var buttonList = [ + "copy", + "excel", + "print", + { + extend: "csv", + text: "Export csv", + charset: "utf-8", + extension: ".csv", + fieldSeparator: ",", + fieldBoundary: "", + bom: true + }, + { + extend: "pdfHtml5", + orientation: "landscape", + pageSize: "LEGAL" + } + ]; + + var jquerySelector = "#pdservice_table"; + var ajaxUrl = "/auth-user/api/arms/pdServicePure/getPdServiceMonitor.do"; + var jsonRoot = "response"; + var isServerSide = false; + + dataTableRef = dataTable_build( + jquerySelector, + ajaxUrl, + jsonRoot, + columnList, + rowsGroupList, + columnDefList, + selectList, + orderList, + buttonList, + isServerSide + ); + + $("#copychecker").on("click", function () { + dataTableRef.button(".buttons-copy").trigger(); + }); + $("#printchecker").on("click", function () { + dataTableRef.button(".buttons-print").trigger(); + }); + $("#csvchecker").on("click", function () { + dataTableRef.button(".buttons-csv").trigger(); + }); + $("#excelchecker").on("click", function () { + dataTableRef.button(".buttons-excel").trigger(); + }); + $("#pdfchecker").on("click", function () { + dataTableRef.button(".buttons-pdf").trigger(); + }); +} + + +// 데이터 테이블 구성 이후 꼭 구현해야 할 메소드 : 열 클릭시 이벤트 +function dataTableClick(tempDataTable, selectedData) { + selectedIndex = selectedData.selectedIndex; + selectedPage = selectedData.selectedPage; + selectId = selectedData.c_id; + $("#fileIdlink").val(selectedData.c_id); + selectName = selectedData.c_title; + pdServiceDataTableClick(selectedData.c_id); + + //제품 클릭 시, 상세보기 tab을 기본값으로 세팅. + $('ul.nav-tabs li').removeClass('active'); + $('.nav-tabs-stats').addClass('active'); + + //파일 업로드 관련 레이어 보이기 처리 + $(".body-middle").show(); + // 이미지 CRUD 관련 HTML 태그 hide 처리. <편집하기> tab 에서만 보여준다. + $(".pdservice-image-row").hide(); + + //파일 리스트 초기화 + $("table tbody.files").empty(); + // Load existing files: + var $fileupload = $("#fileupload"); + + $.ajax({ + // Uncomment the following to send cross-domain cookies: + //xhrFields: {withCredentials: true}, + url: "/auth-user/api/arms/fileRepository/getFilesByNode.do", + data: { fileIdLink: selectId }, + dataType: "json", + context: $fileupload[0] + }).done(function (result) { + $(this).fileupload("option", "done").call(this, null, { result: result }); + $(".file-delete-btn").hide(); // 파일 리스트에서 delete 버튼 display none 처리 -> 편집하기 tab 에서만 보여준다. + }); +} + +//데이터 테이블 ajax load 이후 콜백. +function dataTableCallBack(settings, json) { +} + +function dataTableDrawCallback(tableInfo) { + $("#" + tableInfo.sInstance) + .DataTable() + .columns.adjust() + .responsive.recalc(); +} + +//////////////////////////////////////////////////////////////////////////////////////// +//제품(서비스) 클릭할 때 동작하는 함수 +//1. 상세보기 데이터 바인딩 +//2. 편집하기 데이터 바인딩 +//////////////////////////////////////////////////////////////////////////////////////// +function pdServiceDataTableClick(c_id) { + selectVersion = c_id; + + $.ajax({ + url: "/auth-user/api/arms/pdServicePure/getNode.do", // 클라이언트가 HTTP 요청을 보낼 서버의 URL 주소 + data: { c_id: c_id }, // HTTP 요청과 함께 서버로 보낼 데이터 + method: "GET", // HTTP 요청 메소드(GET, POST 등) + dataType: "json", // 서버에서 보내줄 데이터의 타입 + beforeSend: function () { + $(".loader").removeClass("hide"); + } + }) + // HTTP 요청이 성공하면 요청한 데이터가 done() 메소드로 전달됨. + .done(function (json) { + //$("#detailview_pdservice_name").val(json.c_title); + var selectedHtml = + `
    +
    + + 선택된 제품(서비스) : + + ` + json.c_title + + ` + +
    +
    + `; + + $(".list-group-item").html(selectedHtml); + + $("#detailview_pdservice_name").val(json.c_title); + if (isEmpty(json.c_pdservice_owner) || json.c_pdservice_owner == "none") { + $("#detailview_pdservice_owner").val("책임자가 존재하지 않습니다."); + } else { + $("#detailview_pdservice_owner").val(json.c_pdservice_owner); + } + + if (isEmpty(json.c_pdservice_reviewer01) || json.c_pdservice_reviewer01 == "none") { + $("#detailview_pdservice_reviewer01").val("리뷰어(연대책임자)가 존재하지 않습니다."); + } else { + $("#detailview_pdservice_reviewer01").val(json.c_pdservice_reviewer01); + } + + if (isEmpty(json.c_pdservice_reviewer02) || json.c_pdservice_reviewer02 == "none") { + $("#detailview_pdservice_reviewer02").val("2번째 리뷰어(연대책임자) 없음"); + } else { + $("#detailview_pdservice_reviewer02").val(json.c_pdservice_reviewer02); + } + + if (isEmpty(json.c_pdservice_reviewer03) || json.c_pdservice_reviewer03 == "none") { + $("#detailview_pdservice_reviewer03").val("3번째 리뷰어(연대책임자) 없음"); + } else { + $("#detailview_pdservice_reviewer03").val(json.c_pdservice_reviewer03); + } + + if (isEmpty(json.c_pdservice_reviewer04) || json.c_pdservice_reviewer04 == "none") { + $("#detailview_pdservice_reviewer04").val("4번째 리뷰어(연대책임자) 없음"); + } else { + $("#detailview_pdservice_reviewer04").val(json.c_pdservice_reviewer04); + } + + if (isEmpty(json.c_pdservice_reviewer05) || json.c_pdservice_reviewer05 == "none") { + $("#detailview_pdservice_reviewer05").val("5번째 리뷰어(연대책임자) 없음"); + } else { + $("#detailview_pdservice_reviewer05").val(json.c_pdservice_reviewer05); + } + + CKEDITOR.instances.detailview_pdservice_contents.setData(json.c_pdservice_contents); + + $("#editview_pdservice_name").val(json.c_title); + + //clear + $("#editview_pdservice_owner").val(null).trigger("change"); + + if (json.c_pdservice_owner == null || json.c_pdservice_owner == "none") { + console.log("pdServiceDataTableClick :: json.c_pdservice_owner empty"); + } else { + var newOption = new Option(json.c_pdservice_owner, json.c_pdservice_owner, true, true); + $("#editview_pdservice_owner").append(newOption).trigger("change"); + } + // -------------------- reviewer setting -------------------- // + //reviewer clear + $("#editview_pdservice_reviewers").val(null).trigger("change"); + + var selectedReviewerArr = []; + if (json.c_pdservice_reviewer01 == null || json.c_pdservice_reviewer01 == "none") { + console.log("pdServiceDataTableClick :: json.c_pdservice_reviewer01 empty"); + } else { + selectedReviewerArr.push(json.c_pdservice_reviewer01); + // Set the value, creating a new option if necessary + if ($("#editview_pdservice_reviewers").find("option[value='" + json.c_pdservice_reviewer01 + "']").length) { + console.log('option[value=\'" + json.c_pdservice_reviewer01 + "\']"' + "already exist"); + } else { + // Create a DOM Option and pre-select by default + var newOption01 = new Option(json.c_pdservice_reviewer01, json.c_pdservice_reviewer01, true, true); + // Append it to the select + $("#editview_pdservice_reviewers").append(newOption01).trigger("change"); + } + } + if (json.c_pdservice_reviewer02 == null || json.c_pdservice_reviewer02 == "none") { + console.log("pdServiceDataTableClick :: json.c_pdservice_reviewer02 empty"); + } else { + selectedReviewerArr.push(json.c_pdservice_reviewer02); + // Set the value, creating a new option if necessary + if ($("#editview_pdservice_reviewers").find("option[value='" + json.c_pdservice_reviewer02 + "']").length) { + console.log('option[value=\'" + json.c_pdservice_reviewer02 + "\']"' + "already exist"); + } else { + // Create a DOM Option and pre-select by default + var newOption02 = new Option(json.c_pdservice_reviewer02, json.c_pdservice_reviewer02, true, true); + // Append it to the select + $("#editview_pdservice_reviewers").append(newOption02).trigger("change"); + } + } + if (json.c_pdservice_reviewer03 == null || json.c_pdservice_reviewer03 == "none") { + console.log("pdServiceDataTableClick :: json.c_pdservice_reviewer03 empty"); + } else { + selectedReviewerArr.push(json.c_pdservice_reviewer03); + // Set the value, creating a new option if necessary + if ($("#editview_pdservice_reviewers").find("option[value='" + json.c_pdservice_reviewer03 + "']").length) { + console.log('option[value=\'" + json.c_pdservice_reviewer03 + "\']"' + "already exist"); + } else { + // Create a DOM Option and pre-select by default + var newOption03 = new Option(json.c_pdservice_reviewer03, json.c_pdservice_reviewer03, true, true); + // Append it to the select + $("#editview_pdservice_reviewers").append(newOption03).trigger("change"); + } + } + if (json.c_pdservice_reviewer04 == null || json.c_pdservice_reviewer04 == "none") { + console.log("pdServiceDataTableClick :: json.c_pdservice_reviewer04 empty"); + } else { + selectedReviewerArr.push(json.c_pdservice_reviewer04); + // Set the value, creating a new option if necessary + if ($("#editview_pdservice_reviewers").find("option[value='" + json.c_pdservice_reviewer04 + "']").length) { + console.log('option[value=\'" + json.c_pdservice_reviewer04 + "\']"' + "already exist"); + } else { + // Create a DOM Option and pre-select by default + var newOption04 = new Option(json.c_pdservice_reviewer04, json.c_pdservice_reviewer04, true, true); + // Append it to the select + $("#editview_pdservice_reviewers").append(newOption04).trigger("change"); + } + } + if (json.c_pdservice_reviewer05 == null || json.c_pdservice_reviewer05 == "none") { + console.log("pdServiceDataTableClick :: json.c_pdservice_reviewer05 empty"); + } else { + selectedReviewerArr.push(json.c_pdservice_reviewer05); + // Set the value, creating a new option if necessary + if ($("#editview_pdservice_reviewers").find("option[value='" + json.c_pdservice_reviewer05 + "']").length) { + console.log('option[value=\'" + json.c_pdservice_reviewer05 + "\']"' + "already exist"); + } else { + // Create a DOM Option and pre-select by default + var newOption05 = new Option(json.c_pdservice_reviewer05, json.c_pdservice_reviewer05, true, true); + // Append it to the select + $("#editview_pdservice_reviewers").append(newOption05).trigger("change"); + } + } + $("#editview_pdservice_reviewers").val(selectedReviewerArr).trigger("change"); + + // ------------------------- reviewer end --------------------------------// + + CKEDITOR.instances.input_pdservice_editor.setData(json.c_pdservice_contents); + }) + // HTTP 요청이 실패하면 오류와 상태에 관한 정보가 fail() 메소드로 전달됨. + .fail(function (xhr, status, errorThrown) { + console.log(xhr + status + errorThrown); + }) + // + .always(function (xhr, status) { + console.log(xhr + status); + $(".loader").addClass("hide"); + }); + + $("#delete_text").text($("#pdservice_table").DataTable().rows(".selected").data()[0].c_title); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// 신규 제품(서비스) 등록 버튼 +//////////////////////////////////////////////////////////////////////////////////////// +function save_btn_click() { + $("#regist_pdservice").click(function () { + var reviewers01 = "none"; + var reviewers02 = "none"; + var reviewers03 = "none"; + var reviewers04 = "none"; + var reviewers05 = "none"; + if ($("#popup_editview_pdservice_reviewers").select2("data")[0] != undefined) { + reviewers01 = $("#popup_editview_pdservice_reviewers").select2("data")[0].text; + } + if ($("#popup_editview_pdservice_reviewers").select2("data")[1] != undefined) { + reviewers02 = $("#popup_editview_pdservice_reviewers").select2("data")[1].text; + } + if ($("#popup_editview_pdservice_reviewers").select2("data")[2] != undefined) { + reviewers03 = $("#popup_editview_pdservice_reviewers").select2("data")[2].text; + } + if ($("#popup_editview_pdservice_reviewers").select2("data")[3] != undefined) { + reviewers04 = $("#popup_editview_pdservice_reviewers").select2("data")[3].text; + } + if ($("#popup_editview_pdservice_reviewers").select2("data")[4] != undefined) { + reviewers05 = $("#popup_editview_pdservice_reviewers").select2("data")[4].text; + } + + const cTitle = $("#popup_editview_pdservice_name").val(); + + $.ajax({ + url: "/auth-user/api/arms/pdService/addPdServiceNode.do", + type: "POST", + data: { + ref: 2, + c_title: cTitle, + c_type: "default", + c_pdservice_owner: $("#popup_editview_pdservice_owner").select2("data")[0].text, + c_pdservice_reviewer01: reviewers01, + c_pdservice_reviewer02: reviewers02, + c_pdservice_reviewer03: reviewers03, + c_pdservice_reviewer04: reviewers04, + c_pdservice_reviewer05: reviewers05, + c_pdservice_contents: CKEDITOR.instances.modal_editor.getData() + }, + statusCode: { + 200: function () { + //모달 팝업 끝내고 + $("#close_pdservice").trigger("click"); + //데이터 테이블 데이터 재 로드 + reloadDataWithSameOrdering(cTitle); + jSuccess("신규 제품 등록이 완료 되었습니다."); + } + }, + beforeSend: function () { + $("#regist_pdservice").hide(); + }, + complete: function () { + $("#regist_pdservice").show(); + }, + error: function (e) { + jError("신규 제품 등록 중 에러가 발생했습니다."); + } + }); + }); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// 신규 제품(서비스) 삭제 버튼 +//////////////////////////////////////////////////////////////////////////////////////// +function delete_btn_click(){ + $("#delete_pdservice").click(function () { + $.ajax({ + url: "/auth-user/api/arms/pdService/removeNode.do", + type: "delete", + data: { + c_id: $("#pdservice_table").DataTable().rows(".selected").data()[0].c_id + }, + statusCode: { + 200: function () { + jError($("#editview_pdservice_name").val() + "데이터가 삭제되었습니다."); + //데이터 테이블 데이터 재 로드 + reloadDataWithSameOrdering(""); + } + } + }); + }); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// 제품(서비스) 변경 저장 버튼 +//////////////////////////////////////////////////////////////////////////////////////// +function update_btn_click() { + $("#pdservice_update").click(function () { + var owner = "none"; + if ($("#editview_pdservice_owner").select2("data")[0] != undefined) { + owner = $("#editview_pdservice_owner").select2("data")[0].text; + } + const cId = $("#pdservice_table").DataTable().rows(".selected").data()[0].c_id; + const cTitle = $("#pdservice_table").DataTable().rows(".selected").data()[0].c_title; + var reviewers01 = "none"; + var reviewers02 = "none"; + var reviewers03 = "none"; + var reviewers04 = "none"; + var reviewers05 = "none"; + if ($("#editview_pdservice_reviewers").select2("data")[0] != undefined) { + reviewers01 = $("#editview_pdservice_reviewers").select2("data")[0].text; + } + if ($("#editview_pdservice_reviewers").select2("data")[1] != undefined) { + reviewers02 = $("#editview_pdservice_reviewers").select2("data")[1].text; + } + if ($("#editview_pdservice_reviewers").select2("data")[2] != undefined) { + reviewers03 = $("#editview_pdservice_reviewers").select2("data")[2].text; + } + if ($("#editview_pdservice_reviewers").select2("data")[3] != undefined) { + reviewers04 = $("#editview_pdservice_reviewers").select2("data")[3].text; + } + if ($("#editview_pdservice_reviewers").select2("data")[4] != undefined) { + reviewers05 = $("#editview_pdservice_reviewers").select2("data")[4].text; + } + + $.ajax({ + url: "/auth-user/api/arms/pdService/updateNode.do", + type: "put", + data: { + c_id: cId, + c_title: cTitle, + c_pdservice_owner: owner, + c_pdservice_reviewer01: reviewers01, + c_pdservice_reviewer02: reviewers02, + c_pdservice_reviewer03: reviewers03, + c_pdservice_reviewer04: reviewers04, + c_pdservice_reviewer05: reviewers05, + c_pdservice_contents: CKEDITOR.instances.input_pdservice_editor.getData() + }, + statusCode: { + 200: function () { + jSuccess($("#editview_pdservice_name").val() + "의 데이터가 변경되었습니다."); + + //데이터 테이블 데이터 재 로드 + reloadDataWithSameOrdering(cTitle); + } + } + }); + }); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// 팝업에서 제품(서비스) 변경 저장 버튼 +//////////////////////////////////////////////////////////////////////////////////////// +function popup_update_btn_click() { + $("#extendupdate_pdservice").click(function () { + var owner = "none"; + if ($("#extend_editview_pdservice_owner").select2("data")[0] != undefined) { + owner = $("#extend_editview_pdservice_owner").select2("data")[0].text; + } + + var reviewers01 = "none"; + var reviewers02 = "none"; + var reviewers03 = "none"; + var reviewers04 = "none"; + var reviewers05 = "none"; + if ($("#extend_editview_pdservice_reviewers").select2("data")[0] != undefined) { + reviewers01 = $("#extend_editview_pdservice_reviewers").select2("data")[0].text; + } + if ($("#extend_editview_pdservice_reviewers").select2("data")[1] != undefined) { + reviewers02 = $("#extend_editview_pdservice_reviewers").select2("data")[1].text; + } + if ($("#extend_editview_pdservice_reviewers").select2("data")[2] != undefined) { + reviewers03 = $("#extend_editview_pdservice_reviewers").select2("data")[2].text; + } + if ($("#extend_editview_pdservice_reviewers").select2("data")[3] != undefined) { + reviewers04 = $("#extend_editview_pdservice_reviewers").select2("data")[3].text; + } + if ($("#extend_editview_pdservice_reviewers").select2("data")[4] != undefined) { + reviewers05 = $("#extend_editview_pdservice_reviewers").select2("data")[4].text; + } + + $.ajax({ + url: "/auth-user/api/arms/pdService/updateNode.do", + type: "put", + data: { + c_id: $("#pdservice_table").DataTable().rows(".selected").data()[0].c_id, + c_title: $("#extend_editview_pdservice_name").val(), + c_pdservice_owner: owner, + c_pdservice_reviewer01: reviewers01, + c_pdservice_reviewer02: reviewers02, + c_pdservice_reviewer03: reviewers03, + c_pdservice_reviewer04: reviewers04, + c_pdservice_reviewer05: reviewers05, + c_pdservice_contents: CKEDITOR.instances.extend_modal_editor.getData() + }, + statusCode: { + 200: function () { + //모달 팝업 끝내고 + $("#extendclose_pdservice").trigger("click"); + + jSuccess($("#extend_editview_pdservice_name").val() + "의 데이터가 변경되었습니다."); + + $("#fileIdlink").val(selectId); + pdServiceDataTableClick(selectId); + + //파일 업로드 관련 레이어 보이기 처리 + $(".body-middle").show(); + + //파일 리스트 초기화 + $("table tbody.files").empty(); + // Load existing files: + var $fileupload = $("#fileupload"); + // Load existing files: + $.ajax({ + // Uncomment the following to send cross-domain cookies: + //xhrFields: {withCredentials: true}, + url: "/auth-user/api/arms/fileRepository/getFilesByNode.do", + data: { fileIdlink: selectId }, + dataType: "json", + context: $fileupload[0] + }).done(function (result) { + $(this).fileupload("option", "done").call(this, null, { result: result }); + }); + } + } + }); + }); +} + +/////////////////////////////// +// 팝업 띄울 때, UI 일부 수정되도록 +//////////////////////////////// +function modalPopup(popupName) { + console.log("popupName= " + popupName); + if (popupName === "modal_popup_readonly") { + //modal_popup_readOnly = 새 창으로 제품(서비스 보기) + $("#my_modal1_title").text("제품(서비스) 내용 보기 팝업"); + $("#my_modal1_sub").text("새 창으로 제품(서비스)의 정보를 확인합니다.") + $("#extendupdate_pdservice").addClass("hidden"); + + + } else { //팝업 창으로 편집하기 + + $("#my_modal1_title").text("신규 제품(서비스) 수정 팝업"); + $("#my_modal1_sub").text("A-RMS에 신규 제품(서비스)의 정보를 수정합니다.") + $("#extendupdate_pdservice").removeClass("hidden"); + + + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// 최초 dataTable_build 시 정렬 기준을 dataTableRef.ajax.reload 때마다 가져와서 세팅한다. +// 일관 된 정렬을 보장하기 위한 함수이다. +//////////////////////////////////////////////////////////////////////////////////////// +function reloadDataWithSameOrdering(cTitle) { + const currentOrder = dataTableRef.order(); + dataTableRef.ajax.reload(function() { + dataTableRef.order(currentOrder).draw(); + if(cTitle === "") return false; + $("#pdservice_table tbody tr").each(function() { + const rowTitle = $(this).find("td label").text(); + if (rowTitle === cTitle) { + $(this).click(); + return false; + } + }); + }); +} Index: controltower/nv.d3.min.js.map =================================================================== diff -u --- controltower/nv.d3.min.js.map (revision 0) +++ controltower/nv.d3.min.js.map (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1 @@ +{} \ No newline at end of file Index: controltower/pdfmake.min.js.map =================================================================== diff -u --- controltower/pdfmake.min.js.map (revision 0) +++ controltower/pdfmake.min.js.map (revision b4e0eb3622174702570e139565b080d84999f5a5) @@ -0,0 +1 @@ +{} \ No newline at end of file