OWL ITS + 탐지시스템(인터넷 진흥원)
- 연관 이슈 추가 안되는 오류 수정
- 연관 이슈 추가 후 목록 안뜨는 문제 수정
- 이슈 목록 트리 구조 보기 기능 추가
1개 파일 추가됨
12개 파일 변경됨
468 ■■■■ 파일 변경됨
src/main/java/kr/wisestone/owl/service/IssueService.java 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java 51 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/resources/migration/V1_13__Alter_Table.sql 21 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/resources/migration/V1_14__Alter_Table.sql 16 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/assets/styles/main.css 13 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/custom_components/js-tree/js-tree.html 34 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/custom_components/js-tree/tree.provider.js 75 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/custom_components/js-tree/treeColumnGenerator.directive.js 85 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/issue/issueAddRelation.controller.js 6 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/issue/issueDetail.controller.js 5 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/issue/issueList.controller.js 135 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/common/header.html 21 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/issue/issueListNormal.html 4 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/IssueService.java
@@ -100,5 +100,5 @@
    void findApiIssue(ApiMonitorCondition apiMonitorCondition, Map<String, Object> resJsonData);
    void setCountDownIssues(List<Map<String, Object>> results, List<IssueVo> issueVos);
    void setCountDownIssues(List<IssueVo> issueVos);
}
src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
@@ -1,7 +1,6 @@
package kr.wisestone.owl.service.impl;
import com.google.common.collect.Lists;
import com.sun.org.apache.bcel.internal.generic.NEW;
import kr.wisestone.owl.common.ExcelConditionCheck;
import kr.wisestone.owl.common.IssueCustomFieldValueFormComparator;
import kr.wisestone.owl.config.CommonConfiguration;
@@ -781,11 +780,11 @@
        //  Map 에 있는 데이터를 IssueVo 데이터로 변환한다.
        this.setMapToIssueVo(results, issueVos, issueCondition, user);
//        if (issueCondition.getTree()) {
            this.setDownIssues(issueVos);
        if (issueCondition.getTree()) {
            this.setDownIssues(user, issueVos);
            this.setRelationIssues(issueVos);
//        }
        this.setCountDownIssues(results, issueVos);
        }
        this.setCountDownIssues(issueVos);
        this.SetWorkflowDepartment(issueVos); //워크플로우에 설정한 담당부서 가져오기
@@ -799,13 +798,35 @@
    }
    // 하위 이슈 세팅
    private void setDownIssues(List<IssueVo> issueVos) {
    // 하위 이슈 세팅(재귀)
    private void setDownIssues(User user, List<IssueVo> issueVos) {
        for(IssueVo issueVo : issueVos) {
            List<Issue> downIssues = this.issueRepository.findByParentIssueId(issueVo.getId());
            List<IssueVo> downIssueVos = Lists.newArrayList();
            IssueCondition issueCondition = new IssueCondition();
            issueCondition.addIssueIds(String.valueOf(issueVo.getId()));
            for(Issue downIssue : downIssues){
                issueVo.addIssueDownVo(ConvertUtil.copyProperties(downIssue, IssueVo.class));
                IssueVo addIssueVo = ConvertUtil.copyProperties(downIssue, IssueVo.class);
                addIssueVo.setIssueTypeId(downIssue.getIssueType().getId());
                downIssueVos.add(addIssueVo);
            }
            issueVo.setIssueDownVos(downIssueVos);
            if (downIssueVos.size() > 0) {
                this.setDownIssues(user, downIssueVos);
            }
            //  이슈 사용자 정보 추가
            //this.setIssueUserList(issueVos, issueCondition);
            this.setIssueDepartmentList(issueVos, issueCondition, user);
            //  등록자 정보 추가
            this.setRegister(issueVos);  //  담당자 정보 셋팅
            //  사용자 정의 필드 정보 추가
            this.setIssueCustomFieldValue(issueVos, issueCondition);
            this.SetWorkflowDepartment(issueVos); //워크플로우에 설정한 담당부서 가져오기
        }
    }
@@ -821,9 +842,9 @@
    @Override
    @Transactional(readOnly = true)
    public void setCountDownIssues(List<Map<String, Object>> results, List<IssueVo> issueVos) {
        for (Map<String, Object> result : results){
            List<Issue> downIssues = this.issueRepository.findByParentIssueId((Long) result.get("id")); //하위이슈 가져오기
    public void setCountDownIssues(List<IssueVo> issueVos) {
        for (IssueVo issueVo : issueVos){
            List<Issue> downIssues = this.issueRepository.findByParentIssueId(issueVo.getId()); //하위이슈 가져오기
            if(downIssues != null && downIssues.size() > 0){ //상위이슈 가지고 있는 애들이 있으면
                int downIssueAllCount = 0;// 하위이슈 전체 카운트
                int downIssueCount = 0;// 하위이슈 미완료 카운트
@@ -842,12 +863,8 @@
                        downIssueCount ++;
                    }
                    for(IssueVo issueVo : issueVos){
                        if(issueVo.getId().equals(parentIssueVo.getId())){
                            issueVo.setDownIssueCount(downIssueCount);
                            issueVo.setDownIssueAllCount(parentIssueVo.getDownIssueAllCount());
                        }
                    }
                    issueVo.setDownIssueCount(downIssueCount);
                    issueVo.setDownIssueAllCount(parentIssueVo.getDownIssueAllCount());
                }
            }
        }
src/main/resources/migration/V1_13__Alter_Table.sql
@@ -15,24 +15,3 @@
-- 업체의 url 컬럼 INDEX 추가
ALTER TABLE `company_field` ADD INDEX `urlIndex`(`url`);
ALTER TABLE `company_field` ADD COLUMN `isp_id` bigint(20) DEFAULT NULL;
ALTER TABLE `company_field` ADD COLUMN `hosting_id` bigint(20) DEFAULT NULL;
ALTER TABLE `company_field` ADD INDEX `ispIdIndex`(`isp_id`);
ALTER TABLE `company_field` ADD INDEX `hostingIdIndex`(`hosting_id`);
CREATE TABLE `email_template`(
    `id` BIGINT(11) AUTO_INCREMENT,
    `title` VARCHAR (255) NOT NULL,
    `template` mediumtext NOT NULL,
    `register_id` BIGINT(20) NOT NULL,
    `register_date` TIMESTAMP NULL,
    `modify_id` BIGINT(20) NOT NULL,
    `modify_date` TIMESTAMP NULL,
    PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
src/main/resources/migration/V1_14__Alter_Table.sql
New file
@@ -0,0 +1,16 @@
ALTER TABLE `company_field` ADD COLUMN `isp_id` bigint(20) DEFAULT NULL;
ALTER TABLE `company_field` ADD COLUMN `hosting_id` bigint(20) DEFAULT NULL;
ALTER TABLE `company_field` ADD INDEX `ispIdIndex`(`isp_id`);
ALTER TABLE `company_field` ADD INDEX `hostingIdIndex`(`hosting_id`);
CREATE TABLE `email_template`(
     `id` BIGINT(11) AUTO_INCREMENT,
     `title` VARCHAR (255) NOT NULL,
     `template` mediumtext NOT NULL,
     `register_id` BIGINT(20) NOT NULL,
     `register_date` TIMESTAMP NULL,
     `modify_id` BIGINT(20) NOT NULL,
     `modify_date` TIMESTAMP NULL,
     PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
src/main/webapp/assets/styles/main.css
@@ -30493,4 +30493,15 @@
    margin: 0 auto;
}
/* 간트차트 end */
/* 이슈 트리 */
/**
 * Framework starts from here ...
 * ------------------------------
 */
.tree,
.tree ul {
    list-style:none;
}
src/main/webapp/custom_components/js-tree/js-tree.html
@@ -1,16 +1,18 @@
<ul>
    <li ng-repeat="row in fn.getResponseData()">
        <span>{{row.title}}</span>
        <ul>
            <li ng-repeat="downRow in row.issueDownVos">
                <span>{{downRow.title}}</span>
            </li>
        </ul>
    </li>
    <li ng-if="fn.getResponseData().length == 0">
        <span translate="common.noData">데이터가 없습니다.</span>
    </li>
</ul>
<div>
    <ul class="ml-1 pl-1 tree">
        <li ng-repeat="row in fn.getResponseData()">
            <ul class="">
                <li>
                    <div class="input-group">
                        <div tree-column-generator="row" class="d-block p-2 mt-2 bg-success text-white" >
                        </div>
                        <span class="badge badge-primary mt-3 ml-2 mb-1 cursor" ng-repeat="relIssue in row.issueRelationIssueVos" ng-click="event.changeDetailView(relIssue.id)">{{relIssue.title}}</span>
                    </div>
                    <ul class="" ng-if="row.issueDownVos != null && row.issueDownVos.length > 0" ng-repeat="issueDownVo in row.issueDownVos">
                        <li><div tree-column-generator="issueDownVo" class="d-block p-2 bg-info text-white"></div></li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</div>
src/main/webapp/custom_components/js-tree/tree.provider.js
@@ -9,50 +9,23 @@
                        config : function () {
                            var tableConfig = {
                                hName : "",    //    헤더 이름
                                hWidth : "",    //    칼럼 길이
                                hChecked : false,    //    체크 박스 선택 여부
                                hAlign : "text-center",    //    헤더 정렬 기준
                                hSort : true,    //    정렬 가능 여부
                                dName : "",    //    데이터 이름
                                dAlign : "text-left",    //    데이터 정렬 기준
                                dRenderer : "",    //    렌더러 여부
                                dVisible : "",  //      bootstrap 반응형 컬럼 표시 여부
                                dType : "none",        // 태그 타입
                                dDateFormat : "",   //  날짜 형식
                                rowSpan : 0,    //  rowspan 을 지원한다.
                                colSpan : 0,    //  colspan 을 지원한다.
                                subHead : false,    //  만약 rowspan, colspan 을 사용하게 되면 true 로 셋팅.
                                columnHint : "",    //  컬럼 정보를 추출하기 위한 힌트 정보를 준다 - tableColumnGenerator 의 사용자 정의 필드 부분에서 사용
                                setHName : function (hName) {
                                    this.hName = hName;
                                    return this;
                                },
                                setHWidth : function (hWidth) {
                                    this.hWidth = hWidth;
                                    return this;
                                },
                                setHChecked : function (hChecked) {
                                    this.hChecked = hChecked;
                                    return this;
                                },
                                setHAlign : function (hAlign) {
                                    this.hAlign = hAlign;
                                    return this;
                                },
                                setHSort : function (hSort) {
                                    this.hSort = hSort;
                                    return this;
                                },
                                setDName : function (dName) {
                                    this.dName = dName;
                                    return this;
                                },
                                setDAlign : function (dAlign) {
                                    this.dAlign = dAlign;
                                    return this;
                                },
                                setDRenderer : function (dRenderer) {
                                    this.dRenderer = dRenderer;
                                    return this;
                                },
                                setDVisible : function (dVisible) {
@@ -67,14 +40,6 @@
                                    this.dDateFormat = dDateFormat;
                                    return this;
                                },
                                setRowSpan : function (dRowSpan) {
                                    this.rowSpan = dRowSpan;
                                    return this;
                                },
                                setColSpan : function (dColSpan) {
                                    this.colSpan = dColSpan;
                                    return this;
                                },
                                setSubHead : function (dSubHead) {
                                    this.subHead = dSubHead;
                                    return this;
@@ -86,46 +51,6 @@
                            };
                            return tableConfig;
                        },
                        toggleChecked : function (checkStatus, datas) {
                            //  전체 선택 체크 박스를 클릭했을 경우
                            angular.forEach(datas, function (data) {
                                if (angular.isDefined(data.defaultYn)) {
                                    if (!data.defaultYn) {
                                        data.checked = checkStatus;
                                    }
                                }
                                else {
                                    data.checked = checkStatus;
                                }
                            });
                        },
                        radioChecked : function (target, datas) {
                            //  해당 row 가 라디오 버튼일 경우
                            angular.forEach(datas, function (data) {
                                if (target.id == data.id) {
                                    data.checked = true;
                                }
                                else {
                                    data.checked = false;
                                }
                            });
                        },
                        rowChecked : function (tableConfig, target, datas) {
                            //  각 row 의 체크박스/라디오 버튼을 클릭했을 경우
                            if (tableConfig[0].dType == "checkbox") {
                                target.checked = !target.checked;
                                for (var data in datas) {
                                    if (!data.checked) {
                                        this.hChecked = false;
                                        break;
                                    }
                                }
                            }
                            else if (tableConfig[0].dType == "radio") {
                                this.radioChecked(target, datas);
                            }
                        },
                        orderByColumn : "",  // table order By column name
                        reverse : true,
src/main/webapp/custom_components/js-tree/treeColumnGenerator.directive.js
@@ -11,51 +11,76 @@
                        return function (scope, element, attrs) {
                            scope.data = scope[attrs["treeColumnGenerator"]];
                            var myData = scope.data;
                            var makeTag = "";
                            var treeStartToken = "└";
                            scope.tableConfigs.forEach(function (tableConfig, index) {
                                var txt = "";
                                makeTag = '<span class="' + tableConfig.dVisible + '">';
                                if (tableConfig.colSpan > 0) {
                                    return;
                                }
                                makeTag = '<li class="' + tableConfig.dAlign + ' ' + tableConfig.dVisible + '">';
                                if (tableConfig.dType === "checkbox") {
                                    //  체크 박스일때
                                    if (scope.data.defaultYn) {
                                        makeTag += '<input type="checkbox" ng-checked="data.checked == true ? true : false" disabled ng-click="$root.$tableProvider.rowChecked(tableConfigs, data, fn.getResponseData())">';
                                var viewData = myData[tableConfig.dName];
                                if (tableConfig.dType === "CUSTOM_FIELD") {
                                    var issueCustomFieldValueVos = myData.issueCustomFieldValueVos;
                                    if (issueCustomFieldValueVos != null) {
                                        for (let i = 0; i < issueCustomFieldValueVos.length; i++) {
                                            if (issueCustomFieldValueVos[i].customFieldVo.id === tableConfig.dName) {
                                                if (index > 0) { makeTag += ","; }
                                                txt += issueCustomFieldValueVos[i].useValue;
                                                break;
                                            }
                                        }
                                    }
                                    else {
                                        makeTag += '<input type="checkbox" ng-checked="data.checked == true ? true : false" ng-click="$root.$tableProvider.rowChecked(tableConfigs, data, fn.getResponseData())">';
                                    }
                                    makeTag += "<span  class='cursor issue-tree-item' translate='" + txt + "'></span>";
                                    tableConfig.hChecked = false;
                                }
                                else if (tableConfig.dType === "radio") {
                                    //  라디오 버튼일때
                                    makeTag += '<input type="radio" ng-checked="data.checked == true ? true : false" ng-click="$root.$tableProvider.rowChecked(tableConfigs, data, fn.getResponseData())">';
                                }
                                else if (tableConfig.dType === "date") {
                                    makeTag += $filter('date')(scope.data[tableConfig.dName], $tableProvider.getDateFormat(tableConfig.dDateFormat, scope.data[tableConfig.dName]));
                                }
                                else {
                                    if (angular.isDefined(scope.data[tableConfig.dName]) && scope.data[tableConfig.dName] != null) {
                                        makeTag += '<span>' + scope.data[tableConfig.dName] + '</span>';
                                } else {
                                    if (tableConfig.dName === "assigneeTeam") {
                                        var departmentVos = myData.departmentVos;
                                        if (departmentVos != null) {
                                            if (index > 0) { makeTag += ","; }
                                            for (let i = 0; i < departmentVos.length; i++) {
                                                if (i > 0) {
                                                    txt += ",";
                                                }
                                                txt += departmentVos[i].departmentName;
                                            }
                                        }
                                        makeTag += "<span  class='cursor issue-tree-item' translate='" + txt + "'></span>";
                                    } else if (tableConfig.dName === "register") {
                                        if (index > 0) { makeTag += ","; }
                                        makeTag += "<span  class='cursor issue-tree-item' translate='" + myData.registerVo.name + "'></span>";
                                    }
                                    else {
                                        makeTag += '<span></span>';
                                    else if (tableConfig.dName === "period") {
                                        if (index > 0) { makeTag += ","; }
                                        if (!$rootScope.isDefined(myData.startDate) && !$rootScope.isDefined(myData.completeDate)) {
                                            makeTag += "<span translate='common.noDate'>기간 없음</span>";
                                        }
                                        else {
                                            makeTag += '<span class="cursor" ng-click="event.changeDetailView(data.id)">'  + myData.startDate + ' ~ ' + myData.completeDate + '</span>';
                                        }
                                    }
                                    else if (tableConfig.dName === "countDownIssue") {
                                        if (index > 0) { makeTag += ","; }
                                        makeTag += makeTag += "<span  class='cursor issue-tree-item' translate='(" + myData.downIssueCount + "/" + myData.downIssueAllCount + ")'></span>";
                                    } else {
                                        viewData = viewData != null ? viewData : "";
                                        if (viewData !== "") {
                                            if (index > 0) { makeTag += ","; }
                                            makeTag += "<span ng-click=\"event.changeDetailView(data.id)\" class='cursor issue-tree-item' translate='" + viewData + "'></span>";
                                        } else {
                                            // makeTag += "<span>" + tableConfig.dName + " NOT FOUND</span> "; // 디버깅시 사용
                                            makeTag += "<span></span> ";
                                        }
                                    }
                                }
                                makeTag += '</li>';
                                makeTag += '</span>';
                                var linkFn = $compile(makeTag);
                                var content = linkFn(scope);
                                element.append(content);
                            });
                        }
                    }
src/main/webapp/scripts/app/issue/issueAddRelation.controller.js
@@ -656,7 +656,6 @@
                                id : parameter.id
                            });
                            $rootScope.$broadcast("getIssueList");
                        }
                        else {
                            SweetAlert.error($filter("translate")("issue.failedIssueModify"), result.data.message.message); // 이슈 수정 실패
@@ -688,7 +687,10 @@
                        $resourceProvider.getPageContent(0, 10))).then(function (result) {
                        if (result.data.message.status === "success") {
                            $scope.fn.getIssueDetail();
                            //  이슈 상세 화면 요청
                            $rootScope.$broadcast("getIssueDetail", {
                                id : parameter.id
                            });
                        }
                        else {
                            SweetAlert.error($filter("translate")("issue.failedToIssueAddIssueRelation"), result.data.message.message); // "연관일감 생성 실패"
src/main/webapp/scripts/app/issue/issueDetail.controller.js
@@ -497,7 +497,10 @@
                // 연관 이슈 테이블 설정
                function setRelTableConfigs(issueTableConfigVo) {
                    if (issueTableConfigVo == null) makeRelTableConfigs(); return;
                    if (issueTableConfigVo == null) {
                        makeRelTableConfigs();
                        return;
                    }
                    var issueTableConfigs = issueTableConfigVo.issueTableConfigs;
                    //  연관 슈 목록 테이블 설정 값을 가져와서 적용한다.
src/main/webapp/scripts/app/issue/issueList.controller.js
@@ -41,7 +41,8 @@
                    getIssueTableConfigs : getIssueTableConfigs,  //  사용자 이슈 목록 테이블 설정 값을 가져와서 적용한다.
                    startExecute : startExecute, //  컨트롤 로딩시 처음으로 시작되는 함수
                    getResponseData : getResponseData, //  컨트롤 로딩시 처음으로 시작되는 함수
                    onClickListMode : onClickListMode   // 리스트 모드 변경시 실행되는 함수
                    onClickListMode : onClickListMode,   // 리스트 모드 변경시 실행되는 함수
                    setDefaultTableConfig : setDefaultTableConfig // 기본 테이블 설정 세팅
                };
                //  변수
@@ -87,6 +88,7 @@
                    registers : [], //  등록자
                    customFields : [],  //  사용자 정의 필드
                    issueTableConfigs : [],  //  이슈 테이블 설정
                    issueTreeConfigs : [],  //  이슈 테이블 설정
                    parentIssueId : "",
                    hideIssue : false,
                    listMode : 0, // 목록 모드 0:기본 리스트 1:트리구조 리스트
@@ -201,6 +203,7 @@
                //  이슈 테이블 설정
                function makeTableConfigs() {
                    $scope.vm.tableConfigs = [];
                    $scope.vm.treeConfigs = [];
                    $scope.vm.tableConfigs.push($tableProvider.config()
                        .setDType("checkbox")
@@ -244,81 +247,44 @@
                //  트리 컬럼을 만들어준다.
                function setTreeColumn(issueTableConfig) {
                    //  일반 컬럼
                    switch(issueTableConfig.key) {
                        case "ISSUE_TITLE" :   //  이슈 제목
                            $scope.vm.treeConfigs.push($treeProvider.config()
                                .setHName("issue.issueTitle")
                                .setDType("renderer")
                                .setHWidth("bold " + issueTableConfig.width)
                                .setDAlign("text-center")
                                .setDRenderer("ISSUE_TITLE"));
                                .setDName("title"));
                            break;
                        case "PRIORITY" :   //  우선순위
                            $scope.vm.treeConfigs.push($treeProvider.config()
                                .setHName("common.priority")
                                .setDName("priorityName")
                                .setDType("renderer")
                                .setHWidth("bold " + issueTableConfig.width)
                                .setDAlign("text-center")
                                .setDRenderer("COMMON_PRIORITY"));
                                .setDName("priorityName"));
                            break;
                        case "SEVERITY" :   //  중요도
                            $scope.vm.treeConfigs.push($treeProvider.config()
                                .setHName("common.importance")
                                .setDName("severityName")
                                .setDType("renderer")
                                .setHWidth("bold " + issueTableConfig.width)
                                .setDAlign("text-center")
                                .setDRenderer("COMMON_SEVERITY"));
                                .setDName("severityName"));
                            break;
                        case "ISSUE_TYPE" : //  이슈 타입
                            $scope.vm.treeConfigs.push($treeProvider.config()
                                .setHName("issue.issueType")
                                .setHWidth("bold " + issueTableConfig.width)
                                .setDAlign("text-center")
                                .setDName("issueTypeName"));
                            break;
                        case "ASSIGNEE_TEAM" :   //  담당부서
                            $scope.vm.treeConfigs.push($treeProvider.config()
                                .setHName("common.assigneeTeam")
                                .setDType("renderer")
                                .setHWidth("bold " + issueTableConfig.width)
                                .setDAlign("text-center")
                                .setDRenderer("ISSUE_DEPARTMENT"));
                                .setDName("assigneeTeam"));
                            break;
                        case "REGISTER" :   //  등록자
                            $scope.vm.treeConfigs.push($treeProvider.config()
                                .setHName("common.register")
                                .setDType("renderer")
                                .setHWidth("bold " + issueTableConfig.width)
                                .setDAlign("text-center")
                                .setDRenderer("REGISTER"));
                                .setDName("register"));
                            break;
                        case "PERIOD" : //  기간
                            $scope.vm.treeConfigs.push($treeProvider.config()
                                .setHName("common.period")
                                .setDType("renderer")
                                .setHWidth("bold " + issueTableConfig.width)
                                .setDAlign("text-center")
                                .setDRenderer("ISSUE_DUE_DATE"));
                                .setDName("period"));
                            break;
                        case "MODIFY_DATE" : //  최근 변경일
                            $scope.vm.treeConfigs.push($treeProvider.config()
                                .setHName("common.lastChangeDate")
                                .setHWidth("bold " + issueTableConfig.width)
                                .setDAlign("text-center")
                                .setDName("modifyDate"));
                            break;
                        case "COUNT_DOWN_ISSUE" : //  하위 이슈 개수
                            $scope.vm.treeConfigs.push($treeProvider.config()
                                .setHName("common.countDownIssue")
                                .setDType("renderer")
                                .setHWidth("bold " + issueTableConfig.width)
                                .setDAlign("text-center")
                                .setDRenderer("DOWN_ISSUE_COUNT"));
                                .setDName("countDownIssue"));
                            break;
                    }
@@ -330,12 +296,9 @@
                            if (customField.id === Number(issueTableConfig.key.substring(13))) {
                                $scope.vm.treeConfigs.push($treeProvider.config()
                                    .setHName(customField.name)
                                    .setDType("renderer")
                                    .setHWidth("bold " + issueTableConfig.width)
                                    .setDAlign("text-center")
                                    .setColumnHint(customField)
                                    .setDRenderer("ISSUE_CUSTOM_FIELD_VALUE_VIEW"));
                                    .setDType("CUSTOM_FIELD")
                                    .setDName(customField.id)
                                    .setColumnHint(customField));
                                break;
                            }
                        }
@@ -599,6 +562,7 @@
                //  이슈 목록을 조회한다.
                function getPageList(selectedPage, detail = false) {
                    $rootScope.spinner = true;  //  프로그래스 바
                    if (selectedPage < 0) {
                        selectedPage = 0;
                    }
@@ -666,6 +630,7 @@
                        else {
                            SweetAlert.error($filter("translate")("issue.failedIssueLookup"), result.data.message.message); // 이슈 조회 실패
                        }
                        $rootScope.spinner = false;  //  프로그래스 바
                    });
                }
@@ -1178,6 +1143,41 @@
                    }
                }
                function setDefaultTableConfig() {
                    //  최초 업무 공간에 들어왔을 경우
                    $scope.vm.issueTableConfigs = [{
                        name : $filter("translate")("issue.issueTitle"), // 이슈 제목
                        key : "ISSUE_TITLE",
                        width : "width-140-p",
                        position : 1,
                        display : true
                    }, {
                        name : $filter("translate")("common.priority"), // 우선순위
                        key : "PRIORITY",
                        width : "width-80-p",
                        position : 2,
                        display : true
                    }, {
                        name : $filter("translate")("common.importance"), // 중요도
                        key : "SEVERITY",
                        width : "width-80-p",
                        position : 3,
                        display : true
                    }, {
                        name : $filter("translate")("issue.issueType"), // 이슈 타입
                        key : "ISSUE_TYPE",
                        width : "width-140-p",
                        position : 4,
                        display : true
                    }, {
                        name : $filter("translate")("common.assigneeTeam"), // 담당부서
                        key : "ASSIGNEE_TEAM",
                        width : "width-140-p",
                        position : 5,
                        display : true
                    }];
                }
                //  최초 실행
                function startExecute() {
                    // 파라미터 읽기
@@ -1214,38 +1214,7 @@
                                });
                            }
                            else {
                                //  최초 업무 공간에 들어왔을 경우
                                $scope.vm.issueTableConfigs = [{
                                    name : $filter("translate")("issue.issueTitle"), // 이슈 제목
                                    key : "ISSUE_TITLE",
                                    width : "width-140-p",
                                    position : 1,
                                    display : true
                                }, {
                                    name : $filter("translate")("common.priority"), // 우선순위
                                    key : "PRIORITY",
                                    width : "width-80-p",
                                    position : 2,
                                    display : true
                                }, {
                                    name : $filter("translate")("common.importance"), // 중요도
                                    key : "SEVERITY",
                                    width : "width-80-p",
                                    position : 3,
                                    display : true
                                }, {
                                    name : $filter("translate")("issue.issueType"), // 이슈 타입
                                    key : "ISSUE_TYPE",
                                    width : "width-140-p",
                                    position : 4,
                                    display : true
                                }, {
                                    name : $filter("translate")("common.assigneeTeam"), // 담당부서
                                    key : "ASSIGNEE_TEAM",
                                    width : "width-140-p",
                                    position : 5,
                                    display : true
                                }];
                                $scope.fn.setDefaultTableConfig();
                            }
                            //  이슈 테이블 설정
src/main/webapp/views/common/header.html
@@ -1,7 +1,7 @@
<link href="/assets/font/dripicons/webfont.css" rel="stylesheet">
<div class="top-bar color-scheme-light" owl-profile-over>
    <div class="top-menu-controls row">
        <div class="top-left col-lg-8">
        <div class="top-left col-lg-7">
            <h3>
                <span class="badge badge-primary vertical-middle">PROJECT</span> {{$root.workProject.name}}
            </h3>
@@ -25,9 +25,24 @@
            </select>
        </div>
        <div class="top-right col-lg-4">
        <div class="top-right col-lg-5">
            <div class="input-group">
                <input class="form-control"
                       type="text"
                       tabindex="-1"
                       maxlength="300"
                       kr-input
                       owl-auto-focus
                       ng-model="vm.searchAll.keyWord"
                       placeholder="{{'issue.pleaseEnterIssueKeyWord' | translate}}">
                <div class="input-group-prepend ml-10">
                    <button class="btn btn-navy" ng-click="fn.searchAll(0)"> <span translate="common.search">검색</span></button>
                </div>
            </div>
            <!-- 전체 프로젝트 일때 이슈 만들기 버튼 숨김 -->
            <button class="btn btn-xlg btn-primary btn-rounded mr-10" ng-if="$root.workProject.id > -1" ng-click="fn.addIssue()" tabindex="-1">
            <button class="btn btn-xlg btn-primary btn-rounded mr-10 ml-3" ng-if="$root.workProject.id > -1" ng-click="fn.addIssue()" tabindex="-1">
                <i class="os-icon os-icon-plus"></i> <span translate="issue.createIssue">이슈 만들기</span>
            </button>
src/main/webapp/views/issue/issueListNormal.html
@@ -343,7 +343,7 @@
                                <form class="form-inline justify-content-sm-end  pull-right" method="post" action="/issue/downloadExcel" name="issueListForm" >
                                    <!--span class="badge-tip" function-tool-tip  data-placement="top" data-toggle="tooltip" data-original-title="엑셀 다운로드, 일괄 변경 등 다양한 기능을 제공합니다.">?</span-->
                                    <input type="hidden" name="conditions">
                                    <div class="btn-group">
                                    <div class="btn-group" ng-if="vm.listMode === 0">
                                        <button aria-expanded="false" aria-haspopup="true"
                                                tabindex="-1"
                                                class="btn btn-secondary dropdown-toggle"
@@ -370,7 +370,7 @@
                                  event="tableEvent" detail-view="vm.detailView"></js-table>
                        <js-tree ng-if="vm.listMode === 1"
                                  data="vm.responseData.data" table-configs="vm.tableConfigs"
                                  data="vm.responseData.data" table-configs="vm.treeConfigs"
                                  event="tableEvent" detail-view="vm.detailView"></js-tree>
                    </div>
                    <div class="controls-below-table text-center">