From 61037a004e28c5e508a62f42022d20d6872dc672 Mon Sep 17 00:00:00 2001 From: jhjang <jhjang@maprex.co.kr> Date: 수, 17 11월 2021 11:50:22 +0900 Subject: [PATCH] - 이슈 상세 페이지에 하위 일감 기능 추가 --- src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java | 24 ++++ src/main/java/kr/wisestone/owl/vo/IssueVo.java | 20 ++++ src/main/java/kr/wisestone/owl/web/condition/IssueCondition.java | 8 + src/main/webapp/scripts/components/issue/issue.service.js | 6 + src/main/java/kr/wisestone/owl/repository/IssueRepository.java | 4 src/main/webapp/scripts/app/issue/issueDetail.controller.js | 119 +++++++++++++++++++++++ src/main/java/kr/wisestone/owl/domain/Issue.java | 10 ++ src/main/resources/migration/V1_11__Alter_Table.sql | 2 src/main/java/kr/wisestone/owl/service/IssueService.java | 2 src/main/java/kr/wisestone/owl/web/form/IssueForm.java | 9 + src/main/webapp/i18n/ko/global.json | 10 + src/main/java/kr/wisestone/owl/web/controller/IssueController.java | 10 ++ src/main/webapp/views/issue/issueDetail.html | 50 ++++++++-- src/main/webapp/custom_components/js-table/tableColumnGenerator.directive.js | 12 ++ 14 files changed, 271 insertions(+), 15 deletions(-) diff --git a/src/main/java/kr/wisestone/owl/domain/Issue.java b/src/main/java/kr/wisestone/owl/domain/Issue.java index b9ed37a..c2738c0 100644 --- a/src/main/java/kr/wisestone/owl/domain/Issue.java +++ b/src/main/java/kr/wisestone/owl/domain/Issue.java @@ -101,6 +101,10 @@ @JoinColumn(name = "workflow_status_id") private WorkflowStatus workflowStatus; + @ManyToOne(fetch=FetchType.LAZY) + @JoinColumn(name = "parent_issue_id") + private Issue parentIssue; + public Long getId() { return id; } @@ -321,5 +325,11 @@ this.issueRelations.clear(); } + public Issue getParentIssue() { + return parentIssue; + } + public void setParentIssue(Issue parentIssue) { + this.parentIssue = parentIssue; + } } diff --git a/src/main/java/kr/wisestone/owl/repository/IssueRepository.java b/src/main/java/kr/wisestone/owl/repository/IssueRepository.java index 300b1b2..c5ce0e5 100644 --- a/src/main/java/kr/wisestone/owl/repository/IssueRepository.java +++ b/src/main/java/kr/wisestone/owl/repository/IssueRepository.java @@ -2,6 +2,10 @@ import kr.wisestone.owl.domain.Issue; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.query.Param; + +import java.util.List; public interface IssueRepository extends JpaRepository<Issue, Long> { + List<Issue> findByParentIssueId(@Param("parentIssueId") Long parentIssueId); } diff --git a/src/main/java/kr/wisestone/owl/service/IssueService.java b/src/main/java/kr/wisestone/owl/service/IssueService.java index bbccd25..e3cf2ca 100644 --- a/src/main/java/kr/wisestone/owl/service/IssueService.java +++ b/src/main/java/kr/wisestone/owl/service/IssueService.java @@ -68,4 +68,6 @@ void reservationIssue(); Map<String, Object> findTask(IssueCondition taskCondition); + + void modifyParentIssue(IssueForm issueForm); } diff --git a/src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java b/src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java index 6190016..947aeae 100644 --- a/src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java +++ b/src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java @@ -799,6 +799,7 @@ this.setAttachedFiles(issue, issueVo); // 泥⑤� �뙆�씪 �젙蹂� �뀑�똿 this.setIssueCustomFields(issue, issueVo); // �궗�슜�옄 �젙�쓽 �븘�뱶 媛� �젙蹂� �뀑�똿 this.setRelationIssue(issue, issueVo); //�뿰愿� �씪媛� �뀑�똿 + this.setDownIssues(issue, issueVo); break; @@ -812,6 +813,13 @@ log.info(ElasticSearchUtil.makeUserActiveHistoryMessage(this.webAppUtil.getLoginUser(), ElasticSearchConstants.ISSUE_DETAIL)); resJsonData.put(Constants.RES_KEY_CONTENTS, issueVo); + } + + // �븯�쐞 �씠�뒋 �젙蹂대�� �뀑�똿�븳�떎 + private void setDownIssues(Issue issue, IssueVo issueVo) { + List<Issue> downIssues = this.issueRepository.findByParentIssueId(issue.getId()); + List<IssueVo> issueVos = ConvertUtil.convertObjectsToClasses(downIssues, IssueVo.class); + issueVo.setIssueDownVos(issueVos); } // �씠�뒋 �긽�꽭 �젙蹂대�� �뀑�똿�븳�떎. @@ -833,6 +841,7 @@ this.setIssueComments(issue, issueVo); // �뙎湲� �젙蹂� �뀑�똿 this.setIssueHistory(issue, issueVo); // �씠�뒋 湲곕줉 �젙蹂� �뀑�똿 this.setRelationIssue(issue, issueVo); //�뿰愿� �씪媛� �뀑�똿 + this.setDownIssues(issue, issueVo); } // �벑濡앹옄 �젙蹂� 異붽� @@ -2513,4 +2522,19 @@ return tasks; } + + @Transactional + @Override + public void modifyParentIssue(IssueForm issueForm) { + Issue issue = this.issueRepository.getOne(issueForm.getId()); + Long parentIssueId = issueForm.getParentIssueId(); + if (parentIssueId != null) { + Issue parentIssue = this.issueRepository.getOne(parentIssueId); + issue.setParentIssue(parentIssue); + } else { + issue.setParentIssue(null); + } + + this.issueRepository.saveAndFlush(issue); + } } diff --git a/src/main/java/kr/wisestone/owl/vo/IssueVo.java b/src/main/java/kr/wisestone/owl/vo/IssueVo.java index 8d4b6a4..bf9803c 100644 --- a/src/main/java/kr/wisestone/owl/vo/IssueVo.java +++ b/src/main/java/kr/wisestone/owl/vo/IssueVo.java @@ -44,11 +44,13 @@ private List<IssueTypeCustomFieldVo> issueTypeCustomFieldVos = Lists.newArrayList(); private List<IssueCustomFieldValueVo> issueCustomFieldValueVos = Lists.newArrayList(); private List<IssueRelationVo> issueRelations = Lists.newArrayList(); + private List<IssueVo> issueDownVos = Lists.newArrayList(); private List<IssueVo> issueRelationVos = Lists.newArrayList(); private Long attachedFileCount; private Long issueCommentCount; private String modifyByName; // 蹂�寃쎌옄 �젙蹂� - �씠�뒋 蹂�寃� �젙蹂� �긽�꽭 �솗�씤�뿉�꽌 �궗�슜 private WorkflowStatusVo workflowStatusVo; + private Long parentIssueId; // �긽�쐞 �씪媛� public IssueVo(){} @@ -379,4 +381,22 @@ public void setDepartmentVos(List<DepartmentVo> departmentVos) { this.departmentVos = departmentVos; } + + public Long getParentIssueId() { + return parentIssueId; + } + + public void setParentIssueId(Long parentIssueId) { + this.parentIssueId = parentIssueId; + } + + public List<IssueVo> getIssueDownVos() { + return issueDownVos; + } + + public void setIssueDownVos(List<IssueVo> issueDownVos) { + this.issueDownVos = issueDownVos; + } + + } diff --git a/src/main/java/kr/wisestone/owl/web/condition/IssueCondition.java b/src/main/java/kr/wisestone/owl/web/condition/IssueCondition.java index 9c40ce3..adaf960 100644 --- a/src/main/java/kr/wisestone/owl/web/condition/IssueCondition.java +++ b/src/main/java/kr/wisestone/owl/web/condition/IssueCondition.java @@ -33,6 +33,7 @@ private Long workspaceId; private String projectType; private String deep; + private Long parentIssueId; // �긽�쐞 �씪媛� private List<Long> projectIds = Lists.newArrayList(); private List<Long> issueStatusIds = Lists.newArrayList(); private List<Long> issueTypeIds = Lists.newArrayList(); @@ -406,4 +407,11 @@ this.excludeIds = excludeIds; } + public Long getParentIssueId() { + return parentIssueId; + } + + public void setParentIssueId(Long parentIssueId) { + this.parentIssueId = parentIssueId; + } } diff --git a/src/main/java/kr/wisestone/owl/web/controller/IssueController.java b/src/main/java/kr/wisestone/owl/web/controller/IssueController.java index 7639f38..3f405ff 100644 --- a/src/main/java/kr/wisestone/owl/web/controller/IssueController.java +++ b/src/main/java/kr/wisestone/owl/web/controller/IssueController.java @@ -88,6 +88,16 @@ return this.setSuccessMessage(resJsonData); } + // �븯�쐞 �씠�뒋 異붽� + @RequestMapping(value = "/issue/modifyParentIssue", produces = MediaType.APPLICATION_JSON_VALUE) + public + @ResponseBody + Map<String, Object> modifyParentIssue(@RequestBody Map<String, Map<String, Object>> params) { + Map<String, Object> resJsonData = new HashMap<>(); + this.issueService.modifyParentIssue(IssueForm.make(params.get(Constants.REQ_KEY_CONTENT))); + return this.setSuccessMessage(resJsonData); + } + // �씠�뒋 �궘�젣 @RequestMapping(value = "/issue/remove", produces = MediaType.APPLICATION_JSON_VALUE) public diff --git a/src/main/java/kr/wisestone/owl/web/form/IssueForm.java b/src/main/java/kr/wisestone/owl/web/form/IssueForm.java index 094aed4..1350967 100644 --- a/src/main/java/kr/wisestone/owl/web/form/IssueForm.java +++ b/src/main/java/kr/wisestone/owl/web/form/IssueForm.java @@ -40,6 +40,7 @@ private Long companyId; //�뾽泥댄븘�뱶 private Long ispId; //ISP�븘�뱶 private Long hostingId; //�샇�뒪�똿�븘�뱶 + private Long parentIssueId; // �긽�쐞 �씠�뒋 public IssueForm() { } @@ -312,4 +313,12 @@ public void setHostingId(Long hostingId) { this.hostingId = hostingId; } + + public Long getParentIssueId() { + return parentIssueId; + } + + public void setParentIssueId(Long parentIssueId) { + this.parentIssueId = parentIssueId; + } } diff --git a/src/main/resources/migration/V1_11__Alter_Table.sql b/src/main/resources/migration/V1_11__Alter_Table.sql index dd41b81..caf331d 100644 --- a/src/main/resources/migration/V1_11__Alter_Table.sql +++ b/src/main/resources/migration/V1_11__Alter_Table.sql @@ -127,3 +127,5 @@ -- �씠�뒋 ���엯 �봽濡쒖젥�듃 ALTER TABLE `issue_type` ADD COLUMN `project_id` BIGINT(11) NULL; +-- �긽�쐞 �씠�뒋 +ALTER TABLE `issue` ADD COLUMN `parent_issue_id` BIGINT(11) NULL; diff --git a/src/main/webapp/custom_components/js-table/tableColumnGenerator.directive.js b/src/main/webapp/custom_components/js-table/tableColumnGenerator.directive.js index 960fd55..7e68f05 100644 --- a/src/main/webapp/custom_components/js-table/tableColumnGenerator.directive.js +++ b/src/main/webapp/custom_components/js-table/tableColumnGenerator.directive.js @@ -199,9 +199,14 @@ break; - // �뿰愿��씪媛� �씠�룞 + // �뿰愿� �씪媛� �씠�룞 case "ISSUE_RELATION_MOVE" : makeTag += "<span class=\"titlename cursor\" ng-click=\"event.changeDetailView(data.issueRelation)\">" + scope.data.title + "</span></a>"; + break; + + // �뿰愿� �씪媛� �씠�룞 + case "ISSUE_DOWN_MOVE" : + makeTag += "<span class=\"titlename cursor\" ng-click=\"event.changeDetailView(data.id)\">" + scope.data.title + "</span></a>"; break; // �뿰愿��씪媛� 援щ텇 @@ -214,6 +219,11 @@ makeTag += '<img class="cursor" src="/assets/images/delete-icon.png" ng-click="event.removeRelationIssue(data.id)">'; break; + // �븯�쐞 �씪媛� �궘�젣 + case "ISSUE_DOWN_DELETE": + makeTag += '<img class="cursor" src="/assets/images/delete-icon.png" ng-click="event.removeDownIssue(data.id)">'; + break; + // �씠由꾩쓣 �겢由��븯硫� �닔�젙 �뙘�뾽 �몴�떆 case "COMMON_MODIFY" : if (scope.data.modifyPermissionCheck) { diff --git a/src/main/webapp/i18n/ko/global.json b/src/main/webapp/i18n/ko/global.json index 3c185a4..c77f156 100644 --- a/src/main/webapp/i18n/ko/global.json +++ b/src/main/webapp/i18n/ko/global.json @@ -293,7 +293,15 @@ "normalList" : "�씠�뒋 紐⑸줉", "timeLine" : "���엫 �씪�씤", "useProjects" : "�궗�슜 �봽濡쒖젥�듃", - "companyInfo" : "�뾽泥�/ISP/�샇�뒪�똿" + "companyInfo" : "�뾽泥�/ISP/�샇�뒪�똿", + "downIssue": "�븯�쐞 �씠�뒋", + "downIssueTitle": "�븯�쐞 �씠�뒋 �젣紐�", + "downIssueType": "�븯�쐞 �씠�뒋 援щ텇", + "addDownIssue": "�븯�쐞 �씠�뒋 異붽�", + "downIssueRemove" : "�븯�쐞 �씠�뒋 �궘�젣", + "failedToIssueAddIssueDown": "�븯�쐞 �씠�뒋 異붽� �떎�뙣", + "failedToIssueDeleteIssueDown": "�븯�쐞 �씠�뒋 �궘�젣 �떎�뙣", + "errorSelectDownIssue" : "�븯�쐞 �씠�뒋媛� �꽑�깮�릺吏� �븡�븯�뒿�땲�떎." }, "project": { "createProject": "�봽濡쒖젥�듃 留뚮뱾湲�", diff --git a/src/main/webapp/scripts/app/issue/issueDetail.controller.js b/src/main/webapp/scripts/app/issue/issueDetail.controller.js index f8c07f3..1eee581 100644 --- a/src/main/webapp/scripts/app/issue/issueDetail.controller.js +++ b/src/main/webapp/scripts/app/issue/issueDetail.controller.js @@ -32,6 +32,7 @@ $scope.fn.reservation = reservation; // �삁�빟 �젙蹂대�� �솗�씤 諛� 蹂�寃� �븳�떎. $scope.fn.getIssueListCallBack = getIssueListCallBack; $scope.fn.addRelationIssue = addRelationIssue; // �뿰愿� �씠�뒋 異붽� + $scope.fn.addDownIssue = addDownIssue; // �븯�쐞 �씠�뒋 異붽� // �씠�뒋 紐⑸줉 而⑦듃濡ㅻ윭 vm, fn �긽�냽 以� @@ -61,10 +62,20 @@ $scope.vm.relationIssueType = $scope.vm.relationIssueTypes[0]; $scope.vm.form = { - issues : [] + issues : [], //�뿰愿� �씪媛� + issuesDown : [] // �븯�쐞 �씪媛� }; - $scope.vm.issueName = ""; + + $scope.vm.issueNameDown = ""; // �꽑�깮�맂 �븯�쐞 �씪媛� �씠由� + $scope.vm.autoCompletePageDown = { + issue : { + page : 0, + totalPage : 0 + }, + }; + + $scope.vm.issueName = ""; // �꽑�깮�맂 �뿰愿� �씪媛� �씠由� $scope.vm.autoCompletePage = { issue : { page : 0, @@ -80,10 +91,60 @@ changeDetailView : changeDetailView }; + $scope.vm.downResponseData = []; + $scope.vm.downTableConfigs = []; + // �뀒�씠釉� �씠踰ㅽ듃 + $scope.downTableEvent = { + removeDownIssue : removeDownIssue, // �뿰愿� �씪媛� �궘�젣 + changeDetailView : changeDetailView + }; + function changeDetailView(issue) { // �씠�뒋 踰덊샇瑜� ���옣�븳 �썑 �씠�뒋 紐⑸줉�쑝濡� �씠�룞�븳�떎. // $rootScope.$broadcast("makeIssueSearch", issue); $scope.$parent.tableEvent.changeDetailView(issue.id); + } + + // �븯�쐞 �씪媛� �궘�젣 + function removeDownIssue(id) { + // �궘�젣 �븣由� + SweetAlert.swal({ + title : $filter("translate")("issue.downIssueRemove"), // �뿰愿� �씪媛� �궘�젣 + text : $filter("translate")("issue.wantToDeleteSelectIssue"), + type : "warning", + showCancelButton : true, + confirmButtonColor : "#DD6B55", + confirmButtonText : $filter("translate")("common.delete"), // �궘�젣 + cancelButtonText : $filter("translate")("common.cancel"), // 痍⑥냼 + closeOnConfirm : false, + closeOnCancel : true + }, + function (isConfirm) { + SweetAlert.close(); + + if (isConfirm) { + $rootScope.spinner = true; + + var contents = { + id : id + }; + + Issue.modifyParentIssue($resourceProvider.getContent( + contents, + $resourceProvider.getPageContent(0, 10))).then(function (result) { + + if (result.data.message.status === "success") { + $scope.fn.getIssueDetail(); + } + else { + SweetAlert.error($filter("translate")("issue.failedToIssueDeleteIssueDown"), result.data.message.message); // "�뿰愿��씪媛� �궘�젣 �떎�뙣" + } + $rootScope.spinner = false; + }); + } + }); + + } // �뿰愿� �씪媛� �궘�젣 @@ -133,7 +194,25 @@ $scope.vm.autoCompletePage.issue.totalPage = result.data.page.totalPage; } - // �씠�뒋 �뀒�씠釉� �꽕�젙 + // �븯�쐞 �씠�뒋 �뀒�씠釉� �꽕�젙 + function makeTableConfigsDown() { + $scope.vm.downTableConfigs = []; + $scope.vm.downTableConfigs.push($tableProvider.config() + .setHName("issue.downIssueTitle") + .setDType("renderer") + .setHWidth("width-60 bold") + .setHSort(false) + .setDRenderer("ISSUE_DOWN_MOVE")) + $scope.vm.downTableConfigs.push($tableProvider.config() + .setHName("issue.relationIssueDelete") + .setDType("renderer") + .setHWidth("width-10 bold") + .setDRenderer("ISSUE_DOWN_DELETE") + .setHSort(false) + .setDAlign("text-center")) + } + + // �뿰愿� �씠�뒋 �뀒�씠釉� �꽕�젙 function makeTableConfigs() { $scope.vm.relTableConfigs = []; $scope.vm.relTableConfigs.push($tableProvider.config() @@ -175,6 +254,32 @@ // } // }); // } + + // �븯�쐞 �씠�뒋 異붽� + function addDownIssue() { + if ($scope.vm.issueNameDown.length == 0 || $scope.vm.form.issuesDown.length == 0 + || $scope.vm.issueNameDown != $scope.vm.form.issuesDown[0].title) { + SweetAlert.error($filter("translate")("issue.errorSelectDownIssue"), ""); + return; + } + + var contents = { + id : $scope.vm.form.issuesDown[0].id, + parentIssueId : $rootScope.currentDetailIssueId + }; + + Issue.modifyParentIssue($resourceProvider.getContent( + contents, + $resourceProvider.getPageContent(0, 10))).then(function (result) { + + if (result.data.message.status === "success") { + $scope.fn.getIssueDetail(); + } + else { + SweetAlert.error($filter("translate")("issue.failedToIssueAddIssueDown"), result.data.message.message); // "�뿰愿��씪媛� �깮�꽦 �떎�뙣" + } + }); + } // �뿰愿� �씠�뒋 異붽� @@ -316,6 +421,8 @@ $scope.vm.issueName = ""; $scope.vm.form.issues = []; $scope.vm.form.issues.push(result.data.data); + $scope.vm.form.issuesDown = []; + $scope.vm.form.issuesDown.push(result.data.data); makeTableConfigs(); angular.forEach(result.data.data.issueRelationVos, function (issueRelationVo){ @@ -323,7 +430,13 @@ $scope.vm.form.issues.push(issueRelationVo.issueRelation); }); + makeTableConfigsDown(); + angular.forEach(result.data.data.issueDownVos, function (issueDownVo){ + $scope.vm.form.issuesDown.push(issueDownVo.issue); + }); + $scope.vm.viewer.issueRelationVos = result.data.data.issueRelationVos; + $scope.vm.viewer.issueDownVos = result.data.data.issueDownVos; } } else { diff --git a/src/main/webapp/scripts/components/issue/issue.service.js b/src/main/webapp/scripts/components/issue/issue.service.js index f987fad..1c48a72 100644 --- a/src/main/webapp/scripts/components/issue/issue.service.js +++ b/src/main/webapp/scripts/components/issue/issue.service.js @@ -44,6 +44,12 @@ return response; }); }, + modifyParentIssue : function (conditions) { + return $http.post("issue/modifyParentIssue", conditions).then(function (response) { + $log.debug("�긽�쐞 �씪媛� �닔�젙 寃곌낵 : ", response); + return response; + }); + }, modify : function (conditions) { conditions.url = "issue/modify"; return $upload.upload(conditions).progress(function (evt) { diff --git a/src/main/webapp/views/issue/issueDetail.html b/src/main/webapp/views/issue/issueDetail.html index 89d3763..fc2bf5d 100644 --- a/src/main/webapp/views/issue/issueDetail.html +++ b/src/main/webapp/views/issue/issueDetail.html @@ -1,10 +1,12 @@ +<!-- �씠�뒋 紐⑸줉 --> +<!-- <div class="support-tickets"> <div class="support-tickets-header"> -<!-- <div class="tickets-control">--> -<!-- <h5 translate="issue.issueList">--> -<!-- �씠�뒋 紐⑸줉--> -<!-- </h5>--> -<!-- </div>--> + <div class="tickets-control"> + <h5 translate="issue.issueList"> + �씠�뒋 紐⑸줉 + </h5> + </div> <div class="tickets-filter"> <div class="dataTables_length"> @@ -50,8 +52,9 @@ </div> </div> - - <!-- �뀒�씠釉� --> +--> + <!-- �뀒�씠釉� --> +<!-- <div class="support-ticket "> <div class="st-body"> <div class="table-responsive"> @@ -60,8 +63,9 @@ </div> </div> </div> - +--> <!-- �럹�씠吏� --> +<!-- <div class="controls-below-table text-center"> <ul uib-pagination boundary-links-numbes="true" @@ -78,7 +82,7 @@ </ul> </div> </div> - +--> <!-- �긽�꽭 �솕硫� --> <div class="support-ticket-content-w" ng-controller="issueDetailController"> <div class="support-ticket-content"> @@ -255,7 +259,6 @@ </div> <h6 class="todo-content-subheader mt-20" translate="issue.relationIssue">�뿰愿� �씪媛�</h6> - <!-- �뀒�씠釉� --> <div class="mt-10 issue-detail-word-break width-100"> <js-table data="vm.viewer.issueRelationVos" table-configs="vm.relTableConfigs" @@ -294,6 +297,33 @@ </div> </div> + <h6 class="todo-content-subheader mt-20" translate="issue.downIssue">�븯�쐞 �씪媛�</h6> + <!-- �뀒�씠釉� --> + <div class="mt-10 issue-detail-word-break width-100"> + <js-table data="vm.viewer.issueDownVos" table-configs="vm.downTableConfigs" + event="downTableEvent" detail-view="true" hide-header="false" use-sort="false"></js-table> + + <div class="row"> + <div class="col-sm-6"> + <js-autocomplete-single data-input-name="issue" + selected-model="vm.form.issuesDown" + search="vm.issueNameDown" + source="fn.getIssueList(vm.issueNameDown, vm.form.issuesDown, vm.autoCompletePageDown.issue.page, fn.getIssueListCallBack)" + page="vm.autoCompletePageDown.issue.page" + total-page="vm.autoCompletePageDown.issue.totalPage" + input-disabled="false" + translation-texts="{ empty : 'common.emptyIssue' }" + extra-settings="{ displayProp : 'title' , idProp : 'id', imageable : false, imagePathProp : '', + type : '', maxlength : 200, autoResize : true, stopRemoveBodyEvent : true }"></js-autocomplete-single> + </div> + <div class="col-auto vertical-middle"> + <button type="button" class="btn btn-primary form-control input-sm" + ng-click="fn.addDownIssue()" + translate="issue.addDownIssue">異붽�</button> + </div> + + </div> + </div> <h6 class="todo-content-subheader mt-20" translate="common.content">�궡�슜</h6> <div class="box mt-10 issue-detail-word-break width-100" > -- Gitblit v1.8.0