OWL ITS + 탐지시스템(인터넷 진흥원)
이민희
2021-12-23 ea58f79355dd5715c7889623f59f5e8fca81e811
Merge branch 'master' of http://192.168.0.25:9001/r/owl-kisa
14개 파일 변경됨
248 ■■■■ 파일 변경됨
src/main/java/kr/wisestone/owl/service/UserDepartmentService.java 3 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/UserDepartmentServiceImpl.java 19 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/impl/UserServiceImpl.java 13 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/vo/UserVo.java 18 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/web/controller/ApiController.java 4 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/assets/styles/main.css 4 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/api/apiSetting.controller.js 83 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/customField/customFieldAdd.controller.js 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/customField/customFieldModify.controller.js 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/api/apiSettingSpec.html 18 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/common/sidebar.html 4 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/customField/customFieldAdd.html 30 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/customField/customFieldModify.html 46 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/issue/issueDetail.html 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/java/kr/wisestone/owl/service/UserDepartmentService.java
@@ -1,5 +1,6 @@
package kr.wisestone.owl.service;
import kr.wisestone.owl.domain.Department;
import kr.wisestone.owl.domain.UserDepartment;
import kr.wisestone.owl.web.condition.UserCondition;
import kr.wisestone.owl.web.condition.UserDepartmentCondition;
@@ -16,4 +17,6 @@
    void userDepartmentModify(UserDepartmentForm userDepartmentForm);
    List<UserDepartment> findByDepartmentId(Long id);
    List<Department> findDepartment(Long id);
}
src/main/java/kr/wisestone/owl/service/impl/UserDepartmentServiceImpl.java
@@ -5,14 +5,15 @@
import kr.wisestone.owl.constant.MsgConstants;
import kr.wisestone.owl.domain.*;
import kr.wisestone.owl.exception.OwlRuntimeException;
import kr.wisestone.owl.mapper.UserMapper;
import kr.wisestone.owl.repository.UserDepartmentRepository;
import kr.wisestone.owl.service.DepartmentService;
import kr.wisestone.owl.service.UserDepartmentService;
import kr.wisestone.owl.service.UserService;
import kr.wisestone.owl.util.ConvertUtil;
import kr.wisestone.owl.util.MapUtil;
import kr.wisestone.owl.vo.*;
import kr.wisestone.owl.web.condition.DepartmentCondition;
import kr.wisestone.owl.web.condition.UserCondition;
import kr.wisestone.owl.web.condition.UserDepartmentCondition;
import kr.wisestone.owl.web.form.UserDepartmentForm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
@@ -94,6 +95,20 @@
        return this.userDepartmentRepository.findByDepartmentId(id);
    }
    @Override
    public List<Department> findDepartment(Long userId) {
        List<UserDepartment> userDepartments = this.userDepartmentRepository.findByUserId(userId);
        if (userDepartments != null && userDepartments.size() > 0) {
            List<Department> departments = Lists.newArrayList();
            for (UserDepartment userDepartment : userDepartments) {
                Department department = this.departmentService.getDepartment(userDepartment.getDepartmentId());
                departments.add(department);
            }
            return departments;
        }
        return null;
    }
    // 사용자 부서 ID로 조회한다.
//    @Override
src/main/java/kr/wisestone/owl/service/impl/UserServiceImpl.java
@@ -107,6 +107,9 @@
    private AttachedFileService attachedFileService;
    @Autowired
    private UserDepartmentService userDepartmentService;
    @Autowired
    private IssueService issueService;
    @Autowired
@@ -1245,6 +1248,16 @@
        // user에서 Permission 값을 가져와서 userVo 에 setPermission 함
        userVo.setPermission(user.getPermission());
        userVo.setAccount(CommonUtil.decryptAES128(userVo.getAccount()));
        UserLevel userLevel = user.getUserLevel();
        if (userLevel != null) {
            userVo.setLevelName(userLevel.getLevelName());
        }
        List<Department> departments = this.userDepartmentService.findDepartment(user.getId());
        if (departments != null) {
            userVo.setDepartmentVos(ConvertUtil.convertObjectsToClasses(departments, DepartmentVo.class));
        }
        resJsonData.put(Constants.RES_KEY_CONTENTS, userVo);
        //  사용자 세션 정보를 분석해서 로그에 남긴다.
        log.info(ElasticSearchUtil.makeUserSessionHistoryMessage(httpServletRequest, userVo));
src/main/java/kr/wisestone/owl/vo/UserVo.java
@@ -22,6 +22,8 @@
    private Long lastProjectId;
    private Long lastIssueTypeId;
    private Long departmentId;
    private String levelName;
    private List<DepartmentVo> departmentVos = Lists.newArrayList();
    private Boolean userSocialLogin = Boolean.FALSE;
    private List<ProjectVo> projectVos = Lists.newArrayList();
    private String reservationNotifyTime;
@@ -214,4 +216,20 @@
    public void setProjectManagerYN(Boolean projectManagerYN) {
        this.projectManagerYN = projectManagerYN;
    }
    public String getLevelName() {
        return levelName;
    }
    public void setLevelName(String levelName) {
        this.levelName = levelName;
    }
    public List<DepartmentVo> getDepartmentVos() {
        return departmentVos;
    }
    public void setDepartmentVos(List<DepartmentVo> departmentVos) {
        this.departmentVos = departmentVos;
    }
}
src/main/java/kr/wisestone/owl/web/controller/ApiController.java
@@ -47,7 +47,9 @@
    Map<String, Object> addIssue(MultipartHttpServletRequest request) throws OwlRuntimeException, CloneNotSupportedException {
        Map<String, Object> resJsonData = new HashMap<>();
        IssueApiForm issueForm = IssueApiForm.make(ConvertUtil.convertJsonToMap(request.getParameter(Constants.REQ_KEY_CONTENT)), request.getFiles("file"));
        String str = request.getParameter(Constants.REQ_KEY_CONTENT);
        IssueApiForm issueForm = IssueApiForm.make(ConvertUtil.convertJsonToMap(str), request.getFiles("file"));
        if (issueForm == null) {
            throw new OwlRuntimeException(this.messageAccessor.getMessage(MsgConstants.API_PARAMETER_ERROR));
        }
src/main/webapp/assets/styles/main.css
@@ -262,6 +262,8 @@
    margin-top: 0;
    margin-bottom: 1rem;
    overflow: auto;
    white-space: pre-line;
    word-break : break-word;
    -ms-overflow-style: scrollbar;
}
@@ -29722,7 +29724,7 @@
    z-index: 2;
    overflow: hidden;
    margin-top: 80px;
 }
}
.footer-w .logo-element {
    text-align: center;
src/main/webapp/scripts/app/api/apiSetting.controller.js
@@ -25,17 +25,19 @@
                    getSeverities : getSeverities,
                    onChangeColumnSetting : onChangeColumnSetting,
                    onChangeEndIssueStatus : onChangeEndIssueStatus,
                    onChangeIssueTypeOverlap : onChangeIssueTypeOverlap,
                    onChangeIssueTypeSpec : onChangeIssueTypeSpec,
                    onChangeProject : onChangeProject,
                    onChangeIssueStatus : onChangeIssueStatus,
                    getIssueTypes : getIssueTypes,
                    reset : reset,
                    resetOverlap : resetOverlap,
                    formSubmitOverlap : formSubmitOverlap,
                    removeCustomField : removeCustomField,
                    getOverlapList : getOverlapList,
                    onChangeIssueTypeOverlap : onChangeIssueTypeOverlap,
                    getIssueTypeCustomFields : getIssueTypeCustomFields,
                    getCurrentIssueTypeVo : getCurrentIssueTypeVo,
                    getIssueStatuses : getIssueStatuses,
                    onChangeIssueTypeSpec : onChangeIssueTypeSpec,
                    createRequestModifyJson : createRequestModifyJson,
                    createRequestAddJson : createRequestAddJson,
                    createCustomFields : createCustomFields,
@@ -44,8 +46,9 @@
                    loadPage : loadPage,
                    resetCompleteIssueStatus : resetCompleteIssueStatus,
                    findIssueList : findIssueList,
                    onChangeProject : onChangeProject,
                    setApiIssueTypeStatus : setApiIssueTypeStatus
                    setApiIssueTypeStatus : setApiIssueTypeStatus,
                    findToken : findToken,
                    createAPISample : createAPISample
                };
                $scope.vm = {
@@ -60,6 +63,7 @@
                    sampleJsonModify : "",
                    // projects : [],
                    form : {
                        token : "!토큰값입력(토큰발급필요)!",
                        issueCustomFields : [],
                        issueApiDefault : {
                            title : "",
@@ -316,7 +320,7 @@
                     //  이슈 유형에 연결된 사용자 정의 필드
                function getIssueTypeCustomFields() {
                    var deferred = $q.defer();
                    $scope.vm.form.issueCustomFields = [];
                    var issueTypeVo = $scope.fn.getCurrentIssueTypeVo();
@@ -335,7 +339,7 @@
                                $scope.vm.form.issueCustomFields.push(issueTypeCustomField);
                            });
                            $scope.$broadcast("getIssueTypeListComplete", $scope.vm.form.issueCustomFields);
                            deferred.resolve(result.data.data);
                        }
                        else {
@@ -343,6 +347,7 @@
                        }
                    });
                    return deferred.promise;
                }
@@ -361,12 +366,12 @@
                    });
                }
                $scope.$on("getIssueTypeListComplete", function (event, args) {
                    if ($scope.vm.tab === "API_SPEC_SETTING") {
                        $scope.fn.createRequestAddJson();
                        $scope.fn.createRequestModifyJson();
                    }
                });
                // $scope.$on("getIssueTypeListComplete", function (event, args) {
                //     if ($scope.vm.tab === "API_SPEC_SETTING") {
                //         $scope.fn.createRequestAddJson();
                //         $scope.fn.createRequestModifyJson();
                //     }
                // });
                function changeTab(tab) {
                    $scope.vm.tab = tab;
@@ -411,6 +416,7 @@
                }
                function getIssueStatuses() {
                    var deferred = $q.defer();
                    var condition = {
                        issueTypeId: $scope.vm.issueTypeId
                    }
@@ -419,6 +425,7 @@
                        if (result.data.message.status === "success") {
                            $scope.vm.issueStatuses = result.data.data;
                            deferred.resolve(result.data.data);
                            // $scope.vm.issueStatusId = "";
                            if ($scope.vm.issueStatuses != null && $scope.vm.issueStatuses.length > 0) {
@@ -429,11 +436,11 @@
                                $scope.fn.setApiIssueTypeStatus();
                            }
                            $scope.$broadcast("getIssueStatusComplete", $scope.vm.issueStatuses);
                        } else {
                            SweetAlert.swal($filter("translate")("issue.failedToCriticalListLookup"), result.data.message.message, "error"); // 중요도 목록 조회 실패
                        }
                    });
                    return deferred.promise;
                }
                function onChangeColumnSetting() {
@@ -502,9 +509,28 @@
                    });
                }
                function createAPISample() {
                    $scope.fn.createRequestAddJson();
                    $scope.fn.createRequestModifyJson();
                }
                function onChangeIssueStatus() {
                    // $scope.fn.getIssueStatuses();
                    // $scope.fn.getIssueTypeCustomFields();
                    $scope.fn.findToken();
                    $scope.fn.createAPISample();
                }
                function onChangeIssueTypeSpec() {
                    $scope.fn.getIssueStatuses();
                    $scope.fn.getIssueTypeCustomFields();
                    var promises = {
                        issueStatues : $scope.fn.getIssueStatuses(),
                        issueTypeCustomFields : $scope.fn.getIssueTypeCustomFields(),
                        token : $scope.fn.findToken()
                    }
                    $q.all(promises).then(function (results) {
                        $scope.fn.createAPISample();
                    });
                }
                // 요청 데이터 만들기( 추가)
@@ -512,7 +538,7 @@
                    var customFields = $scope.fn.createCustomFields();
                    var jsonData = {
                            token: "||발급받은 토큰}||",
                            token: $scope.vm.form.token,
                            title: "||이슈 제목||",
                            issueTypeId: $scope.vm.issueTypeId,
                            apiType: "add",
@@ -520,6 +546,29 @@
                        };
                    $scope.vm.sampleJsonAdd = JSON.stringify(jsonData,undefined, 4);
                }
                function findToken() {
                    var deferred = $q.defer();
                    var conditions = {
                    }
                    Api.find($resourceProvider.getContent(conditions,
                        $resourceProvider.getPageContent(0, 1))).then(function (result) {
                        if (result.data.message.status === "success") {
                            if (result.data.data != null) {
                                $scope.vm.form.token = result.data.data.token;
                            }
                            deferred.resolve(result.data.data);
                        }
                        else {
                        }
                    });
                    return deferred.promise;
                }
                function createCustomFields() {
@@ -538,7 +587,7 @@
                    var customFields = $scope.fn.createCustomFields();
                    var jsonData = {
                        token: "||발급받은 토큰||",
                        token: $scope.vm.form.token,
                        issueTypeId: $scope.vm.issueTypeId,
                        apiType: "modify",
                        issueStatusId: $scope.vm.issueStatusId,
src/main/webapp/scripts/app/customField/customFieldAdd.controller.js
@@ -27,7 +27,7 @@
                        options : [],   //  옵션
                        optionText : "",  //  옵션 값
                        numberType : "",
                        ipAdress : "",
                        ipAddress : "",
                        email : "",
                        site : "",
                        tel : "",
src/main/webapp/scripts/app/customField/customFieldModify.controller.js
@@ -36,7 +36,7 @@
                        optionText : "",   //  옵션 값
                        useCustomFieldValue : false, //  이슈에서 사용되고 있는지 여부 확인
                        numberType : "",
                        ipAdress : "",
                        ipAddress : "",
                        email : "",
                        site : "",
                        tel : "",
src/main/webapp/views/api/apiSettingSpec.html
@@ -14,7 +14,7 @@
                                class="form-control input-sm issue-select-label"
                                ng-style="{ 'color' : fn.getOptionColor(vm.issueStatuses, vm.issueStatusId) }"
                                ng-model="vm.issueStatusId"
                                ng-change="fn.onChangeIssueTypeSpec()"
                                ng-change="fn.onChangeIssueStatus()"
                                required>
                            <option ng-repeat="issueStatus in vm.issueStatuses"
                                    ng-style="{ 'color' : issueStatus.color, 'font-weight': 600 }"
@@ -56,16 +56,20 @@
<div class="element-box">
    <div class="row">
        <div class="col-md-1">
        <div>
            <label class="issue-label">
                <span translate="api.requestSampleAdd">이슈 추가</span>
            </label>
        </div>
        <div>
    </div>
    <div class="row">
        <div class="text-wrap">
            <pre>{{vm.sampleJsonAdd}}</pre>
        </div>
        <div class="col-md-1"></div>
        <div class="col-md-1">
    </div>
    <hr>
    <div class="row">
        <div>
            <label class="issue-label">
                <span translate="api.requestSampleModify">이슈 수정</span>
            </label>
@@ -73,7 +77,9 @@
                <span translate="api.requestSampleModifyDesc">수정시</span>
            </label>
        </div>
        <div class="col-md-2">
    </div>
    <div class="row">
        <div class="text-wrap">
            <div>
                <pre>{{vm.sampleJsonModify}}</pre>
            </div>
src/main/webapp/views/common/sidebar.html
@@ -184,8 +184,8 @@
    </div>
    <div class="logged-user-w avatar-inline">
        <div class="row mb-1" ng-if="$root.myLevel != null" >
            <span class="issue-main-label offset-detail-5 badge badge-primary">{{$root.myLevel}}</span>
        <div class="row mb-1" ng-if="$root.user.levelName != null" >
            <span class="issue-main-label offset-detail-5 badge badge-primary">{{$root.user.levelName}}</span>
            <span class="issue-main-label offset-detail-1 badge badge-department">{{$root.myDepartments}}</span>
        </div>
        <div class="logged-user-i">
src/main/webapp/views/customField/customFieldAdd.html
@@ -25,7 +25,7 @@
                       ng-maxlength="15"
                       input-regex="[^a-zA-Z0-9 가-힣ㄱ-ㅎㅏ-ㅣ\u318D\u119E\u11A2\u2022\u2025a\u00B7\uFE55]"
                       required>
                <small ng-show="customFieldAddForm.name.$error.maxlength" translate="common.upTo15Characters">
                <small ng-if="customFieldAddForm.name.$error.maxlength" translate="common.upTo15Characters">
                    최대 15글자까지 입력할 수 있습니다.
                </small>
                <small translate="customField.limitNameToSpecialCharacters">사용자 정의 필드 명은 특수 문자를 입력할 수 없습니다.</small>
@@ -55,15 +55,15 @@
                </div>
            </div>
            <div class="form-group" ng-show="vm.form.customFieldType == 'SINGLE_SELECT' || vm.form.customFieldType == 'MULTI_SELECT'">
                <label ng-show="vm.form.customFieldType == 'SINGLE_SELECT'"><span
            <div class="form-group" ng-if="vm.form.customFieldType == 'SINGLE_SELECT' || vm.form.customFieldType == 'MULTI_SELECT'">
                <label ng-if="vm.form.customFieldType == 'SINGLE_SELECT'"><span
                        translate="customField.createSingleFieldList">단일 선택 필드 목록 만들기</span> <code
                        class="highlighter-rouge">*</code></label>
                <label ng-show="vm.form.customFieldType == 'MULTI_SELECT'"><span
                <label ng-if="vm.form.customFieldType == 'MULTI_SELECT'"><span
                        translate="customField.createMultiFieldList">다중 선택 필드 목록 만들기</span> <code
                        class="highlighter-rouge">*</code></label>
                <div class="input-group" ng-show="vm.form.customFieldType == 'SINGLE_SELECT' || vm.form.customFieldType == 'MULTI_SELECT'">
                <div class="input-group" ng-if="vm.form.customFieldType == 'SINGLE_SELECT' || vm.form.customFieldType == 'MULTI_SELECT'">
                    <input id="optionAdd"
                           type="text"
                           name="options"
@@ -82,7 +82,7 @@
                </small>
            </div>
            <div ng-repeat="option in vm.form.options" ng-show="vm.form.customFieldType != 'INPUT'">
            <div ng-repeat="option in vm.form.options" ng-if="vm.form.customFieldType == 'SINGLE_SELECT' || vm.form.customFieldType == 'MULTI_SELECT'">
                <span class="select3-selection__choice">
                    <span>{{option}}</span>
                    <span class="select3-selection__choice__remove" ng-click="fn.removeOption($index)">×</span>
@@ -91,7 +91,7 @@
            <div class="form-group">
                <label for="customFieldAddForm3"><span translate="customField.defaultValue">기본값</span> </label>
                <input ng-if="vm.form.customFieldType == 'INPUT' || vm.form.customFieldType == 'SINGLE_SELECT' || vm.form.customFieldType == 'MULTI_SELECT'"
                <input ng-show="vm.form.customFieldType == 'INPUT' || vm.form.customFieldType == 'SINGLE_SELECT' || vm.form.customFieldType == 'MULTI_SELECT'"
                       id="customFieldAddForm3"
                       type="text"
                       name="defaultValue"
@@ -112,7 +112,7 @@
                       placeholder="숫자만 입력 가능합니다."
                       autocomplete="off"
                       ng-model="vm.form.defaultValue">
                <div ng-show="customFieldAddForm.numberType.$error.pattern" class="help-block form-text text-danger"
                <div ng-if="customFieldAddForm.numberType.$error.pattern" class="help-block form-text text-danger"
                     translate="common.invalidNumberFormat">숫자만 입력 가능합니다.
                </div>
@@ -139,7 +139,7 @@
                       placeholder="IP 주소 형식만 입력 가능합니다."
                       autocomplete="off"
                       ng-model="vm.form.defaultValue">
                <div ng-show="customFieldAddForm.ipAddress.$error.pattern" class="help-block form-text text-danger"
                <div ng-if="customFieldAddForm.ipAddress.$error.pattern" class="help-block form-text text-danger"
                     translate="common.invalidipAdressFormat">IP주소 형식이 맞지 않습니다.
                </div>
@@ -153,7 +153,7 @@
                       placeholder="이메일 형식만 입력 가능합니다."
                       autocomplete="off"
                       ng-model="vm.form.defaultValue">
                <div ng-show="customFieldAddForm.email.$error.pattern" class="help-block form-text text-danger"
                <div ng-if="customFieldAddForm.email.$error.pattern" class="help-block form-text text-danger"
                     translate="common.invalidEmailFormat">이메일 형식이 맞지 않습니다.
                </div>
@@ -167,7 +167,7 @@
                       placeholder="홈페이지 주소 형식만 입력 가능합니다."
                       autocomplete="off"
                       ng-model="vm.form.defaultValue">
                <div ng-show="customFieldAddForm.site.$error.pattern" class="help-block form-text text-danger"
                <div ng-if="customFieldAddForm.site.$error.pattern" class="help-block form-text text-danger"
                     translate="common.invalidSiteFormat">홈페이지 주소 형식이 맞지 않습니다.(http://로 시작하셔야합니다)
                </div>
@@ -181,19 +181,19 @@
                       placeholder="연락처 형식만 입력 가능합니다."
                       autocomplete="off"
                       ng-model="vm.form.defaultValue">
                <div ng-show="customFieldAddForm.tel.$error.pattern" class="help-block form-text text-danger"
                <div ng-if="customFieldAddForm.tel.$error.pattern" class="help-block form-text text-danger"
                     translate="common.invalidTelFormat">전화번호 형식이 맞지 않습니다.
                </div>
                <small ng-show="vm.form.customFieldType == 'INPUT'" translate="common.upTo100Characters">
                <small ng-if="vm.form.customFieldType == 'INPUT'" translate="common.upTo100Characters">
                    최대 100글자까지 입력할 수 있습니다.
                </small>
                <div class="help-block form-text text-danger" ng-show="vm.form.customFieldType == 'SINGLE_SELECT'"
                <div class="help-block form-text text-danger" ng-if="vm.form.customFieldType == 'SINGLE_SELECT'"
                     translate="customField.selectSingleFieldListHashTag">
                    단일 선택 필드 목록에 있는 값을 기본적으로 선택하고 싶을 때는 해시태그를 사용해야합니다. ex) #대상값
                </div>
                <div class="help-block form-text text-danger" ng-show="vm.form.customFieldType == 'MULTI_SELECT'"
                <div class="help-block form-text text-danger" ng-if="vm.form.customFieldType == 'MULTI_SELECT'"
                     translate="customField.selectMultiFieldListHashTag">
                    다중 선택 필드 목록에 있는 값을 기본적으로 선택하고 싶을 때는 해시태그를 사용해야합니다. ex) #대상값#대상값
                </div>
src/main/webapp/views/customField/customFieldModify.html
@@ -25,7 +25,7 @@
                       ng-maxlength="15"
                       input-regex="[^a-zA-Z0-9 가-힣ㄱ-ㅎㅏ-ㅣ\u318D\u119E\u11A2\u2022\u2025a\u00B7\uFE55]"
                       required>
                <small ng-show="customFieldModifyForm.name.$error.maxlength" class="help-block form-text text-danger"
                <small ng-if="customFieldModifyForm.name.$error.maxlength" class="help-block form-text text-danger"
                       translate="common.upTo15Characters">
                    최대 15글자까지 입력할 수 있습니다.
                </small>
@@ -35,7 +35,7 @@
            <div class="form-group">
                <label for="customFieldModifyForm2"><span translate="customField.fieldType">필드 유형</span><code
                        class="highlighter-rouge">*</code></label>
                &nbsp;&nbsp; <label> <input type="checkbox" ng-model="vm.form.requiredData"> 필수 데이터 </label>
                <!--&nbsp;&nbsp; <label> <input type="checkbox" ng-model="vm.form.requiredData"> 필수 데이터 </label>-->
                <select id="customFieldModifyForm2" class="form-control" ng-model="vm.form.customFieldType"
                        ng-change="fn.changeCustomFieldType()">
                    <option value="INPUT" translate="common.stringField">문자열 필드</option>
@@ -48,17 +48,23 @@
                    <option value="SITE" translate="common.siteField">홈페이지 주소 필드</option>
                    <option value="TEL" translate="common.telField">전화번호 필드</option>
                </select>
                <div class="mt-3">
                    <span class="custom-detail-label">필수 데이터</span>
                    <label class='switch'><input type='checkbox' ng-model="vm.form.requiredData">
                        <span class='slider round'></span>
                    </label>
                </div>
            </div>
            <div class="form-group" ng-show="vm.form.customFieldType == 'SINGLE_SELECT' || vm.form.customFieldType == 'MULTI_SELECT'">
                <label ng-show="vm.form.customFieldType == 'SINGLE_SELECT'"><span
            <div class="form-group" ng-if="vm.form.customFieldType == 'SINGLE_SELECT' || vm.form.customFieldType == 'MULTI_SELECT'">
                <label ng-if="vm.form.customFieldType == 'SINGLE_SELECT'"><span
                        translate="customField.createSingleFieldList">단일 선택 필드 목록 만들기</span> <code
                        class="highlighter-rouge">*</code></label>
                <label ng-show="vm.form.customFieldType == 'MULTI_SELECT'"><span
                <label ng-if="vm.form.customFieldType == 'MULTI_SELECT'"><span
                        translate="customField.createMultiFieldList">다중 선택 필드 목록 만들기</span> <code
                        class="highlighter-rouge">*</code></label>
                <div class="input-group">
                <div class="input-group" ng-if="vm.form.customFieldType == 'SINGLE_SELECT' || vm.form.customFieldType == 'MULTI_SELECT'">
                    <input id="optionAdd"
                           type="text"
                           name="options"
@@ -77,8 +83,8 @@
                </small>
            </div>
            <div ng-repeat="option in vm.form.options" ng-show="vm.form.customFieldType == 'SINGLE_SELECT' || vm.form.customFieldType == 'MULTI_SELECT'">
<!--            <div ng-repeat="option in vm.form.options" ng-show="vm.form.customFieldType != 'INPUT'">-->
            <div ng-repeat="option in vm.form.options" ng-if="vm.form.customFieldType == 'SINGLE_SELECT' || vm.form.customFieldType == 'MULTI_SELECT'">
<!--            <div ng-repeat="option in vm.form.options" ng-if="vm.form.customFieldType != 'INPUT'">-->
                <span class="select3-selection__choice">
                    <span>{{option}}</span>
                    <span class="select3-selection__choice__remove" ng-click="fn.removeOption($index)">×</span>
@@ -87,7 +93,7 @@
            <div class="form-group">
                <label for="customFieldModifyForm3"><span translate="customField.defaultValue">기본값</span> </label>
                <input ng-if="vm.form.customFieldType == 'INPUT' || vm.form.customFieldType == 'SINGLE_SELECT' || vm.form.customFieldType == 'MULTI_SELECT'"
                <input ng-show="vm.form.customFieldType == 'INPUT' || vm.form.customFieldType == 'SINGLE_SELECT' || vm.form.customFieldType == 'MULTI_SELECT'"
                       id="customFieldModifyForm3"
                       type="text"
                       name="defaultValue"
@@ -107,7 +113,7 @@
                       placeholder="숫자만 입력 가능합니다."
                       autocomplete="off"
                       ng-model="vm.form.defaultValue">
                <div ng-show="customFieldModifyForm.numberType.$error.pattern" class="help-block form-text text-danger"
                <div ng-if="customFieldModifyForm.numberType.$error.pattern" class="help-block form-text text-danger"
                     translate="common.invalidNumberFormat">숫자만 입력 가능합니다.
                </div>
@@ -134,7 +140,7 @@
                       placeholder="IP 주소 형식만 입력 가능합니다."
                       autocomplete="off"
                       ng-model="vm.form.defaultValue">
                <div ng-show="customFieldModifyForm.ipAddress.$error.pattern" class="help-block form-text text-danger"
                <div ng-if="customFieldModifyForm.ipAddress.$error.pattern" class="help-block form-text text-danger"
                     translate="common.invalidipAdressFormat">IP주소 형식이 맞지 않습니다.
                </div>
@@ -148,7 +154,7 @@
                       placeholder="이메일 형식만 입력 가능합니다."
                       autocomplete="off"
                       ng-model="vm.form.defaultValue">
                <div ng-show="customFieldModifyForm.email.$error.pattern" class="help-block form-text text-danger"
                <div ng-if="customFieldModifyForm.email.$error.pattern" class="help-block form-text text-danger"
                     translate="common.invalidEmailFormat">이메일 형식이 맞지 않습니다.
                </div>
@@ -162,7 +168,7 @@
                       placeholder="홈페이지 주소 형식만 입력 가능합니다."
                       autocomplete="off"
                       ng-model="vm.form.defaultValue">
                <div ng-show="customFieldModifyForm.site.$error.pattern" class="help-block form-text text-danger"
                <div ng-if="customFieldModifyForm.site.$error.pattern" class="help-block form-text text-danger"
                     translate="common.invalidSiteFormat">홈페이지 주소 형식이 맞지 않습니다.(http://로 시작하셔야합니다)
                </div>
@@ -176,19 +182,23 @@
                       placeholder="연락처 형식만 입력 가능합니다."
                       autocomplete="off"
                       ng-model="vm.form.defaultValue">
                <div ng-show="customFieldModifyForm.tel.$error.pattern" class="help-block form-text text-danger"
                <div ng-if="customFieldModifyForm.tel.$error.pattern" class="help-block form-text text-danger"
                     translate="common.invalidTelFormat">전화번호 형식이 맞지 않습니다.
                </div>
                <small ng-show="customFieldModifyForm.defaultValue.$error.maxlength"
                       class="help-block form-text text-danger" translate="common.upTo100Characters">
<!--                <small ng-if="customFieldModifyForm.defaultValue.$error.maxlength"-->
<!--                       class="help-block form-text text-danger" translate="common.upTo100Characters">-->
<!--                    최대 100글자까지 입력할 수 있습니다.-->
<!--                </small>-->
                <small ng-if="vm.form.customFieldType == 'INPUT'" translate="common.upTo100Characters">
                    최대 100글자까지 입력할 수 있습니다.
                </small>
                <div class="help-block form-text text-danger" ng-show="vm.form.customFieldType == 'SINGLE_SELECT'"
                <div class="help-block form-text text-danger" ng-if="vm.form.customFieldType == 'SINGLE_SELECT'"
                     translate="customField.selectSingleFieldListHashTag">
                    단일 선택 필드 목록에 있는 값을 기본적으로 선택하고 싶을 때는 해시태그를 사용해야합니다. ex) #대상값
                </div>
                <div class="help-block form-text text-danger" ng-show="vm.form.customFieldType == 'MULTI_SELECT'"
                <div class="help-block form-text text-danger" ng-if="vm.form.customFieldType == 'MULTI_SELECT'"
                     translate="customField.selectMultiFieldListHashTag">
                    다중 선택 필드 목록에 있는 값을 기본적으로 선택하고 싶을 때는 해시태그를 사용해야합니다. ex) #대상값#대상값
                </div>
src/main/webapp/views/issue/issueDetail.html
@@ -254,7 +254,7 @@
                            <!-- 멀티 셀렉트 -->
                            <div ng-switch-when="MULTI_SELECT">
                                <span class="issue-detail-word-break"
                                ng-repeat="useValue in issueCustomField.useValues">{{::useValue.value}}, </span>
                                ng-repeat="useValue in issueCustomField.useValues">{{::useValue.value}}</span>
                                <span ng-if="!$root.isDefined(issueCustomField.useValues)">-</span>
                            </div>