OWL ITS + 탐지시스템(인터넷 진흥원)
이민희
2021-11-15 9e1224315ff031c5cfccda6ccb0d7841729d8612
Merge branch 'master' of http://192.168.0.25:9001/r/owl-kisa
2개 파일 추가됨
29개 파일 변경됨
934 ■■■■ 파일 변경됨
src/main/java/kr/wisestone/owl/domain/IssueType.java 13 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java 27 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/vo/IssueTypeVo.java 11 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/web/condition/IssueTypeCondition.java 9 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/web/form/IssueTypeForm.java 9 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/resources/migration/V1_11__Alter_Table.sql 3 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/resources/mybatis/query-template/issueType-template.xml 3 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/resources/system_dev.properties 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/assets/styles/main.css 32 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/custom_components/js-table/tableColumnGenerator.directive.js 7 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/i18n/ko/global.json 13 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/common/common.controller.js 59 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/issue/issueCompanyFieldDetail.controller.js 85 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/issue/issueList.controller.js 17 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/issue/issueManager.controller.js 16 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/issueType/issueTypeAdd.controller.js 24 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/issueType/issueTypeList.controller.js 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/issueType/issueTypeModify.controller.js 28 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/components/utils/autoComplete.controller.js 40 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/config.js 8 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/common/sidebar.html 37 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/issue/issueAdd.html 383 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/issue/issueCompanyFieldDetail.html 37 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/issue/issueDetail.html 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/issue/issueList.html 9 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/issue/issueListNormal.html 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/issue/issueListTimeline.html 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/issue/issueModify.html 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/issue/issueModifyUser.html 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/issueType/issueTypeAdd.html 21 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/issueType/issueTypeModify.html 29 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/domain/IssueType.java
@@ -27,8 +27,13 @@
    @JoinColumn(name = "workflow_id")
    private Workflow workflow;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "project_id")
    private Project project;
    @OneToMany(mappedBy = "issueType", cascade = { CascadeType.ALL }, orphanRemoval = true)
    private Set<IssueTypeCustomField> issueTypeCustomFields = new HashSet<>();
    public IssueType(){}
@@ -95,4 +100,12 @@
    public void setIssueTypeCustomFields(Set<IssueTypeCustomField> issueTypeCustomFields) {
        this.issueTypeCustomFields = issueTypeCustomFields;
    }
    public Project getProject() {
        return project;
    }
    public void setProject(Project project) {
        this.project = project;
    }
}
src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java
@@ -43,6 +43,9 @@
    private WorkflowService workflowService;
    @Autowired
    private ProjectService projectService;
    @Autowired
    private WorkspaceService workspaceService;
    @Autowired
@@ -108,6 +111,8 @@
        issueType.setWorkspace(workspace);
        Workflow workflow = this.workflowService.getWorkflow(issueTypeForm.getWorkflowId());
        issueType.setWorkflow(workflow);
        Project project = this.projectService.getProject(issueTypeForm.getProjectId());
        issueType.setProject(project);
        return this.issueTypeRepository.saveAndFlush(issueType);
    }
@@ -166,6 +171,8 @@
            this.setUseIssueTypeByWorkflow(issueTypeVos);
        }
        this.setUseIssueTypeByProject(issueTypeVos);
        resJsonData.put(Constants.REQ_KEY_PAGE_VO, new ResPage(pageable.getPageNumber(), pageable.getPageSize(),
                totalPage, totalCount));
@@ -179,6 +186,18 @@
        for (IssueTypeVo issueTypeVo : issueTypeVos) {
            IssueType issueType = this.getIssueType(issueTypeVo.getId());
            issueTypeVo.setWorkflowVo(ConvertUtil.copyProperties(issueType.getWorkflow(), WorkflowVo.class));
        }
    }
    //  이슈 유형에 연결된 프로젝트 정보를 셋팅한다.
    private void setUseIssueTypeByProject(List<IssueTypeVo> issueTypeVos) {
        for (IssueTypeVo issueTypeVo : issueTypeVos) {
            IssueType issueType = this.getIssueType(issueTypeVo.getId());
            Project project = issueType.getProject();
            if (project != null) {
                issueTypeVo.setProjectVo(ConvertUtil.copyProperties(issueType.getProject(), ProjectVo.class));
            }
        }
    }
@@ -196,6 +215,11 @@
                case "01": //  워크플로우 정보를 가져온다.
                    issueTypeVo.setWorkflowVo(ConvertUtil.copyProperties(issueType.getWorkflow(), WorkflowVo.class));
                    break;
            }
            Project project = issueType.getProject();
            if (project != null) {
                issueTypeVo.setProjectVo(ConvertUtil.copyProperties(issueType.getProject(), ProjectVo.class));
            }
        }
@@ -222,6 +246,9 @@
        ConvertUtil.copyProperties(issueTypeForm, issueType, "id", "issueTypeType");
        issueType.setWorkflow(workflow);
        Project project = this.projectService.getProject(issueTypeForm.getProjectId());
        issueType.setProject(project);
        this.issueTypeRepository.saveAndFlush(issueType);
        return issueType;
src/main/java/kr/wisestone/owl/vo/IssueTypeVo.java
@@ -1,5 +1,7 @@
package kr.wisestone.owl.vo;
import kr.wisestone.owl.domain.Project;
/**
 * Created by wisestone on 2018-05-29.
 */
@@ -9,6 +11,7 @@
    private String description;
    private String color;
    private WorkflowVo workflowVo;
    private ProjectVo projectVo;
    private Boolean modifyPermissionCheck = Boolean.TRUE;   //  이슈 유형은 모든 사람들이 수정, 삭제할 수 있어서 기본 값이 True
    public IssueTypeVo(){}
@@ -60,4 +63,12 @@
    public void setModifyPermissionCheck(Boolean modifyPermissionCheck) {
        this.modifyPermissionCheck = modifyPermissionCheck;
    }
    public ProjectVo getProjectVo() {
        return projectVo;
    }
    public void setProjectVo(ProjectVo projectVo) {
        this.projectVo = projectVo;
    }
}
src/main/java/kr/wisestone/owl/web/condition/IssueTypeCondition.java
@@ -13,6 +13,7 @@
    private Integer page;
    private Integer pageSize;
    private Long workspaceId;
    private Long projectId;
    private String deep;    //  상세 조회에서 가져올 데이터의 종류를 결정한다.
    public IssueTypeCondition(){}
@@ -69,4 +70,12 @@
    public void setDeep(String deep) {
        this.deep = deep;
    }
    public Long getProjectId() {
        return projectId;
    }
    public void setProjectId(Long projectId) {
        this.projectId = projectId;
    }
}
src/main/java/kr/wisestone/owl/web/form/IssueTypeForm.java
@@ -16,6 +16,7 @@
    private String description;
    private String color;
    private Long workflowId;
    private Long projectId;
    private List<Long> removeIds = Lists.newArrayList();
    public IssueTypeForm(){}
@@ -81,4 +82,12 @@
    public void addRemoveIds(Long removeId) {
        this.removeIds.add(removeId);
    }
    public Long getProjectId() {
        return projectId;
    }
    public void setProjectId(Long projectId) {
        this.projectId = projectId;
    }
}
src/main/resources/migration/V1_11__Alter_Table.sql
@@ -124,3 +124,6 @@
   INDEX `issueTypeIdIndex` (`issue_type_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 이슈 타입 프로젝트
ALTER TABLE `issue_type` ADD COLUMN  `project_id` BIGINT(11) NULL;
src/main/resources/mybatis/query-template/issueType-template.xml
@@ -16,6 +16,9 @@
        <if test="name != '' and name != null">
            AND it.name like CONCAT('%',#{name},'%')
        </if>
        <if test="projectId != '' and projectId != null">
            AND it.project_id like CONCAT('%',#{projectId},'%')
        </if>
        AND ws.id = #{workspaceId}
        <if test="page != null and !page.equals('')">
            limit #{pageSize} offset #{page};
src/main/resources/system_dev.properties
@@ -39,7 +39,7 @@
mail.password=
# email \uC124\uC815
email.host=mail.g2works.kr
email.host=mail.g2works.kra
email.port=587
email.userName=wyu@maprex.co.kr
email.password=1234
src/main/webapp/assets/styles/main.css
@@ -3132,6 +3132,29 @@
    border-color: #292b2c;
}
.btn-indigo {
    color: #fff;
    background-color: #1973EB;
    border-color: #1973EB;
}
.btn-indigo:hover {
    color: #fff;
    background-color: #0f0165;
    border-color: #0f0165;
}
.btn-indigo:focus, .btn-secondary.focus {
    -webkit-box-shadow: 0 0 0 0.2rem rgba(41, 43, 44, 0.5);
    box-shadow: 0 0 0 0.2rem rgba(41, 43, 44, 0.5);
}
.btn-indigo.disabled, .btn-secondary:disabled {
    color: #fff;
    background-color: #292b2c;
    border-color: #292b2c;
}
.btn-success {
    color: #fff;
    background-color: #5eb314;
@@ -28580,7 +28603,6 @@
.tab .tablabel::after {
    display: inline-block;
    color: #4d8bf5;
    background-color:;
    width: 30px;
    font-size: 0.80rem;
    line-height: 40px;
@@ -30173,4 +30195,12 @@
    width: 100%
}
.fontcolor_green {
    color: #6C9266;
    font-size: 15px;
}
.fontcolor_neon_green {
    color: #282c34;
    font-size: 15px;
}
/* 간트차트 end */
src/main/webapp/custom_components/js-table/tableColumnGenerator.directive.js
@@ -81,6 +81,13 @@
                                            }
                                            break;
                                        //  프로젝트 이름(프로젝트 리스트에서 사용)
                                        case "PROJECT_BASIC_NAME" :
                                                if (scope.data.projectVo != null) {
                                                    makeTag += "<span class='titlenameSelect'>" + myToken + scope.data.projectVo.name.replace(/</gi, '&lt;') + "</span>";
                                                }
                                            break;
                                        //  프로젝트 목록에서 사용자 정의 필드 설정 표시
                                        case "CUSTOM_FIELD_CONFIG" :
                                            //  관리자만 수정할 수 있다.
src/main/webapp/i18n/ko/global.json
@@ -291,7 +291,9 @@
        "relationIssueType6" : "다음 이슈를 우선 진행",
        "updateIssueUser" : "이슈 담당자 변경",
        "normalList" : "이슈 목록",
        "timeLine" : "타임 라인"
        "timeLine" : "타임 라인",
        "useProjects" : "사용 프로젝트",
        "companyInfo" : "업체/ISP/호스팅"
    },
    "project": {
        "createProject": "프로젝트 만들기",
@@ -765,7 +767,10 @@
        "departmentName": "부서명",
        "departmentEx": "부서설명",
        "departmentCount": "부서인원",
        "departmentUser": "부서 팀원"
        "departmentUser": "부서 팀원",
        "detectingInfo": "탐지정보",
        "detectingData": "탐지일시",
        "import": "가져오기"
    },
    "tasks": {
        "agileBoardTitle": "칸반 보드"
@@ -796,12 +801,14 @@
        "successToApiTokenAdd" : "API 토큰 생성 성공"
    },
    "companyField" : {
        "info": "업체 정보",
        "add" : "업체 생성",
        "name" : "업체 이름",
        "company" : "업체 분류",
        "profitYN" : "영리/비영리",
        "industry" : "산업 분류",
        "domain" : "도메인",
        "ipAdress" : "ip주소",
        "manager" : "담당자",
        "tel" : "전화번호",
        "code" : "코드",
@@ -817,6 +824,7 @@
        "invalidTelFormat": "전화번호 형식이 맞지 않습니다. xxx-xxx-xxxx 형식으로 입력하세요."
    },
    "ispField" : {
        "info": "ISP 정보",
        "add" : "ISP 생성",
        "name" : "ISP 이름",
        "manager" : "담당자",
@@ -834,6 +842,7 @@
        "invalidCodeFormat": "코드명에는 특수 문자를 입력 할 수 없습니다."
    },
    "hostingField" : {
        "info": "호스팅 정보",
        "add" : "호스팅 생성",
        "name" : "호스팅 이름",
        "manager" : "담당자",
src/main/webapp/scripts/app/common/common.controller.js
@@ -6,8 +6,8 @@
    function (app, angular) {
        app.controller('commonController', ['$scope', '$rootScope', '$log', 'Auth', '$state', 'User', '$resourceProvider', '$uibModal', 'SweetAlert', 'Workspace', '$translate', '$q',
            '$interval', 'IssueSearch', '$filter', 'Notice', 'Project',
            function ($scope, $rootScope, $log, Auth, $state, User, $resourceProvider, $uibModal, SweetAlert, Workspace, $translate, $q, $interval, IssueSearch, $filter, Notice, Project) {
            '$interval', 'IssueSearch', '$filter', 'Notice', 'Project', 'IssueType',
            function ($scope, $rootScope, $log, Auth, $state, User, $resourceProvider, $uibModal, SweetAlert, Workspace, $translate, $q, $interval, IssueSearch, $filter, Notice, Project, IssueType) {
                $scope.fn = {
                    logout: logout,    //  로그아웃
@@ -20,7 +20,9 @@
                    makeIssueSearch: makeIssueSearch,  //  이슈 번호를 저장한 후 이슈 목록으로 이동한다.
                    disconnectSocket: disconnectSocket,    //  웹 소켓 연결 해제
                    sendMessage: sendMessage,
                    moveMenu : moveMenu
                    moveMenu : moveMenu,
                    findIssueList : findIssueList,   // 사이드바 이슈 목록 가져오기
                    changeIssueListMenu : changeIssueListMenu
                };
                $scope.vm = {
@@ -40,6 +42,22 @@
                    findAllWorkproject();
                });
                function changeIssueListMenu(issueTypeId) {
                    $rootScope.issueTypeMenu = null;
                    for (var issueType of $rootScope.workIssueTypes) {
                        if (issueType.id === issueTypeId) {
                            $rootScope.issueTypeMenu = issueType;
                            break;
                        }
                    }
                    if ($rootScope.issueTypeMenu != null) {
                        moveMenu("issues.list");
                    }
                    $rootScope.$broadcast("changeIssueListMenu", $rootScope.issueTypeMenu);
                }
                function moveMenu(stateName) {
                    if ($state.current.name == stateName) {
                        $state.reload();
@@ -50,7 +68,6 @@
                //  메세지 발송
                function sendMessage() {
                    var content = {
                        description : $scope.vm.message,
                        userIds : [1]
@@ -128,6 +145,9 @@
                                    if ($rootScope.user.lastProjectId === project.id) {
                                        $rootScope.workProject = project;
                                    }
                                    var id = $rootScope.workProject.id === -1 ? null : $rootScope.workProject.id;
                                    $scope.fn.findIssueList(id);
                                }
                                $rootScope.projects = datas;
                            }
@@ -180,6 +200,37 @@
                    });
                }
                //  현재 프로젝트 변경시
                $scope.$on("changeLastProject", function (event, args) {
                    findIssueList(args.id);
                });
                // 이슈 유형 목록 가져오기
               function findIssueList(projectId) {
                   //  이슈 타입 목록 검색 조건을 만든다.
                   var conditions = {
                       projectId : projectId > -1 ? projectId : null,
                       deep : "01" //  이슈 유형에 연결된 워크플로우 정보를 찾는다.
                   }
                   IssueType.find($resourceProvider.getContent(conditions,
                       $resourceProvider.getPageContent(0, 100))).then(function (result) {
                       if (result.data.message.status === "success") {
                           $rootScope.workIssueTypes = result.data.data;
                           if ($rootScope.workIssueTypes != null) {
                               changeIssueListMenu($rootScope.workIssueTypes[0].id);
                           }
                       }
                       else {
                           SweetAlert.error($filter("translate")("managementType.failedToIssueTypeList"), result.data.message.message); // "이슈 유형 목록 조회 실패"
                       }
                   });
               }
                // 프로젝트 변경
                function changeLastProject(projectId) {
                   $rootScope.changeLastProject(projectId);
src/main/webapp/scripts/app/issue/issueCompanyFieldDetail.controller.js
New file
@@ -0,0 +1,85 @@
/**
 * Created by wisestone on 2018-02-19.
 */
'use strict';
define([
        'app'
    ],
    function (app) {
        app.controller('companyFieldAddController', ['$scope', '$rootScope', '$log', '$resourceProvider', 'SweetAlert', '$uibModal', '$uibModalInstance', '$state', 'CompanyField', '$filter',
            function ($scope, $rootScope, $log, $resourceProvider, SweetAlert, $uibModal, $uibModalInstance, $state, CompanyField, $filter) {
                $scope.fn = {
                    cancel : cancel,    //  팝업 창 닫기
                    formSubmit : formSubmit,    //  폼 전송
                    formCheck : formCheck,   //  폼 체크
                };
                $scope.vm = {
                    form : {
                        name : "",  //업체명
                        //companyType : "", //업체분류
                        //profitYN : "",  //영리/비영리
                        //industry : "",  //산업분류
                        //domain : "",  //도메인
                        manager : "",   //담당자
                        tel : "",  //전화번호
                        email : "",  //이메일
                        memo : ""  //비고
                    }
                };
                //  폼 체크
                function formCheck(formInvalid) {
                    if (formInvalid) {
                        return true;
                    }
                    return false;
                }
                //  폼 전송
                function formSubmit(condition) {
                    $rootScope.spinner = true;
                    var content = {
                        name : $rootScope.preventXss($scope.vm.form.name),    //  업체명
                        //companyType : $scope.vm.form.companyType, //업체분류
                        //profitYN : $scope.vm.form.profitYN,  //영리/비영리
                        //industry : $scope.vm.form.industry,  //산업분류
                        //domain : $scope.vm.form.domain,  //도메인
                        manager : $scope.vm.form.manager,   //담당자
                        tel : $scope.vm.form.tel,  //전화번호
                        email : $scope.vm.form.email,  //이메일
                        memo : $scope.vm.form.memo  //비고
                    };
                    CompanyField.add($resourceProvider.getContent(content,
                        $resourceProvider.getPageContent(0, 10))).then(function (result) {
                        if (result.data.message.status === "success") {
                            $scope.fn.cancel();
                            //  목록 화면 갱신
                            $rootScope.$broadcast("getPageList", {});
                        }
                        else {
                            SweetAlert.error($filter("translate")("companyField.failedCompanyFieldRegistration"), result.data.message.message);
                        }
                        $rootScope.spinner = false;
                    });
                }
                //  팝업 창 닫기
                function cancel() {
                    $rootScope.$broadcast("closeLayer");    //  팝업이 열리고 나서 js-multi, js-single 등에서 body 이벤트가 날아가는 현상 수정
                    $uibModalInstance.dismiss('cancel');
                    $(document).unbind("keydown");  //  단축키 이벤트 제거
                }
            }
        ]);
    }
);
src/main/webapp/scripts/app/issue/issueList.controller.js
@@ -120,6 +120,7 @@
                //  서버에 저장한 이슈 검색 조건을 가져온다.
                function getVmSearchObject() {
                    IssueSearch.detail($resourceProvider.getContent({}, $resourceProvider.getPageContent(0, 0))).then(function (result) {
                        if (result.data.message.status === "success") {
@@ -239,9 +240,9 @@
                                .setDAlign("text-center")
                                .setDName("issueTypeName"));
                            break;
                        case "ASSIGNEE" :   //  담당자
                        case "ASSIGNEETEAM" :   //  담당부서
                            $scope.vm.tableConfigs.push($tableProvider.config()
                                .setHName("common.assignee")
                                .setHName("common.assigneeTeam")
                                .setDType("renderer")
                                .setHWidth("bold " + issueTableConfig.width)
                                .setDAlign("text-center")
@@ -447,6 +448,14 @@
                        currentPage = selectedPage;
                    }
                    // 메뉴에서 선택된 이슈 유형을 기본으로 추가
                    if ($rootScope.issueTypeMenu != null) {
                        // $scope.vm.pageTitle = $rootScope.issueTypeMenu.name;
                        $scope.vm.search.issueTypeIds.push({
                            fieldKey : $rootScope.issueTypeMenu.id,
                            fieldValue : $rootScope.issueTypeMenu.name
                        });
                    }
                    //  검색 조건을 저장한다.
                    //$scope.fn.makeVmSearchObject();
@@ -857,8 +866,8 @@
                                    position : 3,
                                    display : true
                                }, {
                                    name : $filter("translate")("common.assignee"), // 담당자
                                    key : "ASSIGNEE",
                                    name : $filter("translate")("common.assigneeTeam"), // 담당부서
                                    key : "ASSIGNEETEAM",
                                    width : "width-140-p",
                                    position : 4,
                                    display : true
src/main/webapp/scripts/app/issue/issueManager.controller.js
@@ -12,9 +12,11 @@
                $scope.fn = {
                    changeTab : changeTab,  //  탭 변경
                    start : start
                };
                $scope.vm = {
                    pageTitle : "이슈관리",
                    tab : "ISSUE_LIST" //  업무 공간 정보가 기본 탭
                };
@@ -28,6 +30,20 @@
                        $rootScope.$broadcast("changeListTab");
                    }
                }
                $scope.fn.start();
                $scope.$on("changeIssueListMenu", function (event, args) {
                    if (args != null) {
                        $scope.vm.pageTitle = args.name;
                    }
                });
                function start() {
                    if ($rootScope.issueTypeMenu != null) {
                        $scope.vm.pageTitle = $rootScope.issueTypeMenu.name;
                    }
                }
            }
        ]);
    }
src/main/webapp/scripts/app/issueType/issueTypeAdd.controller.js
@@ -13,6 +13,7 @@
                $scope.fn = {
                    getWorkflowListCallBack : getWorkflowListCallBack,  //  워크플로우 auto complete callback function
                    getProjectListCallBack : getProjectListCallBack, // 프로젝트 auto complete callback function
                    cancel : cancel,    //  팝업 창 닫기
                    formSubmit : formSubmit,    //  폼 전송
                    formCheck : formCheck   //  폼 체크
@@ -22,12 +23,18 @@
                    form : {
                        name : "",  //  이슈 타입 명
                        workflows : [],    //  워크플로우
                        projects : [],      // 프로젝트
                        description : "",  //  설명
                        color : "#febd35" //  색상
                    },
                    projectName : "",
                    workflowName : "",
                    autoCompletePage : {
                        workflow : {
                            page : 0,
                            totalPage : 0
                        },
                        project : {
                            page : 0,
                            totalPage : 0
                        }
@@ -104,6 +111,10 @@
                        return true;
                    }
                    if ($scope.vm.form.projects.length < 1) {
                        return true;
                    }
                    return false;
                }
@@ -119,6 +130,15 @@
                            }
                            return workflowId;
                        })(),
                        projectId :  (function () {
                            var projectId = "";
                            if ($scope.vm.form.projects.length > 0) {
                                projectId = $scope.vm.form.projects[0].id;
                            }
                            return projectId;
                        })(),
                        name : $rootScope.preventXss($scope.vm.form.name),
                        description : $rootScope.preventXss($scope.vm.form.description),
@@ -147,6 +167,10 @@
                    $scope.vm.autoCompletePage.workflow.totalPage = result.data.page.totalPage;
                }
                function getProjectListCallBack(result) {
                    $scope.vm.autoCompletePage.project.totalPage = result.data.page.totalPage;
                }
                function cancel() {
                    $rootScope.$broadcast("closeLayer");    //  팝업이 열리고 나서 js-multi, js-single 등에서 body 이벤트가 날아가는 현상 수정
                    $uibModalInstance.dismiss('cancel');
src/main/webapp/scripts/app/issueType/issueTypeList.controller.js
@@ -68,7 +68,7 @@
                        .setDType("renderer")
                        .setDName("name")
                        .setDAlign("text-center")
                        .setDRenderer("USE_PROJECT_LIST"));
                        .setDRenderer("PROJECT_BASIC_NAME"));
                    $scope.vm.tableConfigs.push($tableProvider.config()
                        .setHName("common.color")
                        .setHWidth("width-140-p bold")
src/main/webapp/scripts/app/issueType/issueTypeModify.controller.js
@@ -13,6 +13,7 @@
                $scope.fn = {
                    getWorkflowListCallBack : getWorkflowListCallBack,  //  워크플로우 auto complete callback function
                    getProjectListCallBack : getProjectListCallBack, // 프로젝트 auto complete callback function
                    cancel : cancel,    //  팝업 창 닫기
                    formSubmit : formSubmit,    //  폼 전송
                    formCheck : formCheck,  //  폼 체크
@@ -28,12 +29,18 @@
                        id : parameter.id,
                        name : "",
                        workflows : [],    //  워크플로우
                        projects : [],      // 프로젝트
                        description : "",  //  설명
                        color : "" //  색상
                    },
                    workflowName : "",
                    projectName : "",
                    autoCompletePage : {
                        workflow : {
                            page : 0,
                            totalPage : 0
                        },
                        project : {
                            page : 0,
                            totalPage : 0
                        }
@@ -100,6 +107,10 @@
                        return true;
                    }
                    if ($scope.vm.form.projects.length < 1) {
                        return true;
                    }
                    return false;
                }
@@ -116,6 +127,15 @@
                            }
                            return workflowId;
                        })(),
                        projectId :  (function () {
                            var projectId = "";
                            if ($scope.vm.form.projects.length > 0) {
                                projectId = $scope.vm.form.projects[0].id;
                            }
                            return projectId;
                        })(),
                        name : $rootScope.preventXss($scope.vm.form.name),
                        description : $rootScope.preventXss($scope.vm.form.description),
@@ -144,6 +164,10 @@
                    $scope.vm.autoCompletePage.workflow.totalPage = result.data.page.totalPage;
                }
                function getProjectListCallBack(result) {
                    $scope.vm.autoCompletePage.project.totalPage = result.data.page.totalPage;
                }
                function cancel() {
                    $rootScope.$broadcast("closeLayer");    //  팝업이 열리고 나서 js-multi, js-single 등에서 body 이벤트가 날아가는 현상 수정
                    $uibModalInstance.dismiss('cancel');
@@ -163,6 +187,10 @@
                                $scope.vm.form.description = result.data.data.description;
                                $scope.vm.form.workflows.push(result.data.data.workflowVo);
                                $scope.vm.workflowName = result.data.data.workflowVo.name;
                                if (result.data.data.projectVo != null) {
                                    $scope.vm.form.projects.push(result.data.data.projectVo);
                                    $scope.vm.projectName = result.data.data.projectVo.name;
                                }
                                $scope.vm.form.color = result.data.data.color;
                            }
                        }
src/main/webapp/scripts/components/utils/autoComplete.controller.js
@@ -17,6 +17,7 @@
                var User = $injector.get("User");
                var Project = $injector.get("Project");
                var Workflow = $injector.get("Workflow");
                var CompanyField = $injector.get("CompanyField");
                var Issue = $injector.get("Issue");
                var UserWorkspace = $injector.get("UserWorkspace");
                var $log = $injector.get("$log");
@@ -28,6 +29,7 @@
                $scope.fn.getIssueList = getIssueList;  //  일감 목록 정보를 조회한다.
                $scope.fn.getWorkflowList = getWorkflowList;    //  워크플로우 목록 정보를 조회한다.
                $scope.fn.getUserDepartmentList = getUserDepartmentList;    //  부서 목록 정보를 조회한다.
                $scope.fn.getCompanyFieldList = getCompanyFieldList;    //  부서 목록 정보를 조회한다.
                function getUserList(query, excludeList, page, callBack) {
                    var conditions = {
@@ -94,6 +96,8 @@
                    var deferred = $q.defer();
                    Project.findWork($resourceProvider.getContent(         //  페이징 업데이트가 필요한 컴포넌트 일경우, page 업데이트가 있을 경우 기본 10개씩 가져오고 아닐경우 25개씩 가져온다.
                        conditions, $resourceProvider.getPageContent($rootScope.isDefined(page) ? page : 0, $rootScope.isDefined(page) ? 10 : 25))).then(function (result) {
                        if (result.data.message.status === "success") {
@@ -111,6 +115,42 @@
                    return deferred.promise;
                }
                function getCompanyFieldList(query, excludeList, page, callBack, statuses, roleTypes) {
                    var conditions = {
                        companyName : query,
                        excludeIds : (function () {
                            var excludeIds = [];
                            angular.forEach(excludeList, function (exclude) {
                                excludeIds.push(exclude.id);
                            });
                            return excludeIds;
                        })()
                    };
                    var deferred = $q.defer();
                    CompanyField.find($resourceProvider.getContent(         //  페이징 업데이트가 필요한 컴포넌트 일경우, page 업데이트가 있을 경우 기본 10개씩 가져오고 아닐경우 25개씩 가져온다.
                        conditions, $resourceProvider.getPageContent($rootScope.isDefined(page) ? page : 0, $rootScope.isDefined(page) ? 10 : 25))).then(function (result) {
                        if (result.data.message.status === "success") {
                            if ($rootScope.isDefined(callBack)) {
                                callBack(result);
                            }
                            deferred.resolve(result.data.data);
                        }
                        else {
                            SweetAlert.swal($filter("translate")("common.failedToProjectListLookUp"), result.data.message.message, "error"); // "프로젝트 목록 조회 실패"
                        }
                    });
                    return deferred.promise;
                }
                function getUserDepartmentList(query, excludeList, page, callBack) {
                    var conditions = {
                        departmentName : query,
src/main/webapp/scripts/config.js
@@ -52,6 +52,10 @@
                $rootScope.projects = [];
                //  현재 사용중인 프로젝트
                $rootScope.workProject = null;
                //  현재 프로젝트에 사용중인 이슈 목록(유형)
                $rootScope.workIssueTypes = [];
                //  현재 선택중인 이슈 목록
                $rootScope.issueTypeMenu = null;
                //  이슈 목록->상세화면에서 마지막으로 접근한 이슈 아이디 - 라우트 탈때마다 초기화
                $rootScope.currentDetailIssueId = null;
                //  문의하기
@@ -310,6 +314,8 @@
                                $rootScope.projects.forEach(function (el) {
                                    if (el.id == projectId) {
                                        $rootScope.workProject = el;
                                        $rootScope.$broadcast("changeLastProject", { id : el.id });
                                    }
                                });
                                $state.go($state.current, {}, {reload: reload});
@@ -318,6 +324,8 @@
                    }
                };
                //  프로젝트 관리 권한이 있는지 확인한다
                $rootScope.checkMngPermissionProject = function () {
                    if (!$rootScope.isDefined($rootScope.user)) {
src/main/webapp/views/common/sidebar.html
@@ -83,6 +83,7 @@
                    <span translate="common.dashboard">대시보드</span>
                </a>
            </li>
            <!--
            <li class="">
                <a ui-sref="tasks.agileBoard" tabindex="-1">
                    <div class="icon-w">
@@ -250,40 +251,16 @@
        <li class="sub-header">
            <span>ISSUE LIST</span>
        </li>
        <!-- UI문서 제작용 임시 코드 시작-->
        <li class="">
            <a ui-sref="dashboards.dashboard" tabindex="-1">
                <div class="icon-w">
        <li ng-repeat="issueType in $root.workIssueTypes">
            <a class="cursor" tabindex="-1" ng-click="fn.changeIssueListMenu(issueType.id)">
                <div class="icon-w ">
                    <div class="os-icon os-icon-layout"></div>
                </div>
                <span>악성 도메인</span>
                <span>{{issueType.name}}</span>
            </a>
        </li>
        <li class="">
            <a ui-sref="dashboards.dashboard" tabindex="-1">
                <div class="icon-w">
                    <div class="os-icon os-icon-layout"></div>
                </div>
                <span>경유지 대응</span>
            </a>
        </li>
        <li class="">
            <a ui-sref="dashboards.dashboard" tabindex="-1">
                <div class="icon-w">
                    <div class="os-icon os-icon-layout"></div>
                </div>
                <span>유포지 대응</span>
            </a>
        </li>
        <li class="">
            <a ui-sref="dashboards.dashboard" tabindex="-1">
                <div class="icon-w">
                    <div class="os-icon os-icon-layout"></div>
                </div>
                <span>분석결과 대응</span>
            </a>
        </li>
        <!-- UI문서 제작용 임시 코드 끝-->
        <!--
        <li class="">
            <a ui-sref="tasks.agileBoard" tabindex="-1">
src/main/webapp/views/issue/issueAdd.html
@@ -136,7 +136,7 @@
            <div class="row">
                <div class="col-lg-4">
                    <div class="form-group mb10">
                        <label class="issue-label"> <span translate="common.assignee">담당자</span> </label>
                        <label class="issue-label"> <span translate="common.assigneeTeam">담당부서</span> </label>
                        <js-input-autocomplete data-input-name="users"
                                               selected-model="vm.form.users"
                                               search="vm.userName"
@@ -148,7 +148,6 @@
                                               extra-settings="{ displayProp : 'byName' , idProp : 'id', imageable : true, imagePathProp : 'profile',
                                               type : 'user', maxlength : 100, autoResize : true, stopRemoveBodyEvent : true }"></js-input-autocomplete>
                        <small translate="issue.setUpUsersParticipatingInProject">프로젝트에 참여하는 사용자를 설정합니다.</small>
                        <div class="select3-selection__choicediv">
                            <span class="select3-selection__choice" ng-repeat="user in vm.form.users">
                                <span class="avatar-w"><img ng-src="{{user.profile}}"></span>
@@ -158,10 +157,10 @@
                            </span>
                        </div>
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mb10">
                        <label for="issueAddForm5" class="issue-label"> <span translate="common.period">기간</span>
                        </label>
                        <label for="issueAddForm5" class="issue-label"> <span translate="common.period">기간</span></label>
                        <input id="issueAddForm5"
                               tabindex="-1"
                               type="text"
@@ -179,7 +178,8 @@
                            </div>
                        </div>
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mgb5">
                        <label class="issue-label"><span translate="common.attachFiles">파일 첨부</span></label>
                        <div class="filebox input-group">
@@ -196,9 +196,6 @@
                                   multiple
                                   ng-file-select="fn.onFileSelect($files)">
                        </div>
                        <small translate="issue.attachOnlyFiles">hwp, jpg, png, txt, pptx, ppt, pdf, xlsx, xls, docx,
                            zip, gif, jpeg, doc, tif, bmp, wmv, avi, mp4, mkv, mov 파일만 첨부할 수 있습니다.
                        </small>
                        <div class="select2-selection__choicediv">
                            <div class="select2-selection__choice2" ng-repeat="file in vm.form.files">
@@ -230,59 +227,335 @@
                        </div>
                    </div>
                </div>
            </div>
                <div class="col-lg-8 bdl1">
                    <div class="row">
                        <div class="col-md-12">
                            <div class="form-group mgb5" ng-show="vm.form.issueCustomFields.length < 1">
                                <label class="issue-label" translate="issue.notIssueTypeCustomFields">이슈 타입에 연결된 사용자 정의
                                    필드가 없습니다.</label>
            <div class="row">
                <div class="col-lg-4 fontcolor_green">
                    <label class="issue-label"><span class="fontcolor_green" translate="common.detectingInfo">탐지정보</span></label>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-4">
                    <div class="form-group mb10">
                        <label for="detectingDateAddForm" class="issue-label"> <span translate="common.detectingData">탐지일시</span> </label>
                        <input id="detectingDateAddForm"
                               tabindex="-1"
                               type="text"
                               readonly
                               class="form-control cursor"
                               placeholder="{{'issue.clickToSelectDate' | translate}}"
                               ng-model="vm.form.startCompleteDateRange"
                               modal-form-auto-scroll
                               date-format="YYYY-MM-DD"
                               parent-el="'#createdWidget2'"
                               date-range-picker>
                        <div class="row">
                            <div class="col-xs-12">
                                <div id="createdWidget2" class="bootstrap-datepicker"></div>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mb10">
                        <label for="domainAddForm" class="issue-label"><span translate="companyField.domain">도메인</span></label>
                        <input id="domainAddForm"
                               name="domain"
                               type="text"
                               class="form-control"
                               kr-input
                               input-regex="[^a-zA-Z0-9 가-힣ㄱ-ㅎㅏ-ㅣ\u318D\u119E\u11A2\u2022\u2025a\u00B7\uFE55]"
                               autocomplete="off"
                               ng-model="vm.form.domain"
                               ng-maxlength="200"
                               maxlength="200">
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mgb5">
                        <label for="ipAdressAddForm" class="issue-label"><span translate="companyField.ipAdress">ip주소</span></label>
                        <input id="ipAdressAddForm"
                               name="ipAdress"
                               type="text"
                               class="form-control"
                               kr-input
                               input-regex="[^a-zA-Z0-9 가-힣ㄱ-ㅎㅏ-ㅣ\u318D\u119E\u11A2\u2022\u2025a\u00B7\uFE55]"
                               autocomplete="off"
                               ng-model="vm.form.ipAdress"
                               ng-maxlength="200"
                               maxlength="200">
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-4 fontcolor_green">
                    <label class="issue-label"><span class="fontcolor_green" translate="companyField.info">업체정보</span></label>
                    <button class="btn btn-sm col-lg-6 btn-indigo" ng-click="fn.companyImport()">
                        &nbsp; &nbsp;  <span translate="common.import">가져오기</span> &nbsp; &nbsp;
                    </button>
                </div>
            </div>
                        <div class="col-md-6" ng-repeat="issueCustomField in vm.form.issueCustomFields">
                            <div class="form-group mgb5">
                                <label class="issue-label">{{issueCustomField.customFieldVo.name}}</label>
                                <div ng-switch on="issueCustomField.customFieldVo.customFieldType">
                                    <!-- 기본 입력 -->
                                    <div ng-switch-when="INPUT">
                                        <input type="text" class="form-control input-sm"
                                               ng-model="issueCustomField.useValues"
                                               maxlength="100"
                                               autocomplete="off"
                                               kr-input
                                               ng-required="issueCustomField.fieldOption == '01'">
                                    </div>
                                    <!-- 단일 셀렉트 -->
                                    <div ng-switch-when="SINGLE_SELECT">
                                        <select class="form-control input-sm issue-select-label"
                                                ng-required="issueCustomField.fieldOption == '01'"
                                                ng-model="issueCustomField.useValues">
                                            <option value="" value="" translate="common.choose">선택하세요.</option>
                                            <option ng-repeat="customFieldValueVo in issueCustomField.customFieldVo.customFieldValueVos"
                                                    value="{{customFieldValueVo.value}}"
                                                    ng-selected="$root.selectOption(issueCustomField.useValues, customFieldValueVo.value)">
                                                {{customFieldValueVo.value}}
                                            </option>
                                        </select>
                                    </div>
                                    <!-- 멀티 셀렉트 -->
                                    <div ng-switch-when="MULTI_SELECT">
                                        <ng-dropdown-multiselect class="multiSelect cursor"
                                                                 data-input-name=""
                                                                 modal-form-auto-scroll
                                                                 selected-model="issueCustomField.useValues"
                                                                 extra-settings="{ 'idProp' : 'value', 'externalIdProp' : 'value', 'displayProp' : 'value', 'stringTypeOption' : 'true', stopRemoveBodyEvent : true }"
                                                                 options="issueCustomField.customFieldVo.customFieldValueVos"></ng-dropdown-multiselect>
                                    </div>
                                </div>
                            </div>
            <div class="row">
                <div class="col-lg-4">
                    <div class="form-group mb10">
                        <label for="companyFieldNameAddForm" class="issue-label"> <span translate="companyField.name">업체명</span> </label>
                        <input id="companyFieldNameAddForm"
                               name="companyName"
                               type="text"
                               class="form-control"
                               autofocus
                               kr-input
                               input-regex="[^a-zA-Z0-9 가-힣ㄱ-ㅎㅏ-ㅣ\u318D\u119E\u11A2\u2022\u2025a\u00B7\uFE55]"
                               autocomplete="off"
                               ng-model="vm.form.companyName"
                               ng-maxlength="100"
                               maxlength="100"
                               required>
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mb10">
                        <label for="companyFieldManagerAddForm" class="issue-label"><span translate="companyField.manager">담당자</span></label>
                        <input id="companyFieldManagerAddForm"
                               name="companyManager"
                               type="text"
                               class="form-control"
                               autofocus
                               kr-input
                               input-regex="[^a-zA-Z0-9 가-힣ㄱ-ㅎㅏ-ㅣ\u318D\u119E\u11A2\u2022\u2025a\u00B7\uFE55]"
                               autocomplete="off"
                               ng-model="vm.form.companyManager"
                               ng-maxlength="100"
                               maxlength="100"
                               required>
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mgb5">
                        <label for="companyFieldTelAddForm" class="issue-label"><span translate="companyField.tel">전화번호</span></label>
                        <input id="companyFieldTelAddForm"
                               name="companyTel"
                               type="text"
                               class="form-control"
                               kr-input
                               ng-pattern="/^\d{2,3}-\d{3,4}-\d{4}$/"
                               autocomplete="off"
                               ng-model="vm.form.companyTel"
                               maxlength="20">
                        <div ng-show="issueAddForm.companyTel.$error.pattern" class="help-block form-text text-danger"
                             translate="companyField.invalidTelFormat">전화번호 형식이 맞지 않습니다. xxx-xxx-xxxx 형식으로 입력하세요.
                        </div>
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mgb5">
                        <label for="companyFieldEmailAddForm" class="issue-label"><span translate="companyField.email">이메일</span></label>
                        <input id="companyFieldEmailAddForm"
                               name="companyEmail"
                               type="email"
                               class="form-control"
                               autocomplete="off"
                               maxLength="50"
                               ng-model="vm.form.companyEmail"
                               kr-input
                               ng-pattern="/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/">
                        <div ng-show="issueAddForm.companyEmail.$error.pattern" class="help-block form-text text-danger"
                             translate="users.invalidEmailFormat">이메일 형식이 맞지 않습니다.
                        </div>
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mgb5">
                        <label for="companyFieldDescAddForm" class="issue-label"><span translate="companyField.desc">비고</span></label>
                        <input id="companyFieldDescAddForm"
                               name="companyDesc"
                               type="text"
                               class="form-control"
                               kr-input
                               autocomplete="off"
                               ng-model="vm.form.companyDesc"
                               ng-maxlength="200"
                               maxlength="200">
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-4 fontcolor_green">
                    <label class="issue-label"><span class="fontcolor_green" translate="ispField.info">ISP 정보</span></label>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-4">
                    <div class="form-group mb10">
                        <label for="ispFieldNameAddForm" class="issue-label"> <span translate="ispField.name">ISP 이름</span> </label>
                        <input id="ispFieldNameAddForm"
                               name=ispName"
                               type="text"
                               class="form-control"
                               autofocus
                               kr-input
                               input-regex="[^a-zA-Z0-9 가-힣ㄱ-ㅎㅏ-ㅣ\u318D\u119E\u11A2\u2022\u2025a\u00B7\uFE55]"
                               autocomplete="off"
                               ng-model="vm.form.ispName"
                               ng-maxlength="100"
                               maxlength="100"
                               required>
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mb10">
                        <label for="ispFieldManagerAddForm" class="issue-label"><span translate="ispField.manager">담당자</span></label>
                        <input id="ispFieldManagerAddForm"
                               name="ispManager"
                               type="text"
                               class="form-control"
                               kr-input
                               input-regex="[^a-zA-Z0-9 가-힣ㄱ-ㅎㅏ-ㅣ\u318D\u119E\u11A2\u2022\u2025a\u00B7\uFE55]"
                               autocomplete="off"
                               ng-model="vm.form.ispManager"
                               ng-maxlength="100"
                               maxlength="100">
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mgb5">
                        <label for="ispFieldTelAddForm" class="issue-label"><span translate="ispField.tel">전화번호</span></label>
                        <input id="ispFieldTelAddForm"
                               name="ispTel"
                               type="text"
                               class="form-control"
                               kr-input
                               ng-pattern="/^\d{2,3}-\d{3,4}-\d{4}$/"
                               autocomplete="off"
                               ng-model="vm.form.ispTel"
                               maxlength="20">
                        <div ng-show="issueAddForm.ispTel.$error.pattern" class="help-block form-text text-danger"
                             translate="companyField.invalidTelFormat">전화번호 형식이 맞지 않습니다. xxx-xxx-xxxx 형식으로 입력하세요.
                        </div>
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mgb5">
                        <label for="ispFieldEmailAddForm" class="issue-label"><span translate="ispField.email">이메일</span></label>
                        <input id="ispFieldEmailAddForm"
                               name="ispEmail"
                               type="email"
                               class="form-control"
                               autocomplete="off"
                               maxLength="50"
                               ng-model="vm.form.ispEmail"
                               kr-input
                               ng-pattern="/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/">
                        <div ng-show="issueAddForm.ispEmail.$error.pattern" class="help-block form-text text-danger"
                             translate="users.invalidEmailFormat">이메일 형식이 맞지 않습니다.
                        </div>
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mgb5">
                        <label for="ispFieldDescAddForm" class="issue-label"><span translate="ispField.desc">비고</span></label>
                        <input id="ispFieldDescAddForm"
                               name="ispDesc"
                               type="text"
                               class="form-control"
                               kr-input
                               autocomplete="off"
                               ng-model="vm.form.ispDesc"
                               ng-maxlength="200"
                               maxlength="200">
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-4 fontcolor_green">
                    <label class="issue-label"><span class="fontcolor_green" translate="hostingField.info">호스팅 정보</span></label>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-4">
                    <div class="form-group mb10">
                        <label for="hostingFieldNameAdd" class="issue-label"> <span translate="hostingField.name">호스팅 이름</span> </label>
                        <input id="hostingFieldNameAdd"
                               name="hostingName"
                               type="text"
                               class="form-control"
                               autofocus
                               kr-input
                               input-regex="[^a-zA-Z0-9 가-힣ㄱ-ㅎㅏ-ㅣ\u318D\u119E\u11A2\u2022\u2025a\u00B7\uFE55]"
                               autocomplete="off"
                               ng-model="vm.form.hostingName"
                               ng-maxlength="100"
                               maxlength="100"
                               required>
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mb10">
                        <label for="hostingFieldManagerAdd" class="issue-label"><span translate="hostingField.manager">담당자</span></label>
                        <input id="hostingFieldManagerAdd"
                               name="hostingManager"
                               type="text"
                               class="form-control"
                               kr-input
                               input-regex="[^a-zA-Z0-9 가-힣ㄱ-ㅎㅏ-ㅣ\u318D\u119E\u11A2\u2022\u2025a\u00B7\uFE55]"
                               autocomplete="off"
                               ng-model="vm.form.hostingManager"
                               ng-maxlength="100"
                               maxlength="100">
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mgb5">
                        <label for="hostingFieldTelAdd" class="issue-label"><span translate="hostingField.tel">전화번호</span></label>
                        <input id="hostingFieldTelAdd"
                               name="hostingTel"
                               type="text"
                               class="form-control"
                               kr-input
                               ng-pattern="/^\d{2,3}-\d{3,4}-\d{4}$/"
                               autocomplete="off"
                               ng-model="vm.form.hostingTel"
                               maxlength="20">
                        <div ng-show="issueAddForm.hostingTel.$error.pattern" class="help-block form-text text-danger"
                             translate="companyField.invalidTelFormat">전화번호 형식이 맞지 않습니다. xxx-xxx-xxxx 형식으로 입력하세요.
                        </div>
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mgb5">
                        <label for="hostingFieldEmailAdd" class="issue-label"><span translate="hostingField.email">이메일</span></label>
                        <input id="hostingFieldEmailAdd"
                               name="hostingEmail"
                               type="email"
                               class="form-control"
                               autocomplete="off"
                               maxLength="50"
                               ng-model="vm.form.hostingEmail"
                               kr-input
                               ng-pattern="/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/">
                        <div ng-show="issueAddForm.hostingEmail.$error.pattern" class="help-block form-text text-danger"
                             translate="users.invalidEmailFormat">이메일 형식이 맞지 않습니다.
                        </div>
                    </div>
                </div>
                <div class="col-lg-4">
                    <div class="form-group mgb5">
                        <label for="hostingFieldDescAdd" class="issue-label"><span translate="hostingField.desc">비고</span></label>
                        <input id="hostingFieldDescAdd"
                               name="hostingDesc"
                               type="text"
                               class="form-control"
                               kr-input
                               autocomplete="off"
                               ng-model="vm.form.hostingDesc"
                               ng-maxlength="200"
                               maxlength="200">
                    </div>
                </div>
            </div>
        </form>
    </div>
src/main/webapp/views/issue/issueCompanyFieldDetail.html
New file
@@ -0,0 +1,37 @@
<div class="formModal">
    <div class="modal-header faded smaller">
        <div class="modal-title">
            <strong>업체 정보</strong>
        </div>
        <button aria-label="Close" class="close" type="button" ng-click="fn.cancel()">
            <span aria-hidden="true"> &times;</span>
        </button>
    </div>
    <div class="modal-body">
        <form role="form" name="companyFieldImportForm">
            <div class="form-group">
                <label><span translate="companyField.name">업체 이름</span>
                       <code class="highlighter-rouge">*</code></label>
                <js-autocomplete-single data-input-name="companyField"
                                        selected-model="vm.form.companyFields"
                                        search="vm.companyName"
                                        source="fn.getCompanyFieldList(vm.companyName, vm.form.companyFields, vm.autoCompletePage.companyField.page, fn.getCompanyFieldListCallBack)"
                                        page="vm.autoCompletePage.companyField.page"
                                        total-page="vm.autoCompletePage.companyField.totalPage"
                                        input-disabled="false"
                                        extra-settings="{ displayProp : 'name' , idProp : 'id', imageable : false, imagePathProp : '',
                                                type : '', maxlength : 200, autoResize : false, stopRemoveBodyEvent : true }"></js-autocomplete-single>
            </div>
            <div class="modal-footer buttons-on-right">
                <button type="button" class="btn btn-md btn-grey" ng-click="fn.cancel()"><span translate="common.cancel">취소</span></button>
                <button type="button" class="btn btn-md btn-primary bold"
                        js-short-cut
                        js-short-cut-action="(fn.formCheck(companyFieldModifyForm.$invalid) || $root.spinner) ? null : fn.formSubmit()"
                        ng-disabled="fn.formCheck(companyFieldImportForm.$invalid)"
                        ng-click="fn.formSubmit()"><span translate="common.save">저장</span>
                </button>
            </div>
        </form>
    </div>
</div>
src/main/webapp/views/issue/issueDetail.html
@@ -207,7 +207,7 @@
                <div class="row">
                    <div class="col-xxl-12">
                        <div class="form-group">
                            <label class="issue-detail-label"><span translate="common.assignee">담당자</span> </label>
                            <label class="issue-detail-label"><span translate="common.assigneeTeam">담당부서</span> </label>
                            <div class="">
                                <div class="select3-selection__choicediv">
                                    <span class="select3-selection__choice" ng-repeat="user in vm.viewer.userVos">
src/main/webapp/views/issue/issueList.html
@@ -1,5 +1,5 @@
<h6 class="element-header" translate="issue.managementIssue">
    이슈 관리
<h6 class="element-header">
    {{vm.pageTitle}}
</h6>
<div class="os-tabs-w">
@@ -8,9 +8,11 @@
            <li class="nav-item">
                <a class="nav-link cursor" ng-class="{ 'active' : vm.tab == 'ISSUE_LIST' }" ng-click="fn.changeTab('ISSUE_LIST')" translate="issue.normalList">일감 목록</a>
            </li>
            <!--
            <li class="nav-item">
                <a class="nav-link cursor" ng-class="{ 'active' : vm.tab == 'ISSUE_TIMELINE' }" ng-click="fn.changeTab('ISSUE_TIMELINE')" translate="issue.timeLine">타임 라인</a>
            </li>
            -->
        </ul>
    </div>
</div>
@@ -20,10 +22,11 @@
    <div ng-show="vm.tab == 'ISSUE_LIST'">
        <div ng-include include-replace src="'views/issue/issueListNormal.html'"></div>
    </div>
<!--
    <div ng-show="vm.tab == 'ISSUE_TIMELINE'">
        <div ng-include include-replace src="'views/issue/issueListTimeline.html'"></div>
    </div>
-->
</div>
src/main/webapp/views/issue/issueListNormal.html
@@ -185,7 +185,7 @@
                                            <div class="col-lg-3">
                                                <div class="form-group">
                                                    <label> <span translate="common.assignee">담당자</span></label>
                                                    <label> <span translate="common.assigneeTeam">담당부서</span></label>
                                                    <js-autocomplete-multi data-input-name="users"
                                                                           selected-model="vm.users"
                                                                           search="vm.userName"
src/main/webapp/views/issue/issueListTimeline.html
@@ -184,7 +184,7 @@
                                            <div class="col-lg-3">
                                                <div class="form-group">
                                                    <label> <span translate="common.assignee">담당자</span></label>
                                                    <label> <span translate="common.assigneeTeam">담당부서</span></label>
                                                    <js-autocomplete-multi data-input-name="users"
                                                                           selected-model="vm.users"
                                                                           search="vm.userName"
src/main/webapp/views/issue/issueModify.html
@@ -138,7 +138,7 @@
            <div class="row">
                <div class="col-lg-4">
                    <div class="form-group mgb5">
                        <label class="issue-label"> <span translate="common.assignee">담당자</span> </label>
                        <label class="issue-label"> <span translate="common.assigneeTeam">담당부서</span> </label>
                        <js-input-autocomplete data-input-name="users"
                                               selected-model="vm.form.users"
                                               search="vm.userName"
src/main/webapp/views/issue/issueModifyUser.html
@@ -12,7 +12,7 @@
        <form role="form" name="issueUserModifyForm">
            <div class="form-group">
                <div class="form-group mgb5">
                    <label class="issue-label"> <span translate="common.assignee">담당자</span> </label>
                    <label class="issue-label"> <span translate="common.assigneeTeam">담당부서</span> </label>
                    <js-input-autocomplete data-input-name="users"
                                           selected-model="vm.form.users"
                                           search="vm.userName"
src/main/webapp/views/issueType/issueTypeAdd.html
@@ -43,17 +43,22 @@
            </div>
            <div class="form-group">
                <label><span translate="issue.useProjects">사용 프로젝트</span></label>
                <js-autocomplete-single data-input-name="workflow"
                                        selected-model="vm.form.workflows"
                                        search="vm.workflowName"
                                        source="fn.getWorkflowList(vm.workflowName, vm.form.workflows, vm.autoCompletePage.workflow.page, fn.getWorkflowListCallBack)"
                                        page="vm.autoCompletePage.workflow.page"
                                        total-page="vm.autoCompletePage.workflow.totalPage"
                <label class="issue-label"> <span translate="issue.useProjects">사용 프로젝트</span> <code
                        class="highlighter-rouge">*</code></label>
                <js-autocomplete-single data-input-name="project"
                                        selected-model="vm.form.projects"
                                        search="vm.projectName"
                                        source="fn.getProjectList(vm.projectName, vm.form.projects, vm.autoCompletePage.project.page, fn.getProjectListCallBack)"
                                        page="vm.autoCompletePage.project.page"
                                        total-page="vm.autoCompletePage.project.totalPage"
                                        input-disabled="false"
                                        extra-settings="{ displayProp : 'name' , idProp : 'id', imageable : false, imagePathProp : '', type : '', maxlength : 200, autoResize : false }"></js-autocomplete-single>
                                        required
                                        translation-texts="{ empty : 'common.emptyProject' }"
                                        extra-settings="{ displayProp : 'name' , idProp : 'id', imageable : false, imagePathProp : '',
                                        type : '', maxlength : 200, autoResize : false, stopRemoveBodyEvent : true }"></js-autocomplete-single>
            </div>
            <div class="form-group">
                <label><span
                        translate="issue.companyInfo">업체/ISP/호스팅 정보</span></label>
src/main/webapp/views/issueType/issueTypeModify.html
@@ -45,6 +45,35 @@
                </div>
            </div>
            <div class="form-group">
                <label class="issue-label"> <span translate="issue.useProjects">사용 프로젝트</span> <code
                        class="highlighter-rouge">*</code></label>
                <js-autocomplete-single data-input-name="project"
                                        selected-model="vm.form.projects"
                                        search="vm.projectName"
                                        source="fn.getProjectList(vm.projectName, vm.form.projects, vm.autoCompletePage.project.page, fn.getProjectListCallBack)"
                                        page="vm.autoCompletePage.project.page"
                                        total-page="vm.autoCompletePage.project.totalPage"
                                        input-disabled="false"
                                        required
                                        translation-texts="{ empty : 'common.emptyProject' }"
                                        extra-settings="{ displayProp : 'name' , idProp : 'id', imageable : false, imagePathProp : '',
                                        type : '', maxlength : 200, autoResize : false, stopRemoveBodyEvent : true }"></js-autocomplete-single>
            </div>
            <div class="form-group">
                <label><span
                        translate="issue.companyInfo">업체/ISP/호스팅 정보</span></label>
                <ng-dropdown-multiselect class="multiSelect cursor"
                                         data-input-name="issueStatusTypes"
                                         selected-model="vm.search.issueStatusTypes"
                                         extra-settings="{ stringTypeOption : true }"
                                         options="vm.options.emailTemplates"></ng-dropdown-multiselect>
            </div>
            <div class="form-group">
                <label for="issueTypeModifyForm2"><span translate="common.color">색상</span> <code class="highlighter-rouge">*</code></label>
                <div class="input-group">