OWL ITS + 탐지시스템(인터넷 진흥원)
이민희
2021-12-07 dbd041f0d099e863c044197b2755e9e8ef3c3da1
하위 이슈상태 전체변경
2개 파일 추가됨
6개 파일 변경됨
305 ■■■■■ 파일 변경됨
src/main/resources/mybatis/query-template/issueStatus-template.xml 29 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/i18n/ko/global.json 2 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/issue/downIssueModifyStatus.controller.js 165 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/issue/issue.js 2 ●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/app/issue/issueDetail.controller.js 20 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/scripts/main.js 1 ●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/issue/downIssueModifyStatus.html 74 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/webapp/views/issue/issueDetail.html 12 ●●●●● 패치 | 보기 | raw | blame | 히스토리
src/main/resources/mybatis/query-template/issueStatus-template.xml
@@ -3,6 +3,35 @@
<mapper namespace="kr.wisestone.owl.mapper.IssueStatusMapper">
    <!--<select id="find" resultType="java.util.HashMap" parameterType="kr.wisestone.owl.web.condition.IssueStatusCondition">
        SELECT
        DISTINCT i.id as id,
        i.name as name,
        i.color as color,
        i.issue_status_type as issueStatusType,
        CASE i.default_yn WHEN 'Y' THEN 'true' ELSE 'false' END as defaultYn
        FROM
        issue_status i
        INNER JOIN workspace ws on i.workspace_id = ws.id
        WHERE 1=1
        <if test="name != '' and name != null">
            AND i.name like CONCAT('%',#{name},'%')
        </if>
        <choose>
            <when test="issueStatusTypes.size != 0">
                AND i.issue_status_type IN
                <foreach collection="issueStatusTypes" item="item" index="index" separator="," open="(" close=")">
                    #{item}
                </foreach>
            </when>
        </choose>
        AND ws.id = #{workspaceId}
        ORDER BY i.name DESC
        <if test="page != null and !page.equals('')">
            limit #{pageSize} offset #{page};
        </if>
    </select>-->
    <select id="find" resultType="java.util.HashMap" parameterType="kr.wisestone.owl.web.condition.IssueStatusCondition">
        SELECT
        DISTINCT i.id as id,
src/main/webapp/i18n/ko/global.json
@@ -729,6 +729,7 @@
        "updatableStatus": "변경 가능한 상태",
        "testCase": "테스트 케이스",
        "updateStatus": "상태 변경",
        "updateDownIssueAllStatus": "하위 이슈상태 전체 변경",
        "tcmProject": "테스트 케이스 관리 프로젝트",
        "btsProject": "이슈 관리 프로젝트",
        "projectName": "프로젝트명",
@@ -737,6 +738,7 @@
        "parentProject": "상위 프로젝트",
        "setParticipatingInProject": "프로젝트에 참여하는 사용자를 설정하십시오.",
        "noUpdatedStatus": "변경할 수 있는 상태가 없습니다.",
        "notEqualedStatus": "이슈 상태가 같을 경우에만 전체 변경이 가능합니다.",
        "wait": "대기",
        "progress": "진행",
        "end": "종료",
src/main/webapp/scripts/app/issue/downIssueModifyStatus.controller.js
New file
@@ -0,0 +1,165 @@
/**
 * Created by wisestone on 2018-11-22.
 */
'use strict';
define([
        'app'
    ],
    function (app) {
        app.controller('downIssueModifyStatusController', ['$scope', '$rootScope', '$log', '$resourceProvider', '$uibModalInstance', 'SweetAlert', '$timeout', '$stateParams', 'parameter',
            'Issue', 'IssueStatus', '$filter', '$injector', '$controller',
            function ($scope, $rootScope, $log, $resourceProvider, $uibModalInstance, SweetAlert, $timeout, $stateParams, parameter, Issue, IssueStatus, $filter, $injector, $controller) {
                //  함수 모음
                $scope.fn = {
                    cancel: cancel,    //  팝업 창 닫기
                    formSubmit: formSubmit,    //  폼 전송
                    formCheck: formCheck,  //  폼 체크
                    findNextMultiIssueStatus: findNextMultiIssueStatus,  //  이동 가능한 이슈 상태를 찾는다.
                    removeDepartment : removeDepartment,     // 담당부서 삭제
                };
                //  변수 모음
                $scope.vm = {
                    issueStatusList: [],   //  변경 가능한 상태 목록
                    form: {
                        departments: [],    // 담당 부서 선택 목록
                        issueStatusId: undefined,
                        comment: ""
                    },
                    departmentName : ""
                };
                angular.extend(this, $controller('autoCompleteController', {$scope : $scope, $injector : $injector}));
                // 담당부서 삭제
                function removeDepartment(index) {
                    $scope.vm.form.departments.splice(index, 1);
                }
                $scope.$watch("vm.form.issueStatusId", function (newValue) {
                    // 이슈 상태별 담당부서 표시
                    let selectIssueStatusId = $scope.vm.form.issueStatusId;
                    let issueStatusList = $scope.vm.issueStatusList;
                    $scope.vm.form.departments = [];
                    if (issueStatusList != null && $scope.vm.issueStatusList.length > 0 && selectIssueStatusId !== "") {
                        for (let i = 0; i < issueStatusList.length; i++) {
                            if (issueStatusList[i].id.toString() === selectIssueStatusId) {
                                let workflowDepartments = issueStatusList[i].workflowDepartmentVos;
                                workflowDepartments.forEach(function (workflowDepartment) {
                                    $scope.vm.form.departments.push(workflowDepartment.departmentVo);
                                });
                                break;
                            }
                        }
                        $scope.vm.issueStatusList.forEach(function (issueStatus) {
                            if (issueStatus.id === $scope.vm.form.issueStatusId) {
                            }
                        });
                    }
                });
                //  이동 가능한 이슈 상태를 찾는다.
                function findNextMultiIssueStatus() {
                    $rootScope.spinner = true;
                    var content = {
                        issueIds : (function () {
                            var issueIds = [];
                            angular.forEach(parameter.downIssues, function (downIssue) {
                                issueIds.push(downIssue.id);
                            });
                            return issueIds;
                        })(),
                    };
                    IssueStatus.findNextMultiIssueStatus($resourceProvider.getContent(
                        content,
                        $resourceProvider.getPageContent(0, 0))).then(function (result) {
                        if (result.data.message.status === "success") {
                            $scope.vm.issueStatusList = result.data.data;
                        } else {
                            SweetAlert.swal($filter("translate")("issue.failedIssueStatusCheck"), result.data.message.message, "error"); // 이동 가능한 이슈 상태 조회 실패
                        }
                        $rootScope.spinner = false;
                    });
                }
                //  폼 전송
                function formCheck(formInvalid) {
                    if (formInvalid) {
                        return true;
                    }
                    return false;
                }
                //  폼 전송
                function formSubmit() {
                    $rootScope.spinner = true;
                    var content = {
                        ids: (function () {
                            var issueIds = [];
                            angular.forEach(parameter.downIssues, function (downIssue) {
                                issueIds.push(downIssue.id);
                            });
                            return issueIds;
                        })(),
                        issueStatusId: $scope.vm.form.issueStatusId,
                        comment: $scope.vm.form.comment,
                        projectId : parameter.projectId,
                        departmentIds : (function () {
                            var departmentIds = [];
                            angular.forEach($scope.vm.form.departments, function (department) {
                                departmentIds.push(department.id);
                            });
                            return departmentIds;
                        })(),
                    };
                    Issue.modifyMultiIssueStatus($resourceProvider.getContent(content,
                        $resourceProvider.getPageContent(0, 0))).then(function (result) {
                        if (result.data.message.status === "success") {
                            $scope.fn.cancel();
                            $rootScope.$broadcast("getIssueList", {});
                            if ($rootScope.isDefined($rootScope.currentDetailIssueId)) {
                                $rootScope.$broadcast("getIssueDetail", {id: $rootScope.currentDetailIssueId});
                            }
                        } else {
                            SweetAlert.error($filter("translate")("issue.failedToChangeMultipleIssueStatus"), result.data.message.message); // 다중 이슈 상태 변경 실패
                        }
                        $rootScope.spinner = false;
                    });
                }
                //  팝업 창 닫기
                function cancel() {
                    $rootScope.$broadcast("closeLayer");    //  팝업이 열리고 나서 js-multi, js-single 등에서 body 이벤트가 날아가는 현상 수정
                    $uibModalInstance.dismiss('cancel');
                    $(document).unbind("keydown");  //  단축키 이벤트 제거
                }
                //  이동 가능한 이슈 상태를 찾는다.
                $scope.fn.findNextMultiIssueStatus();
            }]);
    });
src/main/webapp/scripts/app/issue/issue.js
@@ -36,7 +36,7 @@
                                'issueListTimelineController', 'issueManagerController', 'issueListController', 'issueAddController', 'issueModifyController', 'issueDetailController', 'issueAddRelationController', 'issueImportExcelController',
                                'chartLoader', 'jsTable', 'tableColumnGenerator', 'modalFormAutoScroll', 'summerNote', 'summerNote-ko-KR', 'fullScroll', 'workflowService', 'priorityService', 'issueSearchService', 'issueTableConfigService', 'inputRegex',
                                'severityService', 'issueTypeService', 'issueTypeCustomFieldService', 'issueService', 'issueStatusService', 'issueUserService','issueDepartmentService','issueModifyUserController', 'issueModifyDepartmentController', 'customFieldService', 'issueSearchFieldKeyViewElement',
                                'issueSearchCustomFieldViewElement', 'tableUserImage', 'fullScroll', 'issueCommentService', 'detectIssueEditor', 'formSubmit', 'issueModifyStatusController', 'jsShortCut',
                                'issueSearchCustomFieldViewElement', 'tableUserImage', 'fullScroll', 'issueCommentService', 'detectIssueEditor', 'formSubmit', 'issueModifyStatusController', 'downIssueModifyStatusController', 'jsShortCut',
                                'issueAddTableConfigController','issueAddRelationTableConfigController','issueAddDownTableConfigController','domAppend', 'issueDetailImagePreview', 'issueSendMailPartnersController', 'htmlDiff', 'issueVersionViewController', 'issueVersionService',
                                'jsHtmlDiff', 'issueReservationController', 'issueReservationService', 'issueVersionService', 'issueStatusAutoFocus', 'issueRelationService'
                            ], function () {
src/main/webapp/scripts/app/issue/issueDetail.controller.js
@@ -28,6 +28,7 @@
                $scope.fn.updateActiveHistory = updateActiveHistory;    //  활동 내역에서 전체 보기 탭을 눌렀을 때 댓글, 기록 정보를 업데이트 한다.
                $scope.fn.getChangeIssueStatusList = getChangeIssueStatusList;    //  이슈의 현재 상태에서 변경 가능한 이슈 샅태 목록 가져오기
                $scope.fn.modifyIssueStatus = modifyIssueStatus;    //  이슈 상태 변경
                $scope.fn.modifyDownIssueStatus = modifyDownIssueStatus;    //하위 이슈 상태 변경
                $scope.fn.modifyIssueUser = modifyIssueUser;    //  이슈 담당자 변경
                $scope.fn.modifyIssueDepartment = modifyIssueDepartment;    //  이슈 담당부서 변경
                $scope.fn.initReload = initReload;  //  초기화 해야할 할목을 지정하여 다른 이슈를 클릭할 때 초기화해준다.
@@ -720,6 +721,25 @@
                    });
                }
                function modifyDownIssueStatus() {
                    $uibModal.open({
                        templateUrl : 'views/issue/downIssueModifyStatus.html',
                        size : "md",
                        controller : 'downIssueModifyStatusController',
                        backdrop : 'static',
                        resolve : {
                            parameter : function () {
                                return {
                                    issueTypeId : $scope.vm.viewer.issueTypeVo.id,
                                    issueIds : [$scope.vm.viewer.id],
                                    downIssues : $scope.vm.viewer.issueDownVos,
                                    projectId : $scope.vm.viewer.projectVo.id
                                };
                            }
                        }
                    });
                }
                //  담당자 변경
                function modifyIssueUser() {
                    $uibModal.open({
src/main/webapp/scripts/main.js
@@ -184,6 +184,7 @@
        'issueManagerController' : 'app/issue/issueManager.controller',   //  이슈 관리 컨트롤러
        'issueImportExcelController' : 'app/issue/issueImportExcel.controller',    //  이슈 엑셀 대량 import
        'issueModifyStatusController' : 'app/issue/issueModifyStatus.controller',   //  이슈 다중 상태 변경 컨트롤러
        'downIssueModifyStatusController' : 'app/issue/downIssueModifyStatus.controller',   //  하위 이슈 상태 변경 컨트롤러
        'issueAddTableConfigController' : 'app/issue/issueAddTableConfig.controller',   //  이슈 테이블 설정 컨트롤러
        'issueAddRelationTableConfigController' : 'app/issue/issueAddRelationTableConfig.controller',   //  이슈 테이블 설정 컨트롤러
        'issueAddDownTableConfigController' : 'app/issue/issueAddDownTableConfig.controller',   //  이슈 테이블 설정 컨트롤러
src/main/webapp/views/issue/downIssueModifyStatus.html
New file
@@ -0,0 +1,74 @@
<div class="formModal">
    <div class="modal-header faded smaller">
        <div class="modal-title">
            <strong translate="common.updateIssueStatus">이슈 상태 변경</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="downIssueStatusModifyForm">
            <div class="form-group">
                <label for="downIssueStatusModifyForm1"><span translate="common.updatableStatus">변경 가능한 상태</span> <code
                        class="highlighter-rouge">*</code></label>
                <select id="downIssueStatusModifyForm1"
                        class="form-control"
                        issue-status-auto-focus
                        list="vm.issueStatusList"
                        required
                        ng-model="vm.form.issueStatusId">
                    <option value="" translate="common.selectTarget">대상 선택</option>
                    <option value="{{issueStatus.id}}" ng-repeat="issueStatus in vm.issueStatusList">
                        {{issueStatus.name}}
                    </option>
                </select>
                <div class="help-block form-text text-danger" ng-if="vm.issueStatusList.length < 1"
                     translate="common.notEqualedStatus">
                    이슈 상태가 같을 경우에만 전체 변경이 가능합니다.
                </div>
            </div>
            <div class="form-group mgb5" ng-if="vm.form.issueStatusId !== undefined">
                <label class="issue-label"> <span translate="common.assigneeTeam">담당부서</span> </label>
                <js-autocomplete-multi data-input-name="departments"
                                       selected-model="vm.form.departments"
                                       search="vm.departmentName"
                                       source="fn.getUserDepartmentList(vm.departmentName, vm.form.departments)"
                                       input-disabled="false"
                                       translation-texts="{ count : 'common.userNum', empty : 'common.emptyUser' }"
                                       extra-settings="{ displayProp : 'byName' , 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="department in vm.form.departments">
                                <span>{{department.byName}}</span> <!--사용자가 속해 있는 부서 이름 출력-->
                                <span class="select3-selection__choice__remove" ng-click="fn.removeDepartment($index)">×</span>
                            </span>
                </div>
            </div>
            <div class="form-group">
                <label for="downIssueStatusModifyForm2"><span translate="common.changeReason">변경 사유</span> </label>
                <input class="form-control input-sm"
                       id="downIssueStatusModifyForm2"
                       kr-input
                       autocomplete="off"
                       maxlength="300"
                       ng-model="vm.form.comment"
                       type="text">
            </div>
        </form>
    </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(downIssueStatusModifyForm.$invalid) || $root.spinner) ? null : fn.formSubmit()"
                ng-disabled="fn.formCheck(downIssueStatusModifyForm.$invalid)"
                ng-click="fn.formSubmit()"><span translate="common.save">저장</span>
        </button>
    </div>
</div>
src/main/webapp/views/issue/issueDetail.html
@@ -459,7 +459,7 @@
                        <span class="info_detail_font h3" translate="issue.relationIssue">연관 이슈</span>
                    </div>
                    <div class="col-md-1">
                        <button class="btn btn-darkgrey offset-12" ng-click="fn.addRelationIssueTableConfig()" type="button"><span translate="issue.settingTableDisplay">테이블 표시 설정</span></button>
                        <button class="btn btn-darkgrey offset-10" ng-click="fn.addRelationIssueTableConfig()" type="button"><span translate="issue.settingTableDisplay">테이블 표시 설정</span></button>
                    </div>
                </div>
@@ -505,11 +505,15 @@
                </div>
                <div class="row mt-30">
                    <div class="col-md-10">
                    <div class="col-md-8">
                        <span class="info_detail_font h3" translate="issue.downIssue">하위 이슈</span>
                    </div>
                    <div class="col-md-1">
                        <button class="btn btn-darkgrey offset-12"  ng-click="fn.addDownIssueTableConfig()" type="button"><span translate="issue.settingTableDisplay">테이블 표시 설정</span></button>
                    <div class="col-sm-2">
                        <button type="button" class="btn btn-primary form-control input-sm offset-5" ng-click="fn.modifyDownIssueStatus()"
                                translate="common.updateDownIssueAllStatus">하위이슈 상태 전체 변경</button>
                    </div>
                    <div class="col-sm-1">
                        <button class="btn btn-darkgrey offset-10"  ng-click="fn.addDownIssueTableConfig()" type="button"><span translate="issue.settingTableDisplay">테이블 표시 설정</span></button>
                    </div>
                </div>