OWL ITS + 탐지시스템(인터넷 진흥원)
jhjang
2021-11-29 f3d433b269f28e99dd352f5b69f8ef864c09e5b0
- api 기본값 설정 기능 완료
- api 중복 필드 설정 기능 완료
6개 파일 추가됨
7개 파일 변경됨
611 ■■■■■ 파일 변경됨
src/main/java/kr/wisestone/owl/repository/CustomFieldApiOverlapRepository.java 12 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/CustomFieldApiOverlapService.java 14 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/CustomFieldApiOverlapServiceImpl.java 90 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/IssueApiDefaultServiceImpl.java 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/vo/CustomFieldApiOverlapVo.java 48 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/web/controller/CustomFieldApiOverlapController.java 48 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/web/form/CustomFieldApiOverlapForm.java 61 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/api/apiSetting.controller.js 145 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/components/api/api.service.js 12 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/components/utils/autoComplete.controller.js 36 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/main.js 1 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/api/apiSettingColumn.html 68 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/api/apiSettingOverlap.html 74 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/repository/CustomFieldApiOverlapRepository.java
New file
@@ -0,0 +1,12 @@
package kr.wisestone.owl.repository;
import kr.wisestone.owl.domain.CustomFieldApiOverlap;
import kr.wisestone.owl.domain.IssueApiDefault;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface CustomFieldApiOverlapRepository extends JpaRepository<CustomFieldApiOverlap, Long> {
    List<CustomFieldApiOverlap> findByUserIdAndIssueTypeId(@Param("UserId") Long userId, @Param("IssueTypeId") Long issueTypeId);
}
src/main/java/kr/wisestone/owl/service/CustomFieldApiOverlapService.java
New file
@@ -0,0 +1,14 @@
package kr.wisestone.owl.service;
import kr.wisestone.owl.domain.CustomFieldApiOverlap;
import kr.wisestone.owl.domain.IssueApiDefault;
import kr.wisestone.owl.web.form.CustomFieldApiOverlapForm;
import kr.wisestone.owl.web.form.IssueApiDefaultForm;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Map;
public interface CustomFieldApiOverlapService extends AbstractService<CustomFieldApiOverlap, Long, JpaRepository<CustomFieldApiOverlap, Long>> {
    void find(Map<String, Object> resJsonData, CustomFieldApiOverlapForm form);
    boolean modify(Map<String, Object> resJsonData, CustomFieldApiOverlapForm form);
}
src/main/java/kr/wisestone/owl/service/impl/CustomFieldApiOverlapServiceImpl.java
New file
@@ -0,0 +1,90 @@
package kr.wisestone.owl.service.impl;
import com.google.common.collect.Lists;
import kr.wisestone.owl.constant.Constants;
import kr.wisestone.owl.domain.*;
import kr.wisestone.owl.repository.CustomFieldApiOverlapRepository;
import kr.wisestone.owl.repository.IssueApiDefaultRepository;
import kr.wisestone.owl.service.*;
import kr.wisestone.owl.util.ConvertUtil;
import kr.wisestone.owl.vo.*;
import kr.wisestone.owl.web.form.CustomFieldApiOverlapForm;
import kr.wisestone.owl.web.form.IssueApiDefaultForm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
@Service
public class CustomFieldApiOverlapServiceImpl extends AbstractServiceImpl<CustomFieldApiOverlap, Long, JpaRepository<CustomFieldApiOverlap, Long>>
        implements CustomFieldApiOverlapService {
    static final Logger log = LoggerFactory.getLogger(CustomFieldApiOverlapServiceImpl.class);
    @Autowired
    private CustomFieldApiOverlapRepository customFieldApiOverlapRepository;
    @Autowired
    private IssueTypeService issueTypeService;
    @Autowired
    private CustomFieldService customFieldService;
    @Override
    protected JpaRepository<CustomFieldApiOverlap, Long> getRepository() {
        return this.customFieldApiOverlapRepository;
    }
    @Override
    @Transactional
    public void find(Map<String, Object> resJsonData, CustomFieldApiOverlapForm form) {
        UserVo userVo = this.webAppUtil.getLoginUser();
        List<CustomFieldApiOverlap> customFieldApiOverlaps = this.customFieldApiOverlapRepository.findByUserIdAndIssueTypeId(userVo.getId(), form.getIssueTypeId());
        if (customFieldApiOverlaps != null && customFieldApiOverlaps.size() > 0) {
            List<CustomFieldApiOverlapVo> customFieldApiOverlapVos =  Lists.newArrayList();
            for (CustomFieldApiOverlap customFieldApiOverlap : customFieldApiOverlaps) {
                CustomFieldApiOverlapVo customFieldApiOverlapVo = ConvertUtil.copyProperties(customFieldApiOverlap, CustomFieldApiOverlapVo.class);
                CustomField customField = customFieldApiOverlap.getCustomField();
                if (customField != null) {
                    customFieldApiOverlapVo.setCustomFieldVo(ConvertUtil.copyProperties(customField, CustomFieldVo.class));
                }
                customFieldApiOverlapVos.add(customFieldApiOverlapVo);
            }
            resJsonData.put(Constants.RES_KEY_CONTENTS, customFieldApiOverlapVos);
        }
    }
    @Override
    @Transactional
    public boolean modify(Map<String, Object> resJsonData, CustomFieldApiOverlapForm form) {
        User user = this.webAppUtil.getLoginUserObject();
        List<CustomFieldApiOverlap> customFieldApiOverlaps = this.customFieldApiOverlapRepository.findByUserIdAndIssueTypeId(user.getId(), form.getIssueTypeId());
        if (customFieldApiOverlaps != null && customFieldApiOverlaps.size() > 0) {
            this.customFieldApiOverlapRepository.deleteAll(customFieldApiOverlaps);
        }
        List<CustomFieldApiOverlap> customFieldApiOverlapList = Lists.newArrayList();
        for (Long customFieldId : form.getCustomFieldIds()) {
            CustomFieldApiOverlap customFieldApiOverlap = ConvertUtil.copyProperties(form, CustomFieldApiOverlap.class);
            CustomField customField = this.customFieldService.getCustomField(customFieldId);
            customFieldApiOverlap.setCustomField(customField);
            customFieldApiOverlap.setUser(user);
            customFieldApiOverlap.setIssueType(this.issueTypeService.getIssueType(form.getIssueTypeId()));
            customFieldApiOverlapList.add(customFieldApiOverlap);
        }
        this.customFieldApiOverlapRepository.saveAll(customFieldApiOverlapList);
        return  true;
    }
}
src/main/java/kr/wisestone/owl/service/impl/IssueApiDefaultServiceImpl.java
@@ -57,7 +57,7 @@
            }
            Priority priority = issueApiDefault.getPriority();
            if (project != null) {
            if (priority != null) {
                issueApiDefaultVo.setPriorityId(priority.getId());
            }
src/main/java/kr/wisestone/owl/vo/CustomFieldApiOverlapVo.java
New file
@@ -0,0 +1,48 @@
package kr.wisestone.owl.vo;
import kr.wisestone.owl.domain.CustomField;
import java.util.Date;
public class CustomFieldApiOverlapVo extends BaseVo {
    private Long id;
    private Long userId;
    private Long issueTypeId;
    private CustomFieldVo customFieldVo;
    public CustomFieldApiOverlapVo() {
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public Long getUserId() {
        return userId;
    }
    public void setUserId(Long userId) {
        this.userId = userId;
    }
    public Long getIssueTypeId() {
        return issueTypeId;
    }
    public void setIssueTypeId(Long issueTypeId) {
        this.issueTypeId = issueTypeId;
    }
    public CustomFieldVo getCustomFieldVo() {
        return customFieldVo;
    }
    public void setCustomFieldVo(CustomFieldVo customFieldVo) {
        this.customFieldVo = customFieldVo;
    }
}
src/main/java/kr/wisestone/owl/web/controller/CustomFieldApiOverlapController.java
New file
@@ -0,0 +1,48 @@
package kr.wisestone.owl.web.controller;
import kr.wisestone.owl.constant.Constants;
import kr.wisestone.owl.service.CustomFieldApiOverlapService;
import kr.wisestone.owl.service.IssueApiDefaultService;
import kr.wisestone.owl.util.ConvertUtil;
import kr.wisestone.owl.web.form.CustomFieldApiOverlapForm;
import kr.wisestone.owl.web.form.IssueApiDefaultForm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@Controller
public class CustomFieldApiOverlapController extends BaseController {
    @Autowired
    private CustomFieldApiOverlapService customFieldApiOverlapService;
    //  이슈 타입별 기본값 가져오기
    @RequestMapping(value = "customFieldApiOverlap/find", produces = MediaType.APPLICATION_JSON_VALUE)
    public
    @ResponseBody
    Map<String, Object> find(@RequestBody Map<String, Map<String, Object>> params) {
        Map<String, Object> resJsonData = new HashMap<>();
        this.customFieldApiOverlapService.find(resJsonData, CustomFieldApiOverlapForm.make(params.get(Constants.REQ_KEY_CONTENT)));
        return this.setSuccessMessage(resJsonData);
    }
    //  이슈 타입별 기본값 가져오기
    @RequestMapping(value = "customFieldApiOverlap/modify", produces = MediaType.APPLICATION_JSON_VALUE)
    public
    @ResponseBody
    Map<String, Object> modify(@RequestBody Map<String, Map<String, Object>> params) {
        Map<String, Object> resJsonData = new HashMap<>();
        this.customFieldApiOverlapService.modify(resJsonData, CustomFieldApiOverlapForm.make(params.get(Constants.REQ_KEY_CONTENT)));
        return this.setSuccessMessage(resJsonData);
    }
}
src/main/java/kr/wisestone/owl/web/form/CustomFieldApiOverlapForm.java
New file
@@ -0,0 +1,61 @@
package kr.wisestone.owl.web.form;
import kr.wisestone.owl.util.ConvertUtil;
import kr.wisestone.owl.util.MapUtil;
import org.hibernate.annotations.DynamicInsert;
import java.util.List;
import java.util.Map;
@DynamicInsert
public class CustomFieldApiOverlapForm {
    private Long id;
    private Long userId;
    private Long issueTypeId;
    private List<Long> customFieldIds;
    public CustomFieldApiOverlapForm(){}
    public static CustomFieldApiOverlapForm make(Map<String, Object> params) {
        CustomFieldApiOverlapForm form = ConvertUtil.convertMapToClass(params, CustomFieldApiOverlapForm.class);
        if (MapUtil.getLongs(params, "customFieldIds") != null) {
            form.setCustomFieldIds(MapUtil.getLongs(params, "customFieldIds"));
        }
        return form;
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public Long getIssueTypeId() {
        return issueTypeId;
    }
    public void setIssueTypeId(Long issueTypeId) {
        this.issueTypeId = issueTypeId;
    }
    public Long getUserId() {
        return userId;
    }
    public void setUserId(Long userId) {
        this.userId = userId;
    }
    public List<Long> getCustomFieldIds() {
        return customFieldIds;
    }
    public void setCustomFieldIds(List<Long> customFieldIds) {
        this.customFieldIds = customFieldIds;
    }
}
src/main/webapp/scripts/app/api/apiSetting.controller.js
@@ -7,8 +7,8 @@
        'app', 'angular'
    ],
    function (app, angular) {
        app.controller('apiSettingController', ['$scope', '$rootScope', '$log', '$resourceProvider','$uibModal', 'SweetAlert', '$timeout', '$filter', '$injector', '$controller', 'Api', 'Priority', 'Severity',
            function ($scope, $rootScope, $log, $resourceProvider, $uibModal, SweetAlert, $timeout, $filter, $injector, $controller, Api, Priority, Severity) {
        app.controller('apiSettingController', ['$scope', '$rootScope', '$log', '$resourceProvider','$uibModal', 'SweetAlert', '$timeout', '$filter', '$injector', '$controller', 'Api', 'Priority', 'Severity', 'IssueType',
            function ($scope, $rootScope, $log, $resourceProvider, $uibModal, SweetAlert, $timeout, $filter, $injector, $controller, Api, Priority, Severity, IssueType) {
                $scope.fn = {
                    changeTab : changeTab,
@@ -19,7 +19,15 @@
                    initForm : initForm,
                    getPriorities : getPriorities,
                    getSeverities : getSeverities,
                    start : start
                    start : start,
                    getIssueTypes : getIssueTypes,
                    onChangeIssueType : onChangeIssueType,
                    reset : reset,
                    resetOverlap : resetOverlap,
                    formSubmitOverlap : formSubmitOverlap,
                    removeCustomField : removeCustomField,
                    getOverlapList : getOverlapList,
                    onChangeIssueTypeOverlap : onChangeIssueTypeOverlap
                };
                $scope.vm = {
@@ -34,8 +42,10 @@
                            description : "",
                            priorityId : "",
                            severityId : "",
                            customFields : [],
                            // projectName : "",
                        }
                        },
                        customFieldId : "",
                    },
                    autoCompletePage : {
@@ -48,7 +58,9 @@
                        //     totalPage : 0
                        // }
                    },
                    issueTypeId : "",
                    issueTypeName : "",
                    customFieldName : "",
                    issueTypeData : null            // 이슈 유형 객체
                };
@@ -61,22 +73,75 @@
                    $scope.vm.form.issueApiDefault.severityId = "";
                }
                // 이슈 유형 클릭시
                $scope.$on("onClickIssueType", function (evnet, args) {
                    if (args != null && args.length > 0) {
                function reset() {
                    $scope.fn.initForm();
                    $scope.fn.formSubmit();
                }
                function resetOverlap() {
                    $scope.vm.form.customFieldIds = [];
                    $scope.fn.form.formSubmitOverlap();
                }
                function  getOverlapList() {
                    let conditions = {
                        issueTypeId: $scope.vm.issueTypeId
                    }
                    Api.findApiOverlap($resourceProvider.getContent(
                        conditions, $resourceProvider.getPageContent(0, 1000))).then(function (result) {
                        if (result.data.message.status === "success") {
                            let customFieldApiOverlaps = result.data.data;
                            $scope.vm.form.customFields = [];
                            customFieldApiOverlaps.forEach(function (customFieldApiOverlap) {
                                $scope.vm.form.customFields.push(customFieldApiOverlap.customFieldVo);
                            });
                        }
                        else {
                            SweetAlert.swal($filter("translate")("issue.failedToIssueTypeListLookup"), result.data.message.message, "error"); // "이슈 유형 목록 조회 실패"
                        }
                    });
                }
                function getIssueTypes() {
                    var conditions = {
                    };
                    IssueType.find($resourceProvider.getContent(
                        conditions, $resourceProvider.getPageContent(0, 1000))).then(function (result) {
                        if (result.data.message.status === "success") {
                            $scope.vm.issueTypes = result.data.data;
                            if ($scope.vm.issueTypes != null && $scope.vm.issueTypes.length > 0) {
                                $scope.vm.issueTypeId = $scope.vm.issueTypes[0].id.toString();
                                $scope.fn.onChangeIssueType();
                            }
                        }
                        else {
                            SweetAlert.swal($filter("translate")("issue.failedToIssueTypeListLookup"), result.data.message.message, "error"); // "이슈 유형 목록 조회 실패"
                        }
                    });
                }
                function onChangeIssueTypeOverlap() {
                    $scope.fn.getOverlapList();
                }
                function onChangeIssueType() {
                    if ($scope.vm.issueTypeId != null) {
                        let conditions = {
                            issueTypeId: args[0].id
                            issueTypeId: $scope.vm.issueTypeId
                        }
                        Api.findApiDefault($resourceProvider.getContent(
                            conditions, $resourceProvider.getPageContent(0, 0))).then(function (result) {
                            conditions, $resourceProvider.getPageContent(0, 1000))).then(function (result) {
                            $scope.fn.initForm();
                            if (result.data.message.status === "success") {
                                if (angular.isDefined(result.data.data)) {
                                    $scope.vm.form.issueApiDefault = result.data.data;
                                    $scope.vm.form.issueApiDefault.priorityId = result.data.data.priorityId.toString();
                                    $scope.vm.form.issueApiDefault.severityId = result.data.data.severityId.toString();
                                    $scope.vm.form.issueApiDefault.priorityId = result.data.data.priorityId != null ? result.data.data.priorityId.toString() : "";
                                    $scope.vm.form.issueApiDefault.severityId = result.data.data.severityId != null ? result.data.data.severityId.toString() : "";
                                    // if (angular.isDefined(result.data.data.projectVo)) {
                                    //     $scope.vm.projects = [];
@@ -88,7 +153,8 @@
                            }
                        });
                    }
                });
                }
                //  폼 체크
                function formCheck(formInvalid) {
@@ -100,11 +166,11 @@
                }
                function formSubmit() {
                    if ($scope.vm.issueTypes == null || $scope.vm.issueTypes.length === 0)
                    if ($scope.vm.issueTypeId == null)
                        return;
                    let condition = {
                        issueTypeId : $scope.vm.issueTypes[0].id,
                        issueTypeId : $scope.vm.issueTypeId,
                        title : $scope.vm.form.issueApiDefault.title,
                        // projectId : $scope.vm.projects != null && $scope.vm.projects.length > 0 ? $scope.vm.projects[0].id : null,
                        priorityId : $scope.vm.form.issueApiDefault.priorityId,
@@ -116,10 +182,45 @@
                        $resourceProvider.getPageContent(0, 1))).then(function (result) {
                        if (result.data.message.status === "success") {
                            SweetAlert.swal($filter("translate")("api.successToApiIssueDefault"), result.data.message.message, "success"); // "api 토큰 생성 성공"
                            SweetAlert.swal($filter("translate")("api.successToApiIssueDefault"), result.data.message.message, "success"); // "api 기본값 설정 성공"
                        }
                        else {
                            SweetAlert.swal($filter("translate")("api.failedToApiIssueDefault"), result.data.message.message, "error"); // "api 토큰 생성 실패"
                            SweetAlert.swal($filter("translate")("api.failedToApiIssueDefault"), result.data.message.message, "error"); // "api 기본값 설정 실패"
                        }
                    });
                }
                // 사용자 정의 필드 선택 항목 삭제
                function removeCustomField(index) {
                    $scope.vm.form.customFields.splice(index, 1);
                }
                // 중복 항목 전송
                function formSubmitOverlap() {
                    if ($scope.vm.issueTypeId === null)
                        return;
                    let condition = {
                        issueTypeId : $scope.vm.issueTypeId,
                        customFieldIds : (function () {
                            var ids = [];
                            angular.forEach($scope.vm.form.customFields, function (customField) {
                                ids.push(customField.id);
                            });
                            return ids;
                        })(),
                    }
                    Api.modifyApiOverlap($resourceProvider.getContent(condition,
                        $resourceProvider.getPageContent(0, 1))).then(function (result) {
                        if (result.data.message.status === "success") {
                            SweetAlert.swal($filter("translate")("api.successToApiIssueOverlap"), result.data.message.message, "success"); // "api 중복값 설정 성공"
                        }
                        else {
                            SweetAlert.swal($filter("translate")("api.failedToApiIssueOverlap"), result.data.message.message, "error"); // "api 중복값 설정 실패"
                        }
                    });
                }
@@ -160,6 +261,15 @@
                    });
                }
                $rootScope.$on("changeColumnSettingTab", function (event, args){
                    $scope.fn.start();
                });
                $rootScope.$on("changeOverlapSettingTab", function (event, args){
                    $scope.fn.getOverlapList();
                });
                function changeTab(tab) {
                    $scope.vm.tab = tab;
@@ -175,8 +285,9 @@
                    $scope.fn.initForm();
                    $scope.fn.getSeverities();
                    $scope.fn.getPriorities();
                    $scope.fn.getIssueTypes();
                }
                $scope.fn.start();
            }]);
    });
src/main/webapp/scripts/components/api/api.service.js
@@ -34,6 +34,18 @@
                    $log.debug("이슈 유형 초기값 수정 결과 : ", response);
                    return response;
                });
            },
            findApiOverlap : function (conditions) {
                return $http.post("customFieldApiOverlap/find", conditions).then(function (response) {
                    $log.debug("이슈 유형 중복값 조회 결과 : ", response);
                    return response;
                });
            },
            modifyApiOverlap : function (conditions) {
                return $http.post("customFieldApiOverlap/modify", conditions).then(function (response) {
                    $log.debug("이슈 유형 중복값 수정 결과 : ", response);
                    return response;
                });
            }
        }
    }
src/main/webapp/scripts/components/utils/autoComplete.controller.js
@@ -23,6 +23,7 @@
                var IspField = $injector.get("IspField");
                var HostingField = $injector.get("HostingField");
                var IssueType = $injector.get("IssueType");
                var CustomField = $injector.get("CustomField");
                var $log = $injector.get("$log");
                var SweetAlert = $injector.get("SweetAlert");
@@ -38,6 +39,7 @@
                $scope.fn.getIssueHostingFieldList = getIssueHostingFieldList;    //  호스팅 목록 정보를 조회한다.
                $scope.fn.getPartnerList = getPartnerList;          // 업체/isp/호스팅 목록 조회
                $scope.fn.getIssueTypeList = getIssueTypeList;          // 이슈 유형 목록 조회
                $scope.fn.getCustomFieldList = getCustomFieldList;          // 사용자 정의 필드 목록 조회
                function getUserList(query, excludeList, page, callBack) {
                    var conditions = {
@@ -403,6 +405,40 @@
                    return deferred.promise;
                }
                function getCustomFieldList(query, excludeList, page, callBack) {
                    var conditions = {
                        name : query,
                        excludeIds : (function () {
                            var excludeIds = [];
                            angular.forEach(excludeList, function (exclude) {
                                excludeIds.push(exclude.id);
                            });
                            return excludeIds;
                        })()
                    };
                    var deferred = $q.defer();
                    CustomField.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")("issue.failedToIssueTypeListLookup"), result.data.message.message, "error"); // "이슈 유형 목록 조회 실패"
                        }
                    });
                    return deferred.promise;
                }
                function getIssueTypeList(query, excludeList, page, callBack) {
                    var conditions = {
                        name : query,
src/main/webapp/scripts/main.js
@@ -523,6 +523,7 @@
    'authService',
    'userInviteService',
    'projectService',
    'customFieldService',
    'loginRoute',
    'projectRoute',
    'issueStatusRoute',
src/main/webapp/views/api/apiSettingColumn.html
@@ -1,21 +1,25 @@
<div class="row">
    <div class="col-md-4">
        <div class="form-group mb10">
            <label class="issue-label"> <span translate="issue.issueType">이슈 유형</span>
                <code class="highlighter-rouge">*</code></label>
            <js-autocomplete-single data-input-name="issueType"
                                    selected-model="vm.issueTypes"
                                    search="vm.issueTypeName"
                                    source="fn.getIssueTypeList(vm.issueTypeName, vm.issueTypes, vm.autoCompletePage.issueType.page, fn.getIssueTypeCallback)"
                                    page="vm.autoCompletePage.issueType.page"
                                    total-page="vm.autoCompletePage.issueType.totalPage"
                                    input-disabled="false"
                                    required
                                    broad-cast="onClickIssueType"
                                    translation-texts="{ empty : 'common.emptyIssueType' }"
                                    extra-settings="{ displayProp : 'name' , idProp : 'id', imageable : false, imagePathProp : '',
                                            type : '', maxlength : 200, autoResize : false, stopRemoveBodyEvent : true }"></js-autocomplete-single>
            <label for="issueTypeForm" class="issue-label">
                <span translate="issue.issueType">이슈 유형</span>
            </label>
            <select id="issueTypeForm"
                    name="issueType"
                    class="form-control input-sm issue-select-label"
                    ng-model="vm.issueTypeId"
                    ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.issueTypeId) }"
                    ng-change="fn.onChangeIssueType()"
                    required>
                <option ng-repeat="issueType in vm.issueTypes"
                        ng-style="{ 'color' : issueType.color, 'font-weight': 600 }"
                        value="{{issueType.id}}"
                        translate="{{issueType.name}}">
                </option>
            </select>
        </div>
    </div>
</div>
@@ -23,8 +27,29 @@
<div class="element-box">
    <form role="form" name="apiSettingColumnForm">
        <div class="form-group mb10">
            <label for="issueAddForm1" class="issue-label"><span translate="issue.issueTitle">일감 제목</span> </label>
            <input id="issueAddForm1"
            <label for="customFieldSelectForm" class="issue-label">
                <span translate="issue.issueType">이슈 유형</span>
            </label>
            <select id="customFieldSelectForm"
                    name="issueType"
                    class="form-control input-sm issue-select-label"
                    ng-model="vm.issueTypeId"
                    ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.issueTypeId) }"
                    ng-change="fn.onChangeIssueType()"
                    required>
                <option ng-repeat="issueType in vm.issueTypes"
                        ng-style="{ 'color' : issueType.color, 'font-weight': 600 }"
                        value="{{issueType.id}}"
                        translate="{{issueType.name}}">
                </option>
            </select>
        </div>
        <div class="form-group mb10">
            <label for="issueTitle" class="issue-label"><span translate="issue.issueTitle">일감 제목</span> </label>
            <input id="issueTitle"
                   class="form-control input-sm"
                   ng-model="vm.form.issueApiDefault.title"
                   name="title"
@@ -58,10 +83,10 @@
                    <div class="col-md-4">
                        <div class="form-group mb10">
                            <label for="issueAddForm2" class="issue-label">
                            <label for="issue-priority" class="issue-label">
                                <span translate="common.priority">우선 순위</span>
                            </label>
                            <select id="issueAddForm2"
                            <select id="issue-priority"
                                    name="priority"
                                    class="form-control input-sm issue-select-label"
                                    ng-model="vm.form.issueApiDefault.priorityId"
@@ -77,9 +102,9 @@
                    </div>
                    <div class="col-md-4">
                        <div class="form-group mb10">
                            <label for="issueAddForm3" class="issue-label"> <span
                            <label for="issue-severity" class="issue-label"> <span
                                    translate="common.importance">중요도</span> </label>
                            <select id="issueAddForm3"
                            <select id="issue-severity"
                                    name="severity"
                                    class="form-control input-sm issue-select-label"
                                    ng-model="vm.form.issueApiDefault.severityId"
@@ -113,6 +138,9 @@
    </form>
    <div class="modal-footer buttons-on-right">
        <button type="button" class="btn btn-md btn-secondary bold"
                ng-click="fn.reset()"><span translate="common.reset">초기화</span>
        </button>
        <button type="button" class="btn btn-md btn-primary bold"
                js-short-cut
                js-short-cut-action="(fn.formCheck(apiSettingColumnForm.$invalid) || $root.spinner) ? null : fn.formSubmit()"
src/main/webapp/views/api/apiSettingOverlap.html
@@ -2,35 +2,63 @@
<div class="row">
    <div class="col-sm-5">
        <div class="element-wrapper">
            <label for="issueAddForm4" class="issue-label"> <span
                    translate="issue.issueType">이슈 타입</span>
            </label>
            <select id="issueAddForm4"
                    name="issueType"
                    class="form-control input-sm issue-select-label"
                    ng-model="vm.form.issueTypeId"
                    ng-change="fn.getIssueTypeCustomFields()"
                    ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.form.issueTypeId) }"
                    required>
                <option ng-style="{ 'color' : '#353535' }" value="">홈페이지 변조 감지
                </option>
                <option ng-style="{ 'color' : '#353535' }" value="">경유지 탐지
                </option>
                <option ng-repeat="issueType in vm.issueTypes"
                        ng-style="{ 'color' : issueType.color, 'font-weight': 600 }"
                        value="{{issueType.id}}">●&nbsp;{{issueType.name}}
                </option>
            </select>
            <div class="form-group mb10">
                <label for="issueTypeForm" class="issue-label">
                    <span translate="issue.issueType">이슈 유형</span>
                </label>
                <select id="issueTypeForm"
                        name="issueType"
                        class="form-control input-sm issue-select-label"
                        ng-model="vm.issueTypeId"
                        ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.issueTypeId) }"
                        ng-change="fn.onChangeIssueTypeOverlap()"
                        required>
                    <option ng-repeat="issueType in vm.issueTypes"
                            ng-style="{ 'color' : issueType.color, 'font-weight': 600 }"
                            value="{{issueType.id}}"
                            translate="{{issueType.name}}">
                    </option>
                </select>
            </div>
        </div>
    </div>
</div>
<div class="element-box">
    <p class="btn btn-secondary">
        <span >경유지</span>
        <span>×</span>
    </p>
    <form role="form" name="apiSettingOverlapForm">
        <div class="form-group">
            <label><span translate="common.customField">사용자 정의 필드</span> </label>
            <js-autocomplete-multi data-input-name="customField"
                                   selected-model="vm.form.customFields"
                                   search="vm.customFieldName"
                                   source="fn.getCustomFieldList(vm.customFieldName, vm.form.customFields)"
                                   input-disabled="false"
                                   translation-texts="{ count : 'common.few', empty : 'common.emptyCustomField' }"
                                   required
                                   extra-settings="{ displayProp : 'name' , idProp : 'id', imageable : false, maxlength : 100, autoResize : true }"></js-autocomplete-multi>
            <div class="select3-selection__choicediv mt-10">
                <span class="select3-selection__choice" ng-repeat="customField in vm.form.customFields">
                    <span>{{customField.name}}</span>
                    <span class="select3-selection__choice__remove" ng-click="fn.removeCustomField($index)">×</span>
                </span>
            </div>
        </div>
        <div class="modal-footer buttons-on-right">
            <button type="button" class="btn btn-md btn-secondary bold"
                    ng-click="fn.resetOverlap()"><span translate="common.reset">초기화</span>
            </button>
            <button type="button" class="btn btn-md btn-primary bold"
                    js-short-cut
                    js-short-cut-action="(fn.formCheck(apiSettingOverlapForm.$invalid) || $root.spinner) ? null : fn.formSubmitOverlap()"
                    ng-click="fn.formSubmitOverlap()"><span translate="common.saved">생성</span>
            </button>
      </div>
    </form>
</div>