From 17a9cb0fc114804ab81cb1eaa2dd5919a0194dd1 Mon Sep 17 00:00:00 2001
From: 이민희 <mhlee@maprex.co.kr>
Date: 목, 09 12월 2021 15:30:55 +0900
Subject: [PATCH] Merge branch 'master' of http://192.168.0.25:9001/r/owl-kisa

---
 src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java              |  121 +++++++------------
 src/main/java/kr/wisestone/owl/vo/IssueVo.java                                 |    9 +
 src/main/webapp/bower_components/bootstrap-daterangepicker/daterangepicker.js  |    2 
 src/main/java/kr/wisestone/owl/web/condition/IssueCondition.java               |   14 ++
 src/main/java/kr/wisestone/owl/common/IssueCustomFieldValueFormComparator.java |   20 +++
 src/main/webapp/scripts/components/utils/dateRangePicker.directive.js          |    5 
 src/main/resources/mybatis/query-template/issue-template.xml                   |   38 +++---
 src/main/java/kr/wisestone/owl/mapper/IssueMapper.java                         |    2 
 src/main/webapp/scripts/app/issue/issueDetail.controller.js                    |   16 +-
 src/main/webapp/views/login/login.html                                         |   33 ++--
 src/main/webapp/views/api/apiSettingSpec.html                                  |   13 +
 src/main/webapp/i18n/ko/global.json                                            |    5 
 src/main/webapp/views/issue/issueDetail.html                                   |    4 
 src/main/webapp/scripts/app/project/projectList.controller.js                  |   22 ---
 src/main/webapp/custom_components/js-table/tableColumnGenerator.directive.js   |   13 -
 src/main/webapp/index.html                                                     |    2 
 src/main/webapp/views/api/apiSetting.html                                      |    7 -
 17 files changed, 164 insertions(+), 162 deletions(-)

diff --git a/src/main/java/kr/wisestone/owl/common/IssueCustomFieldValueFormComparator.java b/src/main/java/kr/wisestone/owl/common/IssueCustomFieldValueFormComparator.java
new file mode 100644
index 0000000..1003fe0
--- /dev/null
+++ b/src/main/java/kr/wisestone/owl/common/IssueCustomFieldValueFormComparator.java
@@ -0,0 +1,20 @@
+package kr.wisestone.owl.common;
+
+import kr.wisestone.owl.web.form.IssueApiForm;
+import kr.wisestone.owl.web.form.IssueCustomFieldValueForm;
+
+import java.util.Comparator;
+
+public class IssueCustomFieldValueFormComparator implements Comparator<IssueCustomFieldValueForm> {
+
+    @Override
+    public int compare(IssueCustomFieldValueForm o1, IssueCustomFieldValueForm o2) {
+        if (o1.getCustomFieldId() > o2.getCustomFieldId()) {
+            return 1;
+        } else if (o1.getCustomFieldId() < o2.getCustomFieldId()) {
+            return -1;
+        } else {
+            return 0;
+        }
+    }
+}
diff --git a/src/main/java/kr/wisestone/owl/mapper/IssueMapper.java b/src/main/java/kr/wisestone/owl/mapper/IssueMapper.java
index 90bbfc6..ece925a 100644
--- a/src/main/java/kr/wisestone/owl/mapper/IssueMapper.java
+++ b/src/main/java/kr/wisestone/owl/mapper/IssueMapper.java
@@ -51,6 +51,6 @@
 
     Long countByDepartment(IssueCondition issueCondition);
 
-    List<Map<String, Object>> findNotCompleteByParentIssueId(Long parentIssueId);
+    List<Map<String, Object>> findNotCompleteByParentIssueId(IssueCondition issueCondition);
 }
 
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 2a11e37..d35c3b3 100644
--- a/src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
+++ b/src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
@@ -3,6 +3,7 @@
 import com.google.common.collect.Lists;
 import com.sun.org.apache.bcel.internal.generic.NEW;
 import kr.wisestone.owl.common.ExcelConditionCheck;
+import kr.wisestone.owl.common.IssueCustomFieldValueFormComparator;
 import kr.wisestone.owl.config.CommonConfiguration;
 import kr.wisestone.owl.constant.Constants;
 import kr.wisestone.owl.constant.ElasticSearchConstants;
@@ -263,11 +264,8 @@
 
             List<IssueVo> issueVos = this.findIssue(issueApiForm, customFieldApiOverlaps, user.getId());
             int size = issueVos.size();
-            if (size == 1) {
+            if (size > 0) {
                 issueForm.setParentIssueId(issueVos.get(0).getId());
-            } else if (size > 1) {
-                throw new OwlRuntimeException(
-                        this.messageAccessor.getMessage(MsgConstants.API_OVERLAP_ERROR));
             }
 
             issueForm.setIsApi(Issue.IS_API_YES);
@@ -328,39 +326,36 @@
     }
 
     // 以묐났�맂 �긽�쐞 �씠�뒋 寃��깋
-    private List<IssueVo> findIssue(IssueApiForm issueApiForm, List<CustomFieldApiOverlap> customFieldApiOverlaps, Long userId) {
+    private List<IssueVo> findIssue(IssueApiForm issueApiform, List<CustomFieldApiOverlap> customFieldApiOverlaps, Long userId) {
+        List<IssueCustomFieldValueForm> issueCustomFieldValueForms = issueApiform.getIssueCustomFieldValues();
+        List<IssueVo> resultIssueVos = Lists.newArrayList();
+        String comma = ",";
 
-        List<IssueVo> resultIssueVos = new ArrayList<>();
+        if (issueCustomFieldValueForms.size() > 0) {
+            String concatUseValue = "";
+            int useIdx = 0;
 
-        if (customFieldApiOverlaps != null && customFieldApiOverlaps.size() > 0) {
-            for (CustomFieldApiOverlap customFieldApiOverlap : customFieldApiOverlaps) {
-                for (IssueCustomFieldValueForm issueCustomFieldValue : issueApiForm.getIssueCustomFieldValues()) {
-                    IssueCustomFieldValueCondition issueCustomFieldValueCondition = new IssueCustomFieldValueCondition();
-                    issueCustomFieldValueCondition.setUseParentIssueId(true);
-                    if (customFieldApiOverlap.getCustomField().getId().equals(issueCustomFieldValue.getCustomFieldId())) {
-                        issueCustomFieldValueCondition.setUseValue(issueCustomFieldValue.getUseValue());
+            IssueCustomFieldValueFormComparator comp = new IssueCustomFieldValueFormComparator();
+            Collections.sort(issueCustomFieldValueForms, comp);
 
-                        List<Map<String, Object>> results = this.issueMapper.findByCustomFieldValue(issueCustomFieldValueCondition);
-                        if (results != null && results.size() > 0) {
-                            List<IssueVo> findIssueVos = new ArrayList<>();
-                            Collections.copy(resultIssueVos, findIssueVos);
-                            resultIssueVos.clear();
-                            for (Map<String, Object> result : results) {
-                                IssueVo issueVo = ConvertUtil.convertMapToClass(result, IssueVo.class);
-                                if (findIssueVos.size() == 0) {
-                                    resultIssueVos.add(issueVo);
-                                } else {
-                                    IssueVo findIssueVo = findIssueVo(findIssueVos, issueVo.getId());
-                                    if (findIssueVo != null) {
-                                        resultIssueVos.add(findIssueVo);
-                                    }
-                                }
-                            }
-                        } else {
-                            resultIssueVos.clear();
-                            return resultIssueVos;
+            for (IssueCustomFieldValueForm issueCustomFieldValueForm : issueCustomFieldValueForms) {
+                for(CustomFieldApiOverlap customFieldApiOverlap : customFieldApiOverlaps) {
+                    if (customFieldApiOverlap.getCustomField().getId().equals(issueCustomFieldValueForm.getCustomFieldId())) {
+                        if (useIdx > 0) {
+                            concatUseValue = concatUseValue.concat(comma);
                         }
+                        concatUseValue = concatUseValue.concat(issueCustomFieldValueForm.getUseValue());
+                        useIdx++;
                     }
+                }
+            }
+
+            IssueCustomFieldValueCondition issueCustomFieldValueCondition = new IssueCustomFieldValueCondition();
+            issueCustomFieldValueCondition.setUseValue(concatUseValue);
+            List<Map<String, Object>> results = this.issueMapper.findByCustomFieldValue(issueCustomFieldValueCondition);
+            if (results != null && results.size() > 0) {
+                for (Map<String, Object> result : results) {
+                    resultIssueVos.add(ConvertUtil.convertMapToClass(result, IssueVo.class));
                 }
             }
         }
@@ -773,6 +768,7 @@
 
         int totalPage = (int) Math.ceil((totalCount - 1) / pageable.getPageSize()) + 1;
         //  �씠�뒋 �븘�씠�뵒 珥덇린�솕
+        issueCondition.setIsApi(issueCondition.getIsApi());
         issueCondition.setIssueIds(Lists.newArrayList());
         //  Map �뿉 �엳�뒗 �뜲�씠�꽣瑜� IssueVo �뜲�씠�꽣濡� 蹂��솚�븳�떎.
         this.setMapToIssueVo(results, issueVos, issueCondition, user);
@@ -1483,42 +1479,25 @@
     public List<IssueVo> findIssue(IssueApiForm issueApiform) {
 
         List<IssueCustomFieldValueForm> issueCustomFieldValueForms = issueApiform.getIssueCustomFieldValues();
-        List<IssueVo> resultIssueVos = new ArrayList<>();
+        List<IssueVo> resultIssueVos = Lists.newArrayList();
+        String comma = ",";
 
-        IssueCustomFieldValueCondition issueCustomFieldValueCondition = new IssueCustomFieldValueCondition();
-        issueCustomFieldValueCondition.setUseParentIssueId(false);
         if (issueCustomFieldValueForms.size() > 0) {
-            for (IssueCustomFieldValueForm issueCustomFieldValueForm : issueCustomFieldValueForms) {
-
-                CustomField customField = this.customFieldService.getCustomField(issueCustomFieldValueForm.getCustomFieldId());
-                CustomFieldType customFieldType = CustomFieldType.DATETIME;
-                if (customFieldType.equals(customField.getCustomFieldType())) {
-                    continue;
+            String concatUseValue = "";
+            for (int i = 0; i < issueCustomFieldValueForms.size(); i++) {
+                IssueCustomFieldValueForm issueCustomFieldValueForm = issueCustomFieldValueForms.get(i);
+                if (i > 0) {
+                    concatUseValue = concatUseValue.concat(comma);
                 }
-//                issueCustomFieldValueCondition.addUseValue(issueCustomFieldValueForm.getUseValue());
-                issueCustomFieldValueCondition.setUseValue(issueCustomFieldValueForm.getUseValue());
-                List<Map<String, Object>> results = this.issueMapper.findByCustomFieldValue(issueCustomFieldValueCondition);
-                if (results != null && results.size() > 0) {
-                    List<IssueVo> findIssueVos = new ArrayList<>();
-                    Collections.copy(resultIssueVos, findIssueVos);
-                    resultIssueVos.clear();
-                    for (Map<String, Object> result : results) {
-                        IssueVo issueVo = ConvertUtil.convertMapToClass(result, IssueVo.class);
+                concatUseValue = concatUseValue.concat(issueCustomFieldValueForm.getUseValue());
+            }
 
-                        issueVo.setParentIssueVo(this.getParentIssueVo(MapUtil.getLong(result, "parentIssueId")));
-
-                        if (findIssueVos.size() == 0) {
-                            resultIssueVos.add(issueVo);
-                        } else {
-                            IssueVo findIssueVo = findIssueVo(findIssueVos, issueVo.getId());
-                            if (findIssueVo != null) {
-                                resultIssueVos.add(findIssueVo);
-                            }
-                        }
-                    }
-                } else {
-                    resultIssueVos.clear();
-                    return resultIssueVos;
+            IssueCustomFieldValueCondition issueCustomFieldValueCondition = new IssueCustomFieldValueCondition();
+            issueCustomFieldValueCondition.setUseValue(concatUseValue);
+            List<Map<String, Object>> results = this.issueMapper.findByCustomFieldValue(issueCustomFieldValueCondition);
+            if (results != null && results.size() > 0) {
+                for (Map<String, Object> result : results) {
+                    resultIssueVos.add(ConvertUtil.convertMapToClass(result, IssueVo.class));
                 }
             }
         }
@@ -1534,15 +1513,6 @@
             }
         }
         return null;
-    }
-
-
-    // �븯�쐞 �씠�뒋媛� 紐⑤몢 醫낅즺 泥섎━ �릺�뿀�쓣 寃쎌슦 �긽�쐞�씠�뒋�룄 �셿猷� 泥섎━
-    private void setParentIssueComplete(Issue parentIssue) {
-        if (parentIssue != null) {
-            this.issueMapper.findNotCompleteByParentIssueId(parentIssue.getId());
-
-        }
     }
 
 
@@ -1570,10 +1540,12 @@
                 }
 
                 if (parentIssue != null) {
-                    List<Map<String, Object>> results = this.issueMapper.findNotCompleteByParentIssueId(parentIssue.getId());
+                    IssueCondition issueCondition = new IssueCondition(issueVo.getId(), parentIssue.getId());
+                    List<Map<String, Object>> results = this.issueMapper.findNotCompleteByParentIssueId(issueCondition);
                     // �븯�쐞 �씪媛먯씠 紐⑤몢 醫낅즺 �긽�깭�씪�븣 �긽�쐞 �씪媛먮룄 醫낅즺 泥섎━
                     if (results == null || results.size() == 0) {
                         parentIssue.setIssueStatus(issueType.getIssueStatus());
+                        this.issueRepository.saveAndFlush(parentIssue);
                     }
                 }
 
@@ -1660,6 +1632,7 @@
             this.issueHistoryService.detectIssueStatus(issue, issueForm, detectIssueChange, oldIssueStatus, issueStatus);
         }
 
+        // db�뿉 ���옣
         issue = this.saveIssue(issueForm, checkIssueData);
 
         //  �씠�뒋 �씠�젰 �벑濡�
diff --git a/src/main/java/kr/wisestone/owl/vo/IssueVo.java b/src/main/java/kr/wisestone/owl/vo/IssueVo.java
index 5ac8406..69600a2 100644
--- a/src/main/java/kr/wisestone/owl/vo/IssueVo.java
+++ b/src/main/java/kr/wisestone/owl/vo/IssueVo.java
@@ -31,6 +31,7 @@
     private Long severityId;
     private String severityName;
     private String severityColor;
+    private String isApi;
     private ProjectVo projectVo;    //  �씠�뒋 �긽�꽭�뿉�꽌 �궗�슜
     private IssueStatusVo issueStatusVo;    //  �씠�뒋 �긽�꽭�뿉�꽌 �궗�슜
     private IssueTypeVo issueTypeVo;    //  �씠�뒋 �긽�꽭�뿉�꽌 �궗�슜
@@ -231,6 +232,14 @@
         this.severityColor = severityColor;
     }
 
+    public String getIsApi() {
+        return isApi;
+    }
+
+    public void setIsApi(String isApi) {
+        this.isApi = isApi;
+    }
+
     public Boolean getModifyPermissionCheck() {
         return modifyPermissionCheck;
     }
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 9ba5dfc..1a29c61 100644
--- a/src/main/java/kr/wisestone/owl/web/condition/IssueCondition.java
+++ b/src/main/java/kr/wisestone/owl/web/condition/IssueCondition.java
@@ -34,6 +34,7 @@
     private Long workspaceId;
     private String projectType;
     private String deep;
+    private String isApi;
     private Long parentIssueId;     // �긽�쐞 �씪媛�
     private String useValue;
     private List<Long> projectIds = Lists.newArrayList();
@@ -55,6 +56,11 @@
     private Boolean hideIssue;
 
     public IssueCondition(){}
+
+    public IssueCondition(Long issueId, Long parentIssueId){
+        this.id = issueId;
+        this.parentIssueId = parentIssueId;
+    }
     //  ���떆蹂대뱶 �쐞湲곌�由� �쐞�젽�뿉�꽌 �궗�슜
     public IssueCondition(List<String> issueIds){
         this.issueIds = issueIds;
@@ -301,6 +307,14 @@
         this.deep = deep;
     }
 
+    public String getIsApi() {
+        return isApi;
+    }
+
+    public void setIsApi(String isApi) {
+        this.isApi = isApi;
+    }
+
     public List<Long> getProjectIds() {
         return projectIds;
     }
diff --git a/src/main/resources/mybatis/query-template/issue-template.xml b/src/main/resources/mybatis/query-template/issue-template.xml
index 5479d53..6df1c93 100644
--- a/src/main/resources/mybatis/query-template/issue-template.xml
+++ b/src/main/resources/mybatis/query-template/issue-template.xml
@@ -15,6 +15,7 @@
         issue.complete_date as completeDate,
         issue.issue_number as issueNumber,
         issue.register_date as registerDate,
+        issue.is_api as isApi,
         SUBSTRING(issue.modify_date, 1, 19) as modifyDate,
         project.id as projectId,
         project.name as projectName,
@@ -965,8 +966,6 @@
                     AND is_api = #{isApi};
     </select>
 
-
-
     <!--    �씠�뒋 �긽�깭瑜� �궗�슜�븯�뒗 �씠�뒋 媛��닔瑜� 議고쉶�븳�떎. -->
     <select id="countByIssueStatusId" resultType="java.lang.Long" parameterType="java.lang.Long">
         SELECT COUNT(DISTINCT id) FROM
@@ -977,29 +976,32 @@
     <!--    �듅�젙 �궗�슜�옄 �젙�쓽 �븘�뱶 媛믪씠 媛숈� �씠�뒋瑜� 議고쉶 -->
     <select id="findByCustomFieldValue" resultType="java.util.HashMap" parameterType="kr.wisestone.owl.web.condition.IssueCustomFieldValueCondition">
         SELECT
-        issue_custom.issue_id as id,
-        iss.parent_issue_id as parentIssueId
-        FROM issue_custom_field_value issue_custom
-        INNER JOIN issue iss ON iss.id = issue_custom.issue_id
-        WHERE 1=1
-        AND issue_custom.use_value = #{useValue}
-        <choose>
-          <when test="useParentIssueId.equals(true)">
-              AND iss.parent_issue_id IS NULL
-          </when>
-          <otherwise>
-              AND iss.parent_issue_id IS NOT NULL
-          </otherwise>
-        </choose>
+            issue.id as id,
+            issue.title as title,
+            customFieldValue.customFieldType AS customFieldType,
+            GROUP_CONCAT(customFieldValue.useValue) AS concatUseValue
+        FROM issue issue FORCE INDEX(reverseIndex)
+        INNER JOIN issue_status as issStatus ON issue.issue_status_id = issStatus.id
+        LEFT OUTER JOIN (
+            SELECT cf.id AS customFieldId, cf.custom_field_type AS customFieldType, issue_custom.use_value AS useValue, issue_custom.issue_id AS issueId
+            FROM issue_custom_field_value issue_custom
+            INNER JOIN custom_field cf ON cf.id = issue_custom.custom_field_id
+            ORDER BY issue_custom.id ASC) customFieldValue ON customFieldValue.issueId = issue.id
+        WHERE issStatus.issue_status_type != 'CLOSE'
+        GROUP BY issue.id
+        HAVING concatUseValue LIKE CONCAT('%', #{useValue}, '%')
     </select>
 
+
     <!--  醫낅즺 �븞�맂 �븯�쐞 �씠�뒋 媛��졇�삤湲� -->
-    <select id="findNotCompleteByParentIssueId" resultType="java.util.HashMap" parameterType="java.lang.Long">
+    <select id="findNotCompleteByParentIssueId" resultType="java.util.HashMap" parameterType="kr.wisestone.owl.web.condition.IssueCondition">
         SELECT
-        iss.id as id
+        iss.id as id,
+        iss.title as title
         FROM issue iss
         INNER JOIN issue_status issueStatus on iss.issue_status_id = issueStatus.id
         WHERE iss.parent_issue_id = #{parentIssueId}
+        AND iss.id != #{id}
         AND issueStatus.issue_status_type != 'CLOSE'
     </select>
 </mapper>
diff --git a/src/main/webapp/bower_components/bootstrap-daterangepicker/daterangepicker.js b/src/main/webapp/bower_components/bootstrap-daterangepicker/daterangepicker.js
index 764f07e..7d0f7cd 100644
--- a/src/main/webapp/bower_components/bootstrap-daterangepicker/daterangepicker.js
+++ b/src/main/webapp/bower_components/bootstrap-daterangepicker/daterangepicker.js
@@ -108,7 +108,7 @@
                       '<i class="fa fa-calendar glyphicon glyphicon-calendar"></i>' +
                       '<div class="calendar-time">' +
                         '<div></div>' +
-                        '<i class="fa fa-clock-o glyphicon glyphicon-time"></i>' +
+                        '<i class="fa fa-clock-o glyphicon glyphicon-time" style="position: relative; left:12.3rem; bottom: 1.23rem "></i>' +
                       '</div>' +
                     '</div>' +
                     '<div class="calendar-table"></div>' +
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 136f3c5..beb4f8c 100644
--- a/src/main/webapp/custom_components/js-table/tableColumnGenerator.directive.js
+++ b/src/main/webapp/custom_components/js-table/tableColumnGenerator.directive.js
@@ -75,13 +75,9 @@
                                         //  �봽濡쒖젥�듃 �씠由�(�봽濡쒖젥�듃 由ъ뒪�듃�뿉�꽌 �궗�슜)
                                         case "PROJECT_NAME" :
                                             if ($rootScope.workProject != null && $rootScope.workProject.id == scope.data.id) {
-                                                // makeTag += "<span class='titlenameSelect cursor table-word-break-all sub-line' ng-click='event.changeLastProject(data.id)'>" + myToken + scope.data.name.replace(/</gi, '&lt;') + "</span>";
-                                                makeTag += "<span class='titlenameSelect cursor table-word-break-all sub-line' ng-click='event.moveIssue(data.id)'>" + myToken + scope.data.name.replace(/</gi, '&lt;') + "</span>";
-                                                // makeTag += "<span class='titlenameSelect cursor table-word-break-all sub-line' ng-click='event.changeDetailView(data.id)'>" + myToken + scope.data.name.replace(/</gi, '&lt;') + "</span>";
+                                                makeTag += "<span class='titlenameSelect cursor table-word-break-all sub-line' ng-click='event.changeLastProject(data.id)'>" + myToken + scope.data.name.replace(/</gi, '&lt;') + "</span>";
                                             } else {
-                                                // makeTag += "<span class='titlename cursor table-word-break-all sub-line' ng-click='event.changeLastProject(data.id)'>" + myToken + scope.data.name.replace(/</gi, '&lt;') + "</span>";
-                                                makeTag += "<span class='titlename cursor table-word-break-all sub-line' ng-click='event.moveIssue(data.id)'>" + myToken + scope.data.name.replace(/</gi, '&lt;') + "</span>";
-                                                // makeTag += "<span class='titlename cursor table-word-break-all sub-line' ng-click='event.changeDetailView(data.id)'>" + myToken + scope.data.name.replace(/</gi, '&lt;') + "</span>";
+                                                makeTag += "<span class='titlename cursor table-word-break-all sub-line' ng-click='event.changeLastProject(data.id)'>" + myToken + scope.data.name.replace(/</gi, '&lt;') + "</span>";
                                             }
                                             break;
 
@@ -306,7 +302,6 @@
 
                                         // �븯�쐞 �씠�뒋 �씠�룞(�젣紐�)
                                         case "ISSUE_DOWN_MOVE" :
-
                                             makeTag += "<span class=\"titlename cursor\" ng-click=\"event.changeDetailView(data)\">" + scope.data.title + "</span></a>";
                                             break;
 
@@ -429,8 +424,8 @@
                                             makeTag += '<span class="number-tag">' + scope.data.projectKey + ' - ' + scope.data.issueNumber + '</span>';
                                             makeTag += ' <span class="tag"> / </span> ';
                                             makeTag += "<span class='badge' ng-style='{ \"background-color\" : \"" + scope.data.issueStatusColor + "\"," + "\"border-color\"" + " : \"" + scope.data.issueStatusColor + "\", \"color\": \"#FFFFFF\" }'>" + scope.data.issueStatusName + "</span>";
-                                            // makeTag += ' <span class="tag"> / </span> ';
-                                            // makeTag += '<span class="tag">' + scope.data.projectName + '</span>';
+                                            makeTag += '<span class="tag"> &nbsp;/ </span> ';
+                                            makeTag += '<span class="tag">' +'<span>API:&nbsp;</span>' + scope.data.isApi + '</span>';
                                             makeTag += '</div>';
                                             makeTag += '<div class="titlename cursor text-left" ng-click="event.changeDetailView(data.id)">' + scope.data.title.replace(/</gi, '&lt;') + '</div>';
                                             makeTag += '<div class="extra-infodiv text-left">';
diff --git a/src/main/webapp/i18n/ko/global.json b/src/main/webapp/i18n/ko/global.json
index 3c091ba..af1d697 100644
--- a/src/main/webapp/i18n/ko/global.json
+++ b/src/main/webapp/i18n/ko/global.json
@@ -888,12 +888,13 @@
         "failedToApiMonitor": "API 湲곕줉 議고쉶 �떎�뙣",
         "requestSample": "API �슂泥� �깦�뵆",
         "requestSampleAdd": "�씠�뒋 異붽�",
-        "requestSampleModify": "�씠�뒋 �닔�젙",
+        "requestSampleModify": "�씠�뒋 �긽�깭 �닔�젙",
         "downIssueOverlapSetting" : "�븯�쐞 �씠�뒋 泥섎━ 湲곗� �빆紐�",
         "upIssueCompleteIssueStatus" : "�긽�쐞 �씠�뒋 �옄�룞醫낅즺 �씠�뒋 �긽�깭 �꽕�젙",
         "autoCompleteIssueStatus" : "�옄�룞 醫낅즺 �꽕�젙�븷 �씠�뒋 �긽�깭",
         "successToApiAutoCompleteIssueStatus" : "�옄�룞 醫낅즺 �씠�뒋 �긽�깭 �꽕�젙 �셿猷�",
-        "failedToApiAutoCompleteIssueStatus" : "�옄�룞 醫낅즺 �씠�뒋 �긽�깭 �꽕�젙 �떎�뙣"
+        "failedToApiAutoCompleteIssueStatus" : "�옄�룞 醫낅즺 �씠�뒋 �긽�깭 �꽕�젙 �떎�뙣",
+        "requestSampleModifyDesc" : "(�닔�젙�떆 customField �빆紐⑹� 寃��깋 �슜�룄濡� �궗�슜�맖)"
     },
     "companyField" : {
         "info": "�뾽泥댁젙蹂�",
diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html
index e8de587..55ba8ba 100644
--- a/src/main/webapp/index.html
+++ b/src/main/webapp/index.html
@@ -21,7 +21,7 @@
     <meta name="google-site-verification" content="yhmSp9Zsw5oecXjp43Ndu0w9rBA3FNpnNZ8bQFA_iDA"/>
     <meta name="viewport" content="user-scalable=no,initial-scale=1,maximum-scale=1">
 
-    <title>OWL ITS</title>
+    <title>�깘吏��젙蹂� �넻�빀愿�由�</title>
 
     <link type="text/css" rel="stylesheet" href="bower_components/font-awesome/css/font-awesome.css">
     <link type="text/css" rel="stylesheet" href="bower_components/jquery-ui/themes/base/jquery-ui.css">
diff --git a/src/main/webapp/scripts/app/issue/issueDetail.controller.js b/src/main/webapp/scripts/app/issue/issueDetail.controller.js
index 4c97ae7..b7e8b5c 100644
--- a/src/main/webapp/scripts/app/issue/issueDetail.controller.js
+++ b/src/main/webapp/scripts/app/issue/issueDetail.controller.js
@@ -50,6 +50,7 @@
                 $scope.fn.setDownTableConfigs = setDownTableConfigs;
                 $scope.fn.containsPartner = containsPartner;
                 $scope.fn.onActivate = onActivate;
+                $scope.fn.issueBack = issueBack;
 
                 //  �씠�뒋 紐⑸줉 而⑦듃濡ㅻ윭 vm, fn �긽�냽 以�
                 $scope.vm.viewer = {};
@@ -125,6 +126,12 @@
                     //$rootScope.$broadcast("makeIssueSearch",issue);
                     $scope.$parent.tableEvent.changeDetailView(issue.id);
                     $scope.fn.onActivate();
+                }
+
+                // �긽�쐞 �씠�뒋 �겢由��떆 �긽�쐞 �씠�뒋濡� �씠�룞
+                function issueBack() {
+                    $rootScope.currentDetailIssueId = $scope.vm.viewer.parentIssueVo.id
+                    $rootScope.$broadcast("getIssueDetail", {id: $rootScope.currentDetailIssueId});
                 }
 
                 function onActivate() {
@@ -490,6 +497,7 @@
 
                 // �뿰愿� �씠�뒋 �뀒�씠釉� �꽕�젙
                 function setRelTableConfigs(issueTableConfigVo) {
+                    if (issueTableConfigVo == null) return;
                     var issueTableConfigs = issueTableConfigVo.issueTableConfigs;
 
                     //  �뿰愿� �뒋 紐⑸줉 �뀒�씠釉� �꽕�젙 媛믪쓣 媛��졇���꽌 �쟻�슜�븳�떎.
@@ -541,6 +549,7 @@
 
                 // �븯�쐞 �씠�뒋 �긽�꽭 議고쉶 寃곌낵 �꽕�젙
                 function setDownTableConfigs(issueTableConfigVo) {
+                    if (issueTableConfigVo == null) return;
                     var issueTableConfigs = issueTableConfigVo.issueTableConfigs;
 
                     //  �뿰愿� �뒋 紐⑸줉 �뀒�씠釉� �꽕�젙 媛믪쓣 媛��졇���꽌 �쟻�슜�븳�떎.
@@ -656,7 +665,6 @@
                 //     $scope.fn.getIssueDetail();
                 // });
 
-                // todo �씠嫄� �삉 萸먯�
                 $scope.$watch(function() {
                     return $rootScope.currentDetailIssueId;
                 }, function() {
@@ -889,11 +897,7 @@
                                     angular.forEach(result.data.data.issueDownVos, function (issueDownVo){
                                         //$scope.vm.form.issuesDown.push(issueDownVo.issueDown);
                                         $scope.vm.form.issuesDown.push(issueDownVo);
-                                        // 媛꾪뿉�쟻�씤 �븯�쐞 �씠�뒋 媛깆떊 �삤瑜� 諛⑹�
-                                        // $scope.$on("getIssueDetail", function (event, args) {
-                                        //      $scope.fn.getIssueDetail();
-                                        //  });
-                                        
+
                                     });
                                 }
                                 $scope.vm.viewer.issueRelationVos = result.data.data.issueRelationVos;
diff --git a/src/main/webapp/scripts/app/project/projectList.controller.js b/src/main/webapp/scripts/app/project/projectList.controller.js
index 9fb34d2..93e08bc 100644
--- a/src/main/webapp/scripts/app/project/projectList.controller.js
+++ b/src/main/webapp/scripts/app/project/projectList.controller.js
@@ -69,9 +69,7 @@
                 $scope.tableEvent = {
                     modify : modify,
                     projectCustomFieldConfig : projectCustomFieldConfig,
-                    changeLastProject : changeLastProject,
-                    moveIssue : moveIssue,
-                    changeDetailView : changeDetailView
+                    changeLastProject : changeLastProject
                 };
 
                 angular.extend(this, $controller('autoCompleteController', {$scope : $scope, $injector : $injector}));
@@ -363,22 +361,8 @@
                 }
 
                 function changeLastProject(projectId) {
-                    $rootScope.changeLastProject(projectId);
-                }
-
-                function moveIssue(projectId) {
-                    // $rootScope.currentDetailIssueId = null;
-                    // �씠�뒋 踰덊샇瑜� ���옣�븳 �썑 �씠�뒋 紐⑸줉�쑝濡� �씠�룞�븳�떎.
-                    // $rootScope.$broadcast("makeIssueSearch", {id :$rootScope.currentDetailIssueId});
-                    //$rootScope.$broadcast("makeIssueSearch", {id :$rootScope.issueTypeMenu.id});
-                    $rootScope.$broadcast("makeIssueSearch",projectId);
-                }
-
-                function changeDetailView() {
-                    // $rootScope.$broadcast("getIssueDetail", {id: $rootScope.currentDetailIssueId});
-                    //$scope.$broadcast("getIssueDetail", {id: $rootScope.currentDetailIssueId});
-                    // $rootScope.$broadcast("getIssueDetail", {id :$rootScope.currentDetailIssueId});
-                    //$rootScope.$broadcast("getIssueList", {id :$rootScope.issueTypeMenu.id});
+                    //$rootScope.changeLastProject(projectId);
+                    $state.go("issues.list")
                 }
 
                 $scope.fn.makeTableConfigs();
diff --git a/src/main/webapp/scripts/components/utils/dateRangePicker.directive.js b/src/main/webapp/scripts/components/utils/dateRangePicker.directive.js
index 7be0571..d6ea913 100644
--- a/src/main/webapp/scripts/components/utils/dateRangePicker.directive.js
+++ b/src/main/webapp/scripts/components/utils/dateRangePicker.directive.js
@@ -77,7 +77,8 @@
                                     });
                                 } else if ($attrs["rangeType"] === "singleDate") {
                                     $($element).daterangepicker({
-                                        timePicker: false,
+                                        timePicker: true,
+                                        timePickerSeconds : true,
                                         autoUpdateInput: true,
                                         autoApply : true,
                                         singleDatePicker : true,
@@ -85,7 +86,7 @@
 
                                         //parentEl : $scope.parentEl !== undefined ? $scope.parentEl : "",
                                         locale: {
-                                            format: 'YYYY-MM-DD',
+                                            format: 'YYYY-MM-DD/hh-mm-ss A',
                                             applyLabel: options.applyLabel,
                                             cancelLabel: options.cancelLabel,
                                             daysOfWeek: options.daysOfWeek,
diff --git a/src/main/webapp/views/api/apiSetting.html b/src/main/webapp/views/api/apiSetting.html
index 1be9f02..37a70fc 100644
--- a/src/main/webapp/views/api/apiSetting.html
+++ b/src/main/webapp/views/api/apiSetting.html
@@ -1,13 +1,6 @@
 <div class="row">
     <div class="col-sm-12">
         <div class="element-wrapper">
-            <div class="element-actions">
-                <button ng-click="fn.add()"
-                        class="btn btn-xlg btn-danger"><i class="os-icon os-icon-plus"></i> <span translate="api.addOverlapField">�븘�뱶 留뚮뱾湲�</span>
-                </button>
-            </div>
-
-
             <div class="element-actions" ng-if="$root.checkMngPermission('USER_PERMISSION_MNG_ISSUE_STATUS')">
             </div>
             <h6 class="element-header" translate="api.setting">
diff --git a/src/main/webapp/views/api/apiSettingSpec.html b/src/main/webapp/views/api/apiSettingSpec.html
index 2d05b54..8ff0bb2 100644
--- a/src/main/webapp/views/api/apiSettingSpec.html
+++ b/src/main/webapp/views/api/apiSettingSpec.html
@@ -99,7 +99,7 @@
 <div class="element-box">
     <div class="row">
         <div class="col-md-1">
-            <label for="issue-detectingInfo" class="issue-label">
+            <label class="issue-label">
                 <span translate="api.requestSampleAdd">�씠�뒋 異붽�</span>
             </label>
         </div>
@@ -108,12 +108,17 @@
         </div>
         <div class="col-md-1"></div>
         <div class="col-md-1">
-            <label for="issue-detectingInfo" class="issue-label">
+            <label class="issue-label">
                 <span translate="api.requestSampleModify">�씠�뒋 �닔�젙</span>
             </label>
+            <label class="text-info">
+                <span translate="api.requestSampleModifyDesc">�닔�젙�떆</span>
+            </label>
         </div>
-        <div>
-            <pre>{{vm.sampleJsonModify}}</pre>
+        <div class="col-md-2">
+            <div>
+                <pre>{{vm.sampleJsonModify}}</pre>
+            </div>
         </div>
     </div>
 </div>
\ No newline at end of file
diff --git a/src/main/webapp/views/issue/issueDetail.html b/src/main/webapp/views/issue/issueDetail.html
index 538bf7a..27e2501 100644
--- a/src/main/webapp/views/issue/issueDetail.html
+++ b/src/main/webapp/views/issue/issueDetail.html
@@ -87,7 +87,7 @@
 <div class="support-ticket-content-w" ng-controller="issueDetailController">
     <div class="support-ticket-content">
         <span ng-if="vm.viewer.parentIssueVo != null" class="badge" ng-style="{'background-color' : '#353535', 'border-color' : vm.viewer.issueStatusVo.color, 'color' : '#FFFFFF' }">
-            <span>�긽�쐞 �씠�뒋:{{vm.viewer.parentIssueVo.title}}</span>
+            <span class="cursor" ng-click="fn.issueBack()">�긽�쐞 �씠�뒋:{{vm.viewer.parentIssueVo.title}}</span>
         </span>
 
         <div class="">
@@ -97,7 +97,7 @@
             <span class="ticket-header">
                 <div class="tasks-header-w">
                     <span class="tags">
-                        <span class="tag">{{vm.viewer.projectVo.projectKey}}-{{vm.viewer.issueNumber}} &nbsp; / &nbsp; {{vm.viewer.projectVo.name}}</span>
+                        <span class="tag">{{vm.viewer.projectVo.projectKey}}-{{vm.viewer.issueNumber}} &nbsp; / &nbsp; {{vm.viewer.projectVo.name}} &nbsp; / &nbsp; <span>API :&nbsp;{{vm.viewer.isApi}}</span></span>
                     </span>
                 </div>
             </span>
diff --git a/src/main/webapp/views/login/login.html b/src/main/webapp/views/login/login.html
index 14b673e..aadedea 100644
--- a/src/main/webapp/views/login/login.html
+++ b/src/main/webapp/views/login/login.html
@@ -1,23 +1,24 @@
 <div class="content-i">
     <div class="content-box">
-        <div class="row mt-30">
+        <div class="row mt-30" style="margin-right: 32rem">
             <div class="m-0">
                 <div class="flex">
                     <div class="loginbackdiv">
-                        <div class="loginback">
-                            <img src="/assets/images/logo-kisa-vertical.png"/>
-                            <div class="stardiv">
-                            <!--    <div class="stars"></div>
-                                <div class="twinkling"></div>
-                            </div>
-                            <div class="bgdiv">
-                            </div>
-                            <div class="login-circle">
-                                <div class="circle1"></div>
-                                <div class="circle2"></div>
-                                <div class="circle3"></div>-->
-                            </div>
-                        </div>
+<!--                        <div class="loginback">-->
+<!--                            <img src="/assets/images/logo-kisa-vertical.png"/>-->
+<!--                            <div class="stardiv">-->
+<!--                                <div class="stars"></div>-->
+<!--                                <div class="twinkling"></div>-->
+<!--                            </div>-->
+<!--                            <div class="bgdiv">-->
+<!--                            </div>-->
+<!--                            <div class="login-circle">-->
+<!--                                <div class="circle1"></div>-->
+<!--                                <div class="circle2"></div>-->
+<!--                                <div class="circle3"></div>-->
+<!--                            </div>-->
+<!--                        </div>-->
+<!--                    </div>-->
                     </div>
                     <div class="logincont">
                         <div class="auth-box-w">
@@ -131,7 +132,7 @@
                 </div>
                 -->
                 <div class="footer-s" >
-                    <small>CopyRight WISESTONE All rights reserved.</small>
+                    <small style="margin-left: 8.8rem">CopyRight WISESTONE All rights reserved.</small>
                 </div>
             </div>
         </div>

--
Gitblit v1.8.0