src/main/java/kr/wisestone/owl/domain/CustomFieldApiOverlap.java
@@ -16,6 +16,11 @@ private User user; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "project_id") private Project project; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "issue_type_id") private IssueType issueType; @@ -60,4 +65,12 @@ public void setCustomField(CustomField customField) { this.customField = customField; } public Project getProject() { return project; } public void setProject(Project project) { this.project = project; } } src/main/java/kr/wisestone/owl/domain/IssueType.java
@@ -35,9 +35,8 @@ @JoinColumn(name = "project_id") private Project project; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "complete_issue_status_id") private IssueStatus issueStatus; @OneToMany(mappedBy = "issueType", cascade = {CascadeType.ALL}, orphanRemoval = true) private Set<IssueTypeApiEndStatus> issueTypeApiEndStatuses; /*@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "company_id") @@ -138,11 +137,11 @@ this.usePartner = usePartner; } public IssueStatus getIssueStatus() { return issueStatus; public Set<IssueTypeApiEndStatus> getIssueTypeApiEndStatuses() { return issueTypeApiEndStatuses; } public void setIssueStatus(IssueStatus issueStatus) { this.issueStatus = issueStatus; public void setIssueTypeApiEndStatuses(Set<IssueTypeApiEndStatus> issueTypeApiEndStatuses) { this.issueTypeApiEndStatuses = issueTypeApiEndStatuses; } } src/main/java/kr/wisestone/owl/domain/IssueTypeApiEndStatus.java
New file @@ -0,0 +1,76 @@ package kr.wisestone.owl.domain; import javax.persistence.*; import java.io.Serializable; @Entity public class IssueTypeApiEndStatus extends BaseEntity implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "project_id") private Project project; @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "issue_type_id") private IssueType issueType; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "issue_status_id") private IssueStatus issueStatus; public IssueTypeApiEndStatus(){} public static long getSerialVersionUID() { return serialVersionUID; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } public IssueType getIssueType() { return issueType; } public void setIssueType(IssueType issueType) { this.issueType = issueType; } public Project getProject() { return project; } public void setProject(Project project) { this.project = project; } public IssueStatus getIssueStatus() { return issueStatus; } public void setIssueStatus(IssueStatus issueStatus) { this.issueStatus = issueStatus; } } src/main/java/kr/wisestone/owl/repository/IssueTypeApiEndStatusRepository.java
New file @@ -0,0 +1,23 @@ package kr.wisestone.owl.repository; import kr.wisestone.owl.domain.IssueType; import kr.wisestone.owl.domain.IssueTypeApiEndStatus; import kr.wisestone.owl.domain.Project; import kr.wisestone.owl.domain.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import javax.inject.Named; import javax.inject.Qualifier; import javax.persistence.NamedQuery; import java.util.List; public interface IssueTypeApiEndStatusRepository extends JpaRepository<IssueTypeApiEndStatus, Long> { IssueTypeApiEndStatus findByUserIdAndProjectIdAndIssueTypeId( @Param("user_id") Long userId, @Param("project_id") Long projectId, @Param("issue_type_id") Long issueTypeId); void deleteByUserIdAndProjectIdAndIssueTypeId( @Param("user_id") Long userId, @Param("project_id") Long projectId, @Param("issue_type_id") Long issueTypeId); } src/main/java/kr/wisestone/owl/service/IssueTypeApiEndStatusService.java
New file @@ -0,0 +1,9 @@ package kr.wisestone.owl.service; import kr.wisestone.owl.domain.IssueTypeApiEndStatus; import kr.wisestone.owl.web.form.IssueTypeApiEndStatusForm; import org.springframework.data.jpa.repository.JpaRepository; public interface IssueTypeApiEndStatusService extends AbstractService<IssueTypeApiEndStatus, Long, JpaRepository<IssueTypeApiEndStatus, Long>> { void setApiEndStatus(IssueTypeApiEndStatusForm issueTypeApiEndStatusForm); } src/main/java/kr/wisestone/owl/service/IssueTypeService.java
@@ -33,8 +33,6 @@ IssueType modifyIssueType(IssueTypeForm issueTypeForm); IssueType modifyIssueTypeCompleteIssueStatus(IssueTypeForm issueTypeForm); IssueType getIssueType(Long id); List<IssueType> findByProjectId(Long projectId); src/main/java/kr/wisestone/owl/service/impl/CustomFieldApiOverlapServiceImpl.java
@@ -33,6 +33,9 @@ private IssueTypeService issueTypeService; @Autowired private ProjectService projectService; @Autowired private CustomFieldService customFieldService; @Override @@ -72,6 +75,7 @@ @Transactional public boolean modify(Map<String, Object> resJsonData, CustomFieldApiOverlapForm form) { User user = this.webAppUtil.getLoginUserObject(); Project project = this.projectService.getProject(form.getProjectId()); List<CustomFieldApiOverlap> customFieldApiOverlaps = this.customFieldApiOverlapRepository.findByUserIdAndIssueTypeId(user.getId(), form.getIssueTypeId()); if (customFieldApiOverlaps != null && customFieldApiOverlaps.size() > 0) { this.customFieldApiOverlapRepository.deleteAll(customFieldApiOverlaps); @@ -84,6 +88,7 @@ customFieldApiOverlap.setCustomField(customField); customFieldApiOverlap.setUser(user); customFieldApiOverlap.setIssueType(this.issueTypeService.getIssueType(form.getIssueTypeId())); customFieldApiOverlap.setProject(project); customFieldApiOverlapList.add(customFieldApiOverlap); } src/main/java/kr/wisestone/owl/service/impl/IssueServiceImpl.java
@@ -1796,16 +1796,22 @@ Issue modifyIssue = this.modifyIssueForApi(user, issueForm, files); Issue parentIssue = modifyIssue.getParentIssue(); IssueType issueType = modifyIssue.getIssueType(); IssueStatus issueStatus = issueType.getIssueStatus(); Set<IssueTypeApiEndStatus> issueTypeApiEndStatuses = issueType.getIssueTypeApiEndStatuses(); IssueTypeApiEndStatus issueStatus = null; if (issueTypeApiEndStatuses != null && issueTypeApiEndStatuses.size() > 0) { issueStatus = issueTypeApiEndStatuses.iterator().next(); } else { throw new OwlRuntimeException(this.messageAccessor.getMessage(MsgConstants.API_COMPLETE_ISSUE_STATUS_NOT_EXIST)); } if (parentIssue != null) { if (issueStatus == null) { throw new OwlRuntimeException(this.messageAccessor.getMessage(MsgConstants.API_COMPLETE_ISSUE_STATUS_NOT_EXIST)); } 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()); parentIssue.setIssueStatus(issueStatus.getIssueStatus()); this.issueRepository.saveAndFlush(parentIssue); } } src/main/java/kr/wisestone/owl/service/impl/IssueTypeApiEndStatusServiceImpl.java
New file @@ -0,0 +1,92 @@ package kr.wisestone.owl.service.impl; import com.fasterxml.jackson.databind.ObjectMapper; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import kr.wisestone.owl.constant.MsgConstants; import kr.wisestone.owl.domain.*; import kr.wisestone.owl.exception.OwlRuntimeException; import kr.wisestone.owl.repository.ApiTokenRepository; import kr.wisestone.owl.repository.IssueTypeApiEndStatusRepository; import kr.wisestone.owl.service.IssueStatusService; import kr.wisestone.owl.service.IssueTypeApiEndStatusService; import kr.wisestone.owl.service.IssueTypeService; import kr.wisestone.owl.service.ProjectService; import kr.wisestone.owl.util.ConvertUtil; import kr.wisestone.owl.util.DateUtil; import kr.wisestone.owl.util.WebAppUtil; import kr.wisestone.owl.vo.ApiTokenVo; import kr.wisestone.owl.vo.UserVo; import kr.wisestone.owl.web.form.ApiTokenForm; import kr.wisestone.owl.web.form.IssueTypeApiEndStatusForm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.UnsupportedEncodingException; import java.util.Date; import java.util.List; @Service public class IssueTypeApiEndStatusServiceImpl extends AbstractServiceImpl<IssueTypeApiEndStatus, Long, JpaRepository<IssueTypeApiEndStatus, Long>> implements IssueTypeApiEndStatusService { @Autowired private IssueTypeApiEndStatusRepository issueTypeApiEndStatusRepository; @Autowired private ProjectService projectService; @Autowired private IssueTypeService issueTypeService; @Autowired private IssueStatusService issueStatusService; @Override protected JpaRepository<IssueTypeApiEndStatus, Long> getRepository() { return this.issueTypeApiEndStatusRepository; } // 종료 상태 설정 @Override @Transactional public void setApiEndStatus(IssueTypeApiEndStatusForm issueTypeApiEndStatusForm) { User user = this.webAppUtil.getLoginUserObject(); Project project = this.projectService.getProject(issueTypeApiEndStatusForm.getProjectId()); IssueType issueType = this.issueTypeService.getIssueType(issueTypeApiEndStatusForm.getIssueTypeId()); if (issueTypeApiEndStatusForm.getIssueStatusId() == null) { // 기존 설정 삭제 this.issueTypeApiEndStatusRepository.deleteByUserIdAndProjectIdAndIssueTypeId( user.getId(), issueTypeApiEndStatusForm.getProjectId(), issueTypeApiEndStatusForm.getIssueTypeId()); } else { IssueStatus issueStatus = this.issueStatusService.getIssueStatus(issueTypeApiEndStatusForm.getIssueStatusId()); // 기존 설정 찾기 IssueTypeApiEndStatus issueTypeApiEndStatus = this.issueTypeApiEndStatusRepository.findByUserIdAndProjectIdAndIssueTypeId( user.getId(), issueTypeApiEndStatusForm.getProjectId(), issueTypeApiEndStatusForm.getIssueTypeId()); if (issueTypeApiEndStatus != null) { issueTypeApiEndStatus.setIssueStatus(issueStatus); this.issueTypeApiEndStatusRepository.save(issueTypeApiEndStatus); } else { // 새로 설정 IssueTypeApiEndStatus newIssueTypeApiEndStatus = ConvertUtil.copyProperties(issueTypeApiEndStatusForm, IssueTypeApiEndStatus.class); newIssueTypeApiEndStatus.setUser(user); newIssueTypeApiEndStatus.setProject(project); newIssueTypeApiEndStatus.setIssueType(issueType); newIssueTypeApiEndStatus.setIssueStatus(issueStatus); this.issueTypeApiEndStatusRepository.save(newIssueTypeApiEndStatus); } } } } src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java
@@ -33,6 +33,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @Service public class IssueTypeServiceImpl extends AbstractServiceImpl<IssueType, Long, JpaRepository<IssueType, Long>> implements IssueTypeService { @@ -270,9 +271,11 @@ for (IssueTypeVo issueTypeVo : issueTypeVos) { IssueType issueType = this.getIssueType(issueTypeVo.getId()); IssueStatus issueStatus = issueType.getIssueStatus(); if (issueStatus != null) { issueTypeVo.setCompleteIssueStatusVo(ConvertUtil.copyProperties(issueType.getIssueStatus(), IssueStatusVo.class)); Set<IssueTypeApiEndStatus> issueTypeApiEndStatuses = issueType.getIssueTypeApiEndStatuses(); if (issueTypeApiEndStatuses != null && issueTypeApiEndStatuses.size() > 0) { IssueTypeApiEndStatus issueTypeApiEndStatus = issueTypeApiEndStatuses.iterator().next(); issueTypeVo.setCompleteIssueStatusVo(ConvertUtil.copyProperties(issueTypeApiEndStatus.getIssueStatus(), IssueStatusVo.class)); } } } @@ -323,26 +326,6 @@ } resJsonData.put(Constants.RES_KEY_CONTENTS, issueTypeVo); } // 이슈 유형을 수정한다. 자동 종료 설정만 수정 @Override @Transactional public IssueType modifyIssueTypeCompleteIssueStatus(IssueTypeForm issueTypeForm) { // 사용하고 있는 업무 공간이 활성 상태인지 확인한다. 사용 공간에서 로그인한 사용자가 비활성인지 확인한다. this.workspaceService.checkUseWorkspace(); IssueType issueType = this.getIssueType(issueTypeForm.getId()); if (issueTypeForm.getCompleteIssueStatusId() != null) { // api에서 사용하는 자동 종료 이슈 상태 IssueStatus issueStatus = this.issueStatusService.getIssueStatus(issueTypeForm.getCompleteIssueStatusId()); issueType.setIssueStatus(issueStatus); }else { issueType.setIssueStatus(null); } this.issueTypeRepository.saveAndFlush(issueType); return issueType; } // 이슈 유형을 수정한다. src/main/java/kr/wisestone/owl/web/controller/IssueTypeApiEndStatusController.java
New file @@ -0,0 +1,46 @@ package kr.wisestone.owl.web.controller; import kr.wisestone.owl.constant.Constants; import kr.wisestone.owl.service.GuideService; import kr.wisestone.owl.service.IssueTypeApiEndStatusService; import kr.wisestone.owl.util.ConvertUtil; import kr.wisestone.owl.web.condition.GuideCondition; import kr.wisestone.owl.web.form.GuideForm; import kr.wisestone.owl.web.form.IssueTypeApiEndStatusForm; import kr.wisestone.owl.web.form.IssueTypeForm; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import java.util.HashMap; import java.util.Map; /** * Create By J E O N G - S U N / 2019-05-24 */ @Controller public class IssueTypeApiEndStatusController extends BaseController { @Autowired private IssueTypeApiEndStatusService issueTypeApiEndStatusService; // api 자동 종료 이슈상태 설정 @RequestMapping(value = "/api/saveCompleteIssueStatus", produces = MediaType.APPLICATION_JSON_VALUE) public @ResponseBody Map<String, Object> saveCompleteIssueStatus(@RequestBody Map<String, Map<String, Object>> params) { Map<String, Object> resJsonData = new HashMap<>(); IssueTypeApiEndStatusForm issueTypeApiEndStatusForm = ConvertUtil.convertMapToClass(params.get(Constants.REQ_KEY_CONTENT), IssueTypeApiEndStatusForm.class); this.issueTypeApiEndStatusService.setApiEndStatus(issueTypeApiEndStatusForm); return this.setSuccessMessage(resJsonData); } } src/main/java/kr/wisestone/owl/web/controller/IssueTypeController.java
@@ -95,14 +95,4 @@ return this.issueTypeService.downloadExcel(request, model); } // api 자동 종료 이슈상태 설정 @RequestMapping(value = "/api/saveCompleteIssueStatus", produces = MediaType.APPLICATION_JSON_VALUE) public @ResponseBody Map<String, Object> saveCompleteIssueStatus(@RequestBody Map<String, Map<String, Object>> params) { Map<String, Object> resJsonData = new HashMap<>(); IssueTypeForm issueTypeForm = IssueTypeForm.make(params.get(Constants.REQ_KEY_CONTENT)); this.issueTypeService.modifyIssueTypeCompleteIssueStatus(issueTypeForm); return this.setSuccessMessage(resJsonData); } } src/main/java/kr/wisestone/owl/web/form/CustomFieldApiOverlapForm.java
@@ -12,6 +12,7 @@ private Long id; private Long userId; private Long issueTypeId; private Long projectId; private List<Long> customFieldIds; public CustomFieldApiOverlapForm(){} @@ -64,4 +65,12 @@ this.customFieldIds.add(customFieldId); } } public Long getProjectId() { return projectId; } public void setProjectId(Long projectId) { this.projectId = projectId; } } src/main/java/kr/wisestone/owl/web/form/IssueTypeApiEndStatusForm.java
New file @@ -0,0 +1,43 @@ package kr.wisestone.owl.web.form; public class IssueTypeApiEndStatusForm { private Long userId; private Long projectId; private Long issueTypeId; private Long issueStatusId; public IssueTypeApiEndStatusForm() { } public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } public Long getProjectId() { return projectId; } public void setProjectId(Long projectId) { this.projectId = projectId; } public Long getIssueTypeId() { return issueTypeId; } public void setIssueTypeId(Long issueTypeId) { this.issueTypeId = issueTypeId; } public Long getIssueStatusId() { return issueStatusId; } public void setIssueStatusId(Long issueStatusId) { this.issueStatusId = issueStatusId; } } src/main/java/kr/wisestone/owl/web/form/IssueTypeForm.java
@@ -18,7 +18,6 @@ private String color; private Long workflowId; private Long projectId; private Long completeIssueStatusId; private List<Long> removeIds = Lists.newArrayList(); private Long usePartner; @@ -114,13 +113,5 @@ public void setUsePartner(Long usePartner) { this.usePartner = usePartner; } public Long getCompleteIssueStatusId() { return completeIssueStatusId; } public void setCompleteIssueStatusId(Long completeIssueStatusId) { this.completeIssueStatusId = completeIssueStatusId; } } src/main/resources/migration/V1_15__Alter_Table.sql
New file @@ -0,0 +1,22 @@ ALTER TABLE `custom_field_api_overlap` ADD COLUMN `project_id` bigint(20) DEFAULT NULL; ALTER TABLE `custom_field_api_overlap` ADD INDEX `projectIdIndex`(`project_id`); ALTER TABLE `issue_type` DROP COLUMN `complete_issue_status_id`; -- 이슈 자동 종료 설정 테이블 CREATE TABLE IF NOT EXISTS `issue_type_api_end_status` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) DEFAULT NULL, `project_id` bigint(20) DEFAULT NULL, `issue_type_id` bigint(20) DEFAULT NULL, `issue_status_id` bigint(20) DEFAULT NULL, `register_id` bigint(20) NOT NULL COMMENT 'register_id', `register_date` timestamp NULL DEFAULT NULL COMMENT 'register_date', `modify_id` bigint(20) NOT NULL COMMENT 'modify_id', `modify_date` timestamp NULL DEFAULT NULL COMMENT 'modify_date', PRIMARY KEY (`id`), KEY `userIdIndex` (`user_id`), KEY `projectIdIndex` (`project_id`), KEY `issueTypeIdIndex` (`issue_type_id`), KEY `issueStatusIdIndex` (`issue_status_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; src/main/resources/mybatis/query-template/issueType-template.xml
@@ -9,8 +9,7 @@ it.name as name, it.description as description, it.color as color, it.project_id as projectId, it.complete_issue_status_id as completeIssueStatusId it.project_id as projectId FROM issue_type it INNER JOIN workspace ws on it.workspace_id = ws.id src/main/webapp/i18n/ko/global.json
@@ -858,13 +858,14 @@ "emailField": "이메일 선택 필드", "siteField": "URL 선택 필드", "telField": "전화번호 선택 필드", "invalidipAdressFormat": "IP 주소 형식이 맞지 않습니다.", "invalidNumberFormat": "숫자만 입력 가능합니다.", "invalidDateFormat": "날짜 형식이 맞지 않습니다.(xxxx-xx-xx)", "invalidEmailFormat": "이메일 형식이 맞지 않습니다.", "invalidSiteFormat": "홈페이지 주소 형식이 맞지 않습니다.(http://로 시작하셔야합니다)", "invalidTelFormat": "전화번호 형식이 맞지 않습니다(xxx-xxxx-xxxx).", "invalidUrlFormat": "url 형식이 맞지 않습니다." "invalidipAdressFormat": "* IP 주소 형식이 맞지 않습니다.", "invalidNumberFormat": "* 숫자만 입력 가능합니다.", "invalidDateFormat": "* 날짜 형식이 맞지 않습니다.(xxxx-xx-xx)", "invalidEmailFormat": "* 이메일 형식이 맞지 않습니다.", "invalidSiteFormat": "* 홈페이지 주소 형식이 맞지 않습니다.(http:// 또는 www 로 시작하셔야합니다)", "invalidTelFormat": "* 전화번호 형식이 맞지 않습니다(xxx-xxxx-xxxx).", "invalidUrlFormat": "* url 형식이 맞지 않습니다.", "notIssueType": "이슈 유형이 없습니다." }, "tasks": { "agileBoardTitle": "칸반 보드" src/main/webapp/scripts/app/api/apiSetting.controller.js
@@ -9,23 +9,23 @@ function (app, angular) { app.controller('apiSettingController', ['$scope', '$rootScope', '$log', '$resourceProvider','$uibModal', 'SweetAlert', '$timeout', '$filter', '$injector', '$controller', 'Api', 'Priority', 'Severity', 'IssueType', 'IssueTypeCustomField', 'IssueStatus', 'IssueStatus', '$q', function ($scope, $rootScope, $log, $resourceProvider, $uibModal, SweetAlert, $timeout, $filter, $injector, $controller, Api, Priority, Severity, IssueType, IssueTypeCustomField, IssueStatus) { IssueStatus, $q) { $scope.fn = { changeTab : changeTab, getIssueTypeCallback : getIssueTypeCallback, getProjectListCallback : getProjectListCallback, formSubmit : formSubmit, formSubmitColumnSetting : formSubmitColumnSetting, formCheck : formCheck, initForm : initForm, getPriorities : getPriorities, getSeverities : getSeverities, onChangeColumnSetting : onChangeColumnSetting, onChangeEndIssueStatus : onChangeEndIssueStatus, getIssueTypes : getIssueTypes, onChangeIssueType : onChangeIssueType, reset : reset, resetOverlap : resetOverlap, formSubmitOverlap : formSubmitOverlap, @@ -42,7 +42,10 @@ getProjects : getProjects, formSubmitCompleteIssueStatus : formSubmitCompleteIssueStatus, loadPage : loadPage, resetCompleteIssueStatus : resetCompleteIssueStatus resetCompleteIssueStatus : resetCompleteIssueStatus, findIssueList : findIssueList, onChangeProject : onChangeProject, setApiIssueTypeStatus : setApiIssueTypeStatus }; $scope.vm = { @@ -103,7 +106,7 @@ function reset() { $scope.fn.initForm(); $scope.fn.formSubmit(); $scope.fn.formSubmitColumnSetting(); } // 자동종료 설정 초기화 @@ -158,9 +161,7 @@ if ($scope.vm.issueTypeId === "") { $scope.vm.issueTypeId = $scope.vm.issueTypes[0].id.toString(); } if ($scope.vm.tab === "") { $scope.fn.changeTab("API_COL_SETTING"); } // if ($scope.vm.tab === "API_COL_SETTING") { // $scope.fn.onChangeIssueType(); @@ -188,46 +189,23 @@ return issueTypeVo; } function onChangeIssueTypeOverlap() { $scope.fn.getIssueTypeCustomFields(); $scope.fn.getOverlapList(); // 자동 동료 이슈 상태 변경시 function onChangeEndIssueStatus() { } function onChangeIssueType() { if ($scope.vm.issueTypeId != null) { let conditions = { issueTypeId: $scope.vm.issueTypeId } Api.findApiDefault($resourceProvider.getContent( conditions, $resourceProvider.getPageContent(0, 1000))).then(function (result) { $scope.fn.initForm(); if (result.data.message.status === "success") { if (angular.isDefined(result.data.data)) { $scope.vm.form.issueApiDefault = result.data.data; $scope.vm.form.issueApiDefault.priorityId = result.data.data.priorityId != null ? result.data.data.priorityId.toString() : ""; $scope.vm.form.issueApiDefault.severityId = result.data.data.severityId != null ? result.data.data.severityId.toString() : ""; // if (angular.isDefined(result.data.data.projectVo)) { // $scope.vm.projects = []; // $scope.vm.projects.push(result.data.data.projectVo); // } } } else { SweetAlert.swal($filter("translate")("common.failedToIssueTypeDefault"), result.data.message.message, "error"); // "프로젝트 목록 조회 실패" } }); } function onChangeIssueTypeOverlap() { $scope.fn.getIssueStatuses(); $scope.fn.getIssueTypeCustomFields(); $scope.fn.getOverlapList(); } function formSubmitCompleteIssueStatus() { if ($scope.vm.issueTypeId != null) { let content = { id: $scope.vm.issueTypeId, completeIssueStatusId: $scope.vm.completeIssueStatusId issueTypeId : $scope.vm.issueTypeId, projectId : $scope.vm.projectId, issueStatusId: $scope.vm.completeIssueStatusId === "none" ? null : $scope.vm.completeIssueStatusId } Api.saveCompleteIssueStatus($resourceProvider.getContent( @@ -235,7 +213,8 @@ if (result.data.message.status === "success") { SweetAlert.swal($filter("translate")("api.successToApiAutoCompleteIssueStatus"), result.data.message.message, "success"); // "설정 성공" $scope.fn.getIssueTypes(); //$scope.fn.getIssueTypes(); $scope.fn.findIssueList($scope.vm.projectId); } else { SweetAlert.swal($filter("translate")("api.failedToApiAutoCompleteIssueStatus"), result.data.message.message, "error"); // "설정 실패" } @@ -252,14 +231,14 @@ return false; } function formSubmit() { function formSubmitColumnSetting() { if ($scope.vm.issueTypeId == null) return; let condition = { issueTypeId : $scope.vm.issueTypeId, title : $scope.vm.form.issueApiDefault.title, // projectId : $scope.vm.projects != null && $scope.vm.projects.length > 0 ? $scope.vm.projects[0].id : null, projectId : $scope.vm.projectId, priorityId : $scope.vm.form.issueApiDefault.priorityId, severityId : $scope.vm.form.issueApiDefault.severityId, description : $scope.vm.form.issueApiDefault.description, @@ -289,6 +268,7 @@ let condition = { issueTypeId : $scope.vm.issueTypeId, projectId : $scope.vm.projectId, customFieldIds : (function () { var ids = []; @@ -400,37 +380,35 @@ if (tab === "API_COL_SETTING") { $scope.fn.onChangeColumnSetting(); } else if (tab === "API_OVERLAP_SETTING") { $scope.fn.getIssueStatuses(); $scope.fn.onChangeIssueTypeOverlap(); } else if (tab === "API_SPEC_SETTING") { $scope.fn.onChangeIssueTypeSpec(); } } $scope.$on("getIssueStatusComplete", function (event, args){ if ($scope.vm.tab === "API_OVERLAP_SETTING") { if ($scope.vm.issueStatuses != null) { $scope.vm.completeIssueStatuses = []; // 자동 종료 이슈 상태 적용 function setApiIssueTypeStatus() { if ($scope.vm.issueStatuses != null) { $scope.vm.completeIssueStatuses = []; $scope.vm.issueStatuses.forEach(function (issueStatus) { if (issueStatus.issueStatusType === "CLOSE") { $scope.vm.completeIssueStatuses.push(issueStatus); $scope.vm.issueStatuses.forEach(function (issueStatus) { if (issueStatus.issueStatusType === "CLOSE") { $scope.vm.completeIssueStatuses.push(issueStatus); } }); // 설정된 상태 지정 $scope.vm.completeIssueStatusId = "none"; let issueTypeVo = $scope.fn.getCurrentIssueTypeVo(); if (issueTypeVo.completeIssueStatusVo != null) { $scope.vm.completeIssueStatuses.forEach(function (issueStatus) { if (issueStatus.id === issueTypeVo.completeIssueStatusVo.id) { $scope.vm.completeIssueStatusId = issueStatus.id.toString(); } }); // 설정된 상태 지정 $scope.vm.completeIssueStatusId = ""; let issueTypeVo = $scope.fn.getCurrentIssueTypeVo(); if (issueTypeVo.completeIssueStatusVo != null) { $scope.vm.completeIssueStatuses.forEach(function (issueStatus) { if (issueStatus.id === issueTypeVo.completeIssueStatusVo.id) { $scope.vm.completeIssueStatusId = issueStatus.id.toString(); } }); } } } }); } function getIssueStatuses() { var condition = { @@ -443,11 +421,14 @@ $scope.vm.issueStatuses = result.data.data; // $scope.vm.issueStatusId = ""; if ($scope.vm.issueTypeId === "") { if ($scope.vm.issueStatuses != null && $scope.vm.issueStatuses.length > 0) { $scope.vm.issueStatusId = $scope.vm.issueStatuses[0].id.toString(); } if ($scope.vm.issueStatuses != null && $scope.vm.issueStatuses.length > 0) { $scope.vm.issueStatusId = $scope.vm.issueStatuses[0].id.toString(); } if ($scope.vm.tab === "API_OVERLAP_SETTING") { $scope.fn.setApiIssueTypeStatus(); } $scope.$broadcast("getIssueStatusComplete", $scope.vm.issueStatuses); } else { SweetAlert.swal($filter("translate")("issue.failedToCriticalListLookup"), result.data.message.message, "error"); // 중요도 목록 조회 실패 @@ -456,11 +437,70 @@ } function onChangeColumnSetting() { $scope.fn.getSeverities(); $scope.fn.getPriorities(); $scope.fn.onChangeIssueType(); var promises = { severities : $scope.fn.getSeverities(), priorities : $scope.fn.getPriorities(), } $q.all(promises).then(function (results) { if ($scope.vm.issueTypeId != null && $scope.vm.issueTypeId !== "none") { let conditions = { issueTypeId: $scope.vm.issueTypeId } Api.findApiDefault($resourceProvider.getContent( conditions, $resourceProvider.getPageContent(0, 1000))).then(function (result) { $scope.fn.initForm(); if (result.data.message.status === "success") { if (angular.isDefined(result.data.data)) { $scope.vm.form.issueApiDefault = result.data.data; $scope.vm.form.issueApiDefault.priorityId = result.data.data.priorityId != null ? result.data.data.priorityId.toString() : ""; $scope.vm.form.issueApiDefault.severityId = result.data.data.severityId != null ? result.data.data.severityId.toString() : ""; } } else { SweetAlert.swal($filter("translate")("common.failedToIssueTypeDefault"), result.data.message.message, "error"); // "프로젝트 목록 조회 실패" } }); } }); } // 프로젝트 변경시 function onChangeProject() { $scope.fn.findIssueList($scope.vm.projectId); } // 이슈 유형 목록 가져오기 function findIssueList(projectId) { if ($rootScope.projects == null || $rootScope.projects.length <= 1) return; // 이슈 타입 목록 검색 조건을 만든다. var conditions = { projectId : projectId > -1 ? projectId : null, useProject : true, deep : "01" // 이슈 유형에 연결된 워크플로우 정보를 찾는다. } IssueType.find($resourceProvider.getContent(conditions, $resourceProvider.getPageContent(0, 100))).then(function (result) { if (result.data.message.status === "success") { $scope.vm.issueTypes = result.data.data; if ($scope.vm.issueTypes != null && $scope.vm.issueTypes.length > 0) { $scope.vm.issueTypeId = $scope.vm.issueTypes[0].id.toString(); $scope.fn.getIssueStatuses(); $scope.fn.getIssueTypeCustomFields(); } else { $scope.vm.issueTypeId = "none"; } } else { SweetAlert.error($filter("translate")("managementType.failedToIssueTypeList"), result.data.message.message); // "이슈 유형 목록 조회 실패" } }); } function onChangeIssueTypeSpec() { $scope.fn.getIssueStatuses(); @@ -514,7 +554,8 @@ if ($rootScope.projects != null && $rootScope.projects.length > 0) { // 공통 데이터 불러오기 $scope.fn.getProjects(); $scope.fn.getIssueTypes(); $scope.fn.findIssueList($scope.vm.projectId); // $scope.fn.getIssueTypes(); } }, true); @@ -534,6 +575,8 @@ } } if ($scope.vm.tab === "") { $scope.fn.changeTab("API_COL_SETTING"); } }]); }); src/main/webapp/scripts/config.js
@@ -285,17 +285,17 @@ return false; }; $rootScope.getMyInfo = function () { User.findMyLevelAndDepartment($resourceProvider.getContent({}, $resourceProvider.getPageContent(0, 0))).then(function (result) { if (result.data.message.status === "success") { $rootScope.myLevel = result.data.data.levelName $rootScope.myDepartments = result.data.data.departmentName } }); } // $rootScope.getMyInfo = function () { // // User.findMyLevelAndDepartment($resourceProvider.getContent({}, // $resourceProvider.getPageContent(0, 0))).then(function (result) { // // if (result.data.message.status === "success") { // $rootScope.myLevel = result.data.data.levelName // $rootScope.myDepartments = result.data.data.departmentName // } // }); // } /*$rootScope.checkMngPermissionViewIssueAndProject = function (userPermission) { if (!$rootScope.isDefined($rootScope.user)) { @@ -549,7 +549,7 @@ // 이슈 목록->상세화면에서 마지막으로 접근한 이슈 아이디 - 라우트 탈때마다 초기화 $rootScope.currentDetailIssueId = null; // 사용자 정보를 가져온다. $rootScope.getMyInfo(); // $rootScope.getMyInfo(); $log.debug("toState.name : ", toState.name); $log.debug("$rootScope.previousStateName 확인 : ", $rootScope.previousStateName); src/main/webapp/views/api/apiSetting.html
@@ -25,12 +25,15 @@ <div class="tab-content mt-30"> <div ng-show="vm.tab == 'API_SPEC_SETTING'"> <div ng-include include-replace src="'views/api/apiSettingHeader.html'"></div> <div ng-include include-replace src="'views/api/apiSettingSpec.html'"></div> </div> <div ng-show="vm.tab == 'API_COL_SETTING'"> <div ng-include include-replace src="'views/api/apiSettingHeader.html'"></div> <div ng-include include-replace src="'views/api/apiSettingColumn.html'"></div> </div> <div ng-show="vm.tab == 'API_OVERLAP_SETTING'"> <div ng-include include-replace src="'views/api/apiSettingHeader.html'"></div> <div ng-include include-replace src="'views/api/apiSettingOverlap.html'"></div> </div> </div> src/main/webapp/views/api/apiSettingColumn.html
@@ -1,46 +1,3 @@ <div class="row"> <div class="col-md-4" ng-if="false"> <div class="form-group mb10"> <label for="projectForm" class="issue-label"> <span translate="common.project">프로젝트</span> </label> <select id="projectForm" name="project" class="form-control input-sm issue-select-label" ng-model="vm.projectId" ng-change="fn.onChangeIssueTypeSpec()" required> <option ng-repeat="project in vm.projects" value="{{project.id}}" translate="{{project.name}}(id:{{project.id}})"> </option> </select> </div> </div> <div class="col-md-4"> <div class="form-group mb10"> <label for="issueTypeForm" class="issue-label"> <span translate="issue.issueType">이슈 유형</span> </label> <select id="issueTypeForm" name="issueType" class="form-control input-sm issue-select-label" ng-model="vm.issueTypeId" ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.issueTypeId) }" ng-change="fn.onChangeIssueType()" required> <option ng-repeat="issueType in vm.issueTypes" ng-style="{ 'color' : issueType.color, 'font-weight': 600 }" value="{{issueType.id}}" translate="{{issueType.name}}(id:{{issueType.id}})"> </option> </select> </div> </div> </div> <div class="element-box"> <form role="form" name="apiSettingColumnForm"> <div class="form-group mb10"> @@ -140,8 +97,8 @@ </button> <button type="button" class="btn btn-md btn-primary bold" js-short-cut js-short-cut-action="(fn.formCheck(apiSettingColumnForm.$invalid) || $root.spinner) ? null : fn.formSubmit()" ng-click="fn.formSubmit()"><span translate="common.saved">생성</span> js-short-cut-action="(fn.formCheck(apiSettingColumnForm.$invalid) || $root.spinner) ? null : fn.formSubmitColumnSetting()" ng-click="fn.formSubmitColumnSetting()"><span translate="common.saved">생성</span> </button> </div> </div> src/main/webapp/views/api/apiSettingHeader.html
New file @@ -0,0 +1,42 @@ <div class="row"> <div class="col-md-4"> <div class="form-group mb10"> <label for="projectForm" class="issue-label"> <span translate="common.project">프로젝트</span> </label> <select id="projectForm" name="project" class="form-control input-sm issue-select-label" ng-model="vm.projectId" ng-change="fn.onChangeProject()" required> <option ng-repeat="project in vm.projects" value="{{project.id}}" translate="{{project.name}}(id:{{project.id}})"> </option> </select> </div> </div> <div class="col-md-4"> <div class="form-group mb10"> <label for="issueTypeForm" class="issue-label"> <span translate="issue.issueType">이슈 유형</span> </label> <select id="issueTypeForm" name="issueType" class="form-control input-sm issue-select-label" ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.issueTypeId) }" ng-model="vm.issueTypeId" ng-change="fn.loadPage()" required> <option ng-if="vm.issueTypes == null || vm.issueTypes.length == 0" value="none" translate="common.none"></option> <option ng-repeat="issueType in vm.issueTypes" ng-style="{ 'color' : issueType.color, 'font-weight': 600 }" value="{{issueType.id}}" translate="{{issueType.name}}(id:{{issueType.id}})"> </option> </select> </div> </div> </div> src/main/webapp/views/api/apiSettingOverlap.html
@@ -1,52 +1,3 @@ <div class="row"> <div class="col-md-4" ng-if="false"> <div class="form-group mb10"> <label for="projectForm" class="issue-label"> <span translate="common.project">프로젝트</span> </label> <select id="projectForm" name="project" class="form-control input-sm issue-select-label" ng-model="vm.projectId" ng-change="fn.onChangeIssueTypeSpec()" required> <option ng-repeat="project in vm.projects" value="{{project.id}}" translate="{{project.name}}(id:{{project.id}})"> </option> </select> </div> </div> <div class="col-sm-4"> <div class="element-wrapper"> <div class="form-group mb10"> <label for="issueTypeForm" class="issue-label"> <span translate="issue.issueType">이슈 유형</span> </label> <select id="issueTypeForm" name="issueType" class="form-control input-sm issue-select-label" ng-model="vm.issueTypeId" ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.issueTypeId) }" ng-change="fn.onChangeIssueTypeOverlap()" required> <option ng-repeat="issueType in vm.issueTypes" ng-style="{ 'color' : issueType.color, 'font-weight': 600 }" value="{{issueType.id}}" translate="{{issueType.name}}"> </option> </select> </div> </div> </div> </div> <label for="issueTypeForm" class="issue-label"> <span translate="api.upIssueCompleteIssueStatus">상위 이슈 자동종료 이슈 상태 설정</span> </label> @@ -62,8 +13,9 @@ class="form-control input-sm issue-select-label" ng-style="{ 'color' : fn.getOptionColor(vm.completeIssueStatuses, vm.completeIssueStatusId) }" ng-model="vm.completeIssueStatusId" ng-change="fn.onChangeIssueTypeOverlap()" ng-change="fn.onChangeEndIssueStatus()" required> <option value="none" translate="common.select"></option> <option ng-repeat="issueStatus in vm.completeIssueStatuses" ng-style="{ 'color' : issueStatus.color, 'font-weight': 600 }" value="{{issueStatus.id}}" src/main/webapp/views/api/apiSettingSpec.html
@@ -1,45 +1,3 @@ <div class="row"> <div class="col-md-4"> <div class="form-group mb10"> <label for="projectForm" class="issue-label"> <span translate="common.project">프로젝트</span> </label> <select id="projectForm" name="project" class="form-control input-sm issue-select-label" ng-model="vm.projectId" ng-change="fn.onChangeIssueTypeSpec()" required> <option ng-repeat="project in vm.projects" value="{{project.id}}" translate="{{project.name}}(id:{{project.id}})"> </option> </select> </div> </div> <div class="col-md-4"> <div class="form-group mb10"> <label for="issueTypeForm" class="issue-label"> <span translate="issue.issueType">이슈 유형</span> </label> <select id="issueTypeForm" name="issueType" class="form-control input-sm issue-select-label" ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.issueTypeId) }" ng-model="vm.issueTypeId" ng-change="fn.onChangeIssueTypeSpec()" required> <option ng-repeat="issueType in vm.issueTypes" ng-style="{ 'color' : issueType.color, 'font-weight': 600 }" value="{{issueType.id}}" translate="{{issueType.name}}(id:{{issueType.id}})"> </option> </select> </div> </div> </div> <div class="element-box"> <form role="form" name="apiSettingColumnForm"> <div class="form-group mb10"> src/main/webapp/views/customField/customFieldAdd.html
@@ -131,7 +131,7 @@ </div> <input ng-if="vm.form.customFieldType == 'IP_ADDRESS'" name="ipAdress" name="ipAddress" type="text" class="form-control" kr-input @@ -139,7 +139,7 @@ placeholder="IP 주소 형식만 입력 가능합니다." autocomplete="off" ng-model="vm.form.defaultValue"> <div ng-show="customFieldAddForm.ipAdress.$error.pattern" class="help-block form-text text-danger" <div ng-show="customFieldAddForm.ipAddress.$error.pattern" class="help-block form-text text-danger" translate="common.invalidipAdressFormat">IP주소 형식이 맞지 않습니다. </div> @@ -161,9 +161,9 @@ name="site" type="text" class="form-control" maxlength="30" maxlength="100" kr-input ng-pattern="/((http|https):\/\/)?(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/" ng-pattern="/(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/" placeholder="홈페이지 주소 형식만 입력 가능합니다." autocomplete="off" ng-model="vm.form.defaultValue"> @@ -171,10 +171,10 @@ translate="common.invalidSiteFormat">홈페이지 주소 형식이 맞지 않습니다.(http://로 시작하셔야합니다) </div> <input ng-if="vm.form.customFieldType == 'TEL'" name="tel" type="text" maxlength="30" class="form-control" kr-input ng-pattern="/^\d{2,3}-\d{3,4}-\d{4}$/" src/main/webapp/views/customField/customFieldModify.html
@@ -107,17 +107,17 @@ placeholder="숫자만 입력 가능합니다." autocomplete="off" ng-model="vm.form.defaultValue"> <div ng-show="customFieldAddForm.ipAdress.$error.pattern" class="help-block form-text text-danger" <div ng-show="customFieldModifyForm.numberType.$error.pattern" class="help-block form-text text-danger" translate="common.invalidNumberFormat">숫자만 입력 가능합니다. </div> <input ng-if="vm.form.customFieldType == 'DATETIME'" name="dateTime" class="form-control input-readonly" placeholder="{{'issue.clickToSelectDate' | translate}}" ng-model="vm.form.defaultValue" modal-form-auto-scroll range-type="singleDate" onfocus="this.blur()" date-range-picker> <div class="row"> <div class="col-xs-12"> @@ -126,7 +126,7 @@ </div> <input ng-if="vm.form.customFieldType == 'IP_ADDRESS'" name="ipAdress" name="ipAddress" type="text" class="form-control" kr-input @@ -134,7 +134,7 @@ placeholder="IP 주소 형식만 입력 가능합니다." autocomplete="off" ng-model="vm.form.defaultValue"> <div ng-show="customFieldAddForm.ipAdress.$error.pattern" class="help-block form-text text-danger" <div ng-show="customFieldModifyForm.ipAddress.$error.pattern" class="help-block form-text text-danger" translate="common.invalidipAdressFormat">IP주소 형식이 맞지 않습니다. </div> @@ -148,7 +148,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-show="customFieldModifyForm.email.$error.pattern" class="help-block form-text text-danger" translate="common.invalidEmailFormat">이메일 형식이 맞지 않습니다. </div> @@ -156,27 +156,27 @@ name="site" type="text" class="form-control" maxlength="30" maxlength="100" kr-input ng-pattern="/(http(s)?:\/\/)([a-z0-9\w]+\.*)+[a-z0-9]{2,4}/gi" ng-pattern="/(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/" placeholder="홈페이지 주소 형식만 입력 가능합니다." autocomplete="off" ng-model="vm.form.defaultValue"> <div ng-show="customFieldAddForm.site.$error.pattern" class="help-block form-text text-danger" <div ng-show="customFieldModifyForm.site.$error.pattern" class="help-block form-text text-danger" translate="common.invalidSiteFormat">홈페이지 주소 형식이 맞지 않습니다.(http://로 시작하셔야합니다) </div> <input ng-if="vm.form.customFieldType == 'TEL'" name="tel" type="text" maxlength="30" class="form-control" kr-input ng-pattern="/^\d{2,3}-\d{3,4}-\d{4}$/" placeholder="연락처 형식만 입력 가능합니다." autocomplete="off" ng-model="vm.form.defaultValue"> <div ng-show="customFieldAddForm.tel.$error.pattern" class="help-block form-text text-danger" <div ng-show="customFieldModifyForm.tel.$error.pattern" class="help-block form-text text-danger" translate="common.invalidTelFormat">전화번호 형식이 맞지 않습니다. </div> src/main/webapp/views/issue/issueAdd.html
@@ -236,7 +236,7 @@ <!-- 기본 입력 --> <div ng-switch-when="INPUT"> <input type="text" class="form-control input-sm" name="input" name="inputValue" ng-model="issueCustomField.useValues" maxlength="100" autocomplete="off" @@ -244,32 +244,39 @@ ng-required="issueCustomField.fieldOption == '01' || issueCustomField.customFieldVo.requiredData == 'Y'"> <small class="help-block form-text text-danger" ng-show="issueCustomField.customFieldVo.requiredData == 'Y'" ng-if="issueAddForm.input.$error.required" ng-if="issueAddForm.inputValue.$error.required" translate="issue.pleaseEnterIssueTypeCustomFields">해당 사용자정의필드는 필수 입력 값 입니다. </small> </div> <div ng-switch-when="NUMBER"> <input type="text" class="form-control input-sm" name="number" name="numberType" ng-model="issueCustomField.useValues" maxlength="100" autocomplete="off" kr-input ng-pattern="/^[0-9]*$/" placeholder="숫자만 입력 가능합니다." ng-required="issueCustomField.fieldOption == '01' || issueCustomField.customFieldVo.requiredData == 'Y'"> <small class="help-block form-text text-danger" ng-show="issueCustomField.customFieldVo.requiredData == 'Y'" ng-if="issueAddForm.number.$error.required" ng-if="issueAddForm.numberType.$error.required" translate="issue.pleaseEnterIssueTypeCustomFields">해당 사용자 정의 필드는 필수 입력 값 입니다. </small> <div ng-show="issueAddForm.numberType.$error.pattern" class="help-block form-text text-danger" translate="common.invalidNumberFormat">숫자만 입력 가능합니다. </div> </div> <div ng-switch-when="DATETIME"> <input type="text" class="form-control input-sm" <input class="form-control input-sm input-readonly" name="dateTime" ng-model="issueCustomField.useValues" maxlength="100" autocomplete="off" placeholder="{{'issue.clickToSelectDate' | translate}}" modal-form-auto-scroll range-type="singleDate" date-range-picker kr-input ng-required="issueCustomField.fieldOption == '01' || issueCustomField.customFieldVo.requiredData == 'Y'"> <small class="help-block form-text text-danger" @@ -283,15 +290,38 @@ <input type="text" class="form-control input-sm" name="ipAddress" ng-model="issueCustomField.useValues" maxlength="100" autocomplete="off" kr-input ng-pattern="/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/" placeholder="IP 주소 형식만 입력 가능합니다." ng-required="issueCustomField.fieldOption == '01' || issueCustomField.customFieldVo.requiredData == 'Y'"> <small class="help-block form-text text-danger" ng-show="issueCustomField.customFieldVo.requiredData == 'Y'" ng-if="issueAddForm.ipAddress.$error.required" translate="issue.pleaseEnterIssueTypeCustomFields">해당 사용자 정의 필드는 필수 입력 값 입니다. </small> <div ng-show="issueAddForm.ipAddress.$error.pattern" class="help-block form-text text-danger" translate="common.invalidipAdressFormat">IP주소 형식이 맞지 않습니다. </div> </div> <div ng-switch-when="EMAIL"> <input type="email" class="form-control input-sm" name="email" maxlength="30" ng-model="issueCustomField.useValues" kr-input ng-pattern="/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/" placeholder="이메일 형식만 입력 가능합니다." ng-required="issueCustomField.fieldOption == '01' || issueCustomField.customFieldVo.requiredData == 'Y'"> <small class="help-block form-text text-danger" ng-show="issueCustomField.customFieldVo.requiredData == 'Y'" ng-if="issueAddForm.ipAddress.$error.required" translate="issue.pleaseEnterIssueTypeCustomFields">해당 사용자 정의 필드는 필수 입력 값 입니다. </small> <div ng-show="issueAddForm.email.$error.pattern" class="help-block form-text text-danger" translate="common.invalidEmailFormat">이메일 형식이 맞지 않습니다. </div> </div> <div ng-switch-when="SITE"> @@ -301,27 +331,37 @@ maxlength="100" autocomplete="off" kr-input ng-pattern="/(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/" placeholder="홈페이지 주소 형식만 입력 가능합니다." ng-required="issueCustomField.fieldOption == '01' || issueCustomField.customFieldVo.requiredData == 'Y'"> <small class="help-block form-text text-danger" ng-show="issueCustomField.customFieldVo.requiredData == 'Y'" ng-if="issueAddForm.site.$error.required" translate="issue.pleaseEnterIssueTypeCustomFields">해당 사용자 정의 필드는 필수 입력 값 입니다. </small> <div ng-show="issueAddForm.site.$error.pattern" class="help-block form-text text-danger" translate="common.invalidSiteFormat">홈페이지 주소 형식이 맞지 않습니다.(http:// 또는 www 로 시작하셔야합니다) </div> </div> <div ng-switch-when="TEL"> <input type="text" class="form-control input-sm" name="tel" ng-model="issueCustomField.useValues" maxlength="100" maxlength="30" autocomplete="off" kr-input ng-pattern="/^\d{2,3}-\d{3,4}-\d{4}$/" placeholder="연락처 형식만 입력 가능합니다." ng-required="issueCustomField.fieldOption == '01' || issueCustomField.customFieldVo.requiredData == 'Y'"> <small class="help-block form-text text-danger" ng-show="issueCustomField.customFieldVo.requiredData == 'Y'" ng-if="issueAddForm.tel.$error.required" translate="issue.pleaseEnterIssueTypeCustomFields">해당 사용자 정의 필드는 필수 입력 값 입니다. </small> <div ng-show="issueAddForm.tel.$error.pattern" class="help-block form-text text-danger" translate="common.invalidTelFormat">전화번호 형식이 맞지 않습니다. </div> </div> <!-- 단일 셀렉트 --> src/main/webapp/views/issue/issueModify.html
@@ -236,7 +236,7 @@ <!-- 기본 입력 --> <div ng-switch-when="INPUT"> <input type="text" class="form-control input-sm" name="input" name="inputValue" ng-model="issueCustomField.useValues" maxlength="100" autocomplete="off" @@ -244,24 +244,29 @@ ng-required="issueCustomField.fieldOption == '01' || issueCustomField.customFieldVo.requiredData == 'Y'"> <small class="help-block form-text text-danger" ng-show="issueCustomField.customFieldVo.requiredData == 'Y'" ng-if="issueModifyForm.input.$error.required" ng-if="issueModifyForm.inputValue.$error.required" translate="issue.pleaseEnterIssueTypeCustomFields">해당 사용자정의필드는 필수 입력 값 입니다. </small> </div> <div ng-switch-when="NUMBER"> <input type="text" class="form-control input-sm" name="number" name="numberType" ng-model="issueCustomField.useValues" maxlength="100" autocomplete="off" kr-input ng-pattern="/^[0-9]*$/" placeholder="숫자만 입력 가능합니다." ng-required="issueCustomField.fieldOption == '01' || issueCustomField.customFieldVo.requiredData == 'Y'"> <small class="help-block form-text text-danger" ng-show="issueCustomField.customFieldVo.requiredData == 'Y'" ng-if="issueModifyForm.number.$error.required" ng-if="issueModifyForm.numberType.$error.required" translate="issue.pleaseEnterIssueTypeCustomFields">해당 사용자 정의 필드는 필수 입력 값 입니다. </small> <div ng-show="issueModifyForm.numberType.$error.pattern" class="help-block form-text text-danger" translate="common.invalidNumberFormat">숫자만 입력 가능합니다. </div> </div> <div ng-switch-when="DATETIME"> @@ -286,12 +291,36 @@ maxlength="100" autocomplete="off" kr-input ng-pattern="/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/" placeholder="IP 주소 형식만 입력 가능합니다." ng-required="issueCustomField.fieldOption == '01' || issueCustomField.customFieldVo.requiredData == 'Y'"> <small class="help-block form-text text-danger" ng-show="issueCustomField.customFieldVo.requiredData == 'Y'" ng-if="issueModifyForm.ipAddress.$error.required" translate="issue.pleaseEnterIssueTypeCustomFields">해당 사용자 정의 필드는 필수 입력 값 입니다. </small> <div ng-show="issueModifyForm.ipAddress.$error.pattern" class="help-block form-text text-danger" translate="common.invalidipAdressFormat">IP주소 형식이 맞지 않습니다. </div> </div> <div ng-switch-when="EMAIL"> <input type="email" class="form-control input-sm" name="email" maxlength="30" ng-model="issueCustomField.useValues" kr-input ng-pattern="/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/" placeholder="이메일 형식만 입력 가능합니다." ng-required="issueCustomField.fieldOption == '01' || issueCustomField.customFieldVo.requiredData == 'Y'"> <small class="help-block form-text text-danger" ng-show="issueCustomField.customFieldVo.requiredData == 'Y'" ng-if="issueModifyForm.ipAddress.$error.required" translate="issue.pleaseEnterIssueTypeCustomFields">해당 사용자 정의 필드는 필수 입력 값 입니다. </small> <div ng-show="issueModifyForm.email.$error.pattern" class="help-block form-text text-danger" translate="common.invalidEmailFormat">이메일 형식이 맞지 않습니다. </div> </div> <div ng-switch-when="SITE"> @@ -301,27 +330,37 @@ maxlength="100" autocomplete="off" kr-input ng-pattern="/(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/" placeholder="홈페이지 주소 형식만 입력 가능합니다." ng-required="issueCustomField.fieldOption == '01' || issueCustomField.customFieldVo.requiredData == 'Y'"> <small class="help-block form-text text-danger" ng-show="issueCustomField.customFieldVo.requiredData == 'Y'" ng-if="issueModifyForm.site.$error.required" translate="issue.pleaseEnterIssueTypeCustomFields">해당 사용자 정의 필드는 필수 입력 값 입니다. </small> <div ng-show="issueModifyForm.site.$error.pattern" class="help-block form-text text-danger" translate="common.invalidSiteFormat">홈페이지 주소 형식이 맞지 않습니다.(http://로 시작하셔야합니다) </div> </div> <div ng-switch-when="TEL"> <input type="text" class="form-control input-sm" name="tel" ng-model="issueCustomField.useValues" maxlength="100" maxlength="30" autocomplete="off" kr-input ng-pattern="/^\d{2,3}-\d{3,4}-\d{4}$/" placeholder="연락처 형식만 입력 가능합니다." ng-required="issueCustomField.fieldOption == '01' || issueCustomField.customFieldVo.requiredData == 'Y'"> <small class="help-block form-text text-danger" ng-show="issueCustomField.customFieldVo.requiredData == 'Y'" ng-if="issueModifyForm.tel.$error.required" translate="issue.pleaseEnterIssueTypeCustomFields">해당 사용자 정의 필드는 필수 입력 값 입니다. </small> <div ng-show="issueModifyForm.tel.$error.pattern" class="help-block form-text text-danger" translate="common.invalidTelFormat">전화번호 형식이 맞지 않습니다. </div> </div> <!-- 단일 셀렉트 -->