From 42d7d22a1832dbf91cafcedf872c65817401fb94 Mon Sep 17 00:00:00 2001 From: jhjang <jhjang@maprex.co.kr> Date: 월, 15 11월 2021 10:24:43 +0900 Subject: [PATCH] - api 관련 메뉴 추가 => api 토큰 생성 기능 추가 --- src/main/java/kr/wisestone/owl/domain/IssueApiDefault.java | 161 +++++ src/main/webapp/scripts/app/issueType/issueTypeList.controller.js | 7 src/main/webapp/views/api/apiAuth.html | 20 src/main/webapp/views/issueType/issueTypeAdd.html | 22 src/main/java/kr/wisestone/owl/vo/ApiTokenVo.java | 47 + src/main/java/kr/wisestone/owl/web/controller/ApiController.java | 50 + src/main/java/kr/wisestone/owl/web/form/ApiTokenForm.java | 51 + src/main/webapp/scripts/app/api/apiAuth.controller.js | 84 ++ pom.xml | 12 src/main/webapp/scripts/app/api/apiSetting.controller.js | 27 src/main/webapp/scripts/app/issueType/issueTypeAdd.controller.js | 10 src/main/resources/migration/V1_11__Alter_Table.sql | 73 ++ src/main/java/kr/wisestone/owl/domain/User.java | 23 src/main/webapp/views/api/apiOverlapAdd.html | 36 + src/main/webapp/scripts/app/api/api.js | 6 src/main/webapp/custom_components/js-workflow/js-workflow.html | 18 src/main/webapp/scripts/main.js | 1 src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java | 8 src/main/webapp/views/api/apiSetting.html | 266 -------- src/main/webapp/views/common/sidebar.html | 54 + src/main/webapp/scripts/app/customField/customFieldList.controller.js | 18 src/main/java/kr/wisestone/owl/domain/ApiToken.java | 58 + src/main/java/kr/wisestone/owl/service/impl/ApiTokenServiceImpl.java | 131 ++++ src/main/webapp/scripts/components/api/api.service.js | 29 src/main/java/kr/wisestone/owl/repository/ApiTokenRepository.java | 11 src/main/webapp/views/api/apiSettingOverlap.html | 36 + src/main/java/kr/wisestone/owl/web/condition/ApiTokenCondition.java | 54 + src/main/java/kr/wisestone/owl/service/ApiTokenService.java | 34 + src/main/webapp/scripts/app/ispField/ispField.js | 2 src/main/webapp/views/login/login.html | 2 src/main/webapp/assets/styles/main.css | 2 src/main/webapp/views/customField/customFieldAdd.html | 7 src/main/java/kr/wisestone/owl/domain/CustomFieldApiDefault.java | 73 ++ src/main/webapp/views/project/projectModify.html | 4 src/main/java/kr/wisestone/owl/domain/CustomFieldApiOverlap.java | 63 ++ src/main/java/kr/wisestone/owl/web/controller/ApiTokenController.java | 71 ++ src/main/webapp/i18n/ko/global.json | 9 src/main/webapp/scripts/app/project/projectList.controller.js | 8 src/main/webapp/WEB-INF/i18n/code_ko_KR.properties | 6 src/main/webapp/scripts/app/customField/customFieldAdd.controller.js | 6 src/main/webapp/views/api/apiSettingColumn.html | 252 ++++++++ 41 files changed, 1,544 insertions(+), 308 deletions(-) diff --git a/pom.xml b/pom.xml index 02f7d26..e76a386 100644 --- a/pom.xml +++ b/pom.xml @@ -493,6 +493,18 @@ <version>${elastic.search.version}</version> </dependency> + <!-- JWT (api token) --> + <dependency> + <groupId>javax.xml.bind</groupId> + <artifactId>jaxb-api</artifactId> + <version>2.3.1</version> + </dependency> + <dependency> + <groupId>io.jsonwebtoken</groupId> + <artifactId>jjwt</artifactId> + <version>0.9.1</version> + </dependency> + </dependencies> <repositories> diff --git a/src/main/java/kr/wisestone/owl/domain/ApiToken.java b/src/main/java/kr/wisestone/owl/domain/ApiToken.java new file mode 100644 index 0000000..dabcf4d --- /dev/null +++ b/src/main/java/kr/wisestone/owl/domain/ApiToken.java @@ -0,0 +1,58 @@ +package kr.wisestone.owl.domain; + +import javax.persistence.*; +import java.io.Serializable; + +@Entity +public class ApiToken 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; + + private String appName; + private String token; + + public ApiToken(){} + + 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 String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } +} diff --git a/src/main/java/kr/wisestone/owl/domain/CustomFieldApiDefault.java b/src/main/java/kr/wisestone/owl/domain/CustomFieldApiDefault.java new file mode 100644 index 0000000..7223cee --- /dev/null +++ b/src/main/java/kr/wisestone/owl/domain/CustomFieldApiDefault.java @@ -0,0 +1,73 @@ +package kr.wisestone.owl.domain; + +import javax.persistence.*; +import java.io.Serializable; + +@Entity +public class CustomFieldApiDefault 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 = "issue_type_id") + private IssueType issueType; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "custom_field_id") + private CustomField customField; + + private String customFieldValue; + + public CustomFieldApiDefault(){} + + 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 CustomField getCustomField() { + return customField; + } + + public void setCustomField(CustomField customField) { + this.customField = customField; + } + + public String getCustomFieldValue() { + return customFieldValue; + } + + public void setCustomFieldValue(String customFieldValue) { + this.customFieldValue = customFieldValue; + } +} diff --git a/src/main/java/kr/wisestone/owl/domain/CustomFieldApiOverlap.java b/src/main/java/kr/wisestone/owl/domain/CustomFieldApiOverlap.java new file mode 100644 index 0000000..49bc65d --- /dev/null +++ b/src/main/java/kr/wisestone/owl/domain/CustomFieldApiOverlap.java @@ -0,0 +1,63 @@ +package kr.wisestone.owl.domain; + +import javax.persistence.*; +import java.io.Serializable; + +@Entity +public class CustomFieldApiOverlap 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 = "issue_type_id") + private IssueType issueType; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "custom_field_id") + private CustomField customField; + + public CustomFieldApiOverlap(){} + + 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 CustomField getCustomField() { + return customField; + } + + public void setCustomField(CustomField customField) { + this.customField = customField; + } +} diff --git a/src/main/java/kr/wisestone/owl/domain/IssueApiDefault.java b/src/main/java/kr/wisestone/owl/domain/IssueApiDefault.java new file mode 100644 index 0000000..f32fdaa --- /dev/null +++ b/src/main/java/kr/wisestone/owl/domain/IssueApiDefault.java @@ -0,0 +1,161 @@ +package kr.wisestone.owl.domain; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; + +@Entity +public class IssueApiDefault 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 = "issue_type_id") + private IssueType issueType; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "issue_status_id") + private IssueStatus issueStatus; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "project_id") + private Project project; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "priority_id") + private Priority priority; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "severity_id") + private Severity severity; + + private String title; + private String description; + + private Long reverseIndex; + private Long issue_number; + + @Temporal(TemporalType.TIMESTAMP) + private Date start_date; + + @Temporal(TemporalType.TIMESTAMP) + private Date complete_date; + + + public IssueApiDefault(){} + + 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 IssueStatus getIssueStatus() { + return issueStatus; + } + + public void setIssueStatus(IssueStatus issueStatus) { + this.issueStatus = issueStatus; + } + + public Project getProject() { + return project; + } + + public void setProject(Project project) { + this.project = project; + } + + public Priority getPriority() { + return priority; + } + + public void setPriority(Priority priority) { + this.priority = priority; + } + + public Severity getSeverity() { + return severity; + } + + public void setSeverity(Severity severity) { + this.severity = severity; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Long getReverseIndex() { + return reverseIndex; + } + + public void setReverseIndex(Long reverseIndex) { + this.reverseIndex = reverseIndex; + } + + public Long getIssue_number() { + return issue_number; + } + + public void setIssue_number(Long issue_number) { + this.issue_number = issue_number; + } + + public Date getStart_date() { + return start_date; + } + + public void setStart_date(Date start_date) { + this.start_date = start_date; + } + + public Date getComplete_date() { + return complete_date; + } + + public void setComplete_date(Date complete_date) { + this.complete_date = complete_date; + } +} diff --git a/src/main/java/kr/wisestone/owl/domain/User.java b/src/main/java/kr/wisestone/owl/domain/User.java index 679b680..f86c285 100644 --- a/src/main/java/kr/wisestone/owl/domain/User.java +++ b/src/main/java/kr/wisestone/owl/domain/User.java @@ -19,6 +19,9 @@ public static final String DEFAULT_RESERVATION_NOTIFY_TIME = "09:00"; // 湲곕낯 �씠硫붿씪 �븣由� �삁�젙 �떆媛� public static final String DEFAULT_LANGUAGE = "ko"; // 湲곕낯 �뼵�뼱 + public static final String INSERT_TYPE_NORMAL = "N"; // 異붽� ���엯(�씪諛�) + public static final String INSERT_TYPE_API = "A"; // 異붽� ���엯(API) + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -37,6 +40,7 @@ private String reservationNotifyTime; // �씠硫붿씪 �븣由� �떆媛� �삁�젙 private String language; private String licensekey; + private String insertType = User.INSERT_TYPE_NORMAL; @OneToMany(mappedBy = "user", cascade = {CascadeType.ALL}, orphanRemoval = true) private Set<SystemRoleUser> systemRoleUsers = new HashSet<>(); @@ -62,6 +66,9 @@ @ManyToOne(targetEntity = UserLevel.class, fetch = FetchType.LAZY) @JoinColumn(name="level_id") private UserLevel userLevel; + + @OneToMany(mappedBy = "user", cascade = {CascadeType.ALL}, orphanRemoval = true) + private Set<ApiToken> apiTokens = new HashSet<>(); // @ManyToOne(targetEntity = Department.class, fetch = FetchType.LAZY) // @JoinColumn(name="department_id") @@ -204,6 +211,14 @@ this.projectRoleUsers = projectRoleUsers; } + public String getInsertType() { + return insertType; + } + + public void setInsertType(String insertType) { + this.insertType = insertType; + } + public void addProjectRole(ProjectRole projectRole) { if (this.projectRoleUsers == null) { this.projectRoleUsers = new HashSet<>(); @@ -312,6 +327,14 @@ this.licensekey = licensekey; } + public Set<ApiToken> getApiTokens() { + return apiTokens; + } + + public void setApiTokens(Set<ApiToken> apiTokens) { + this.apiTokens = apiTokens; + } + @Override public Collection<? extends GrantedAuthority> getAuthorities() { // TODO Auto-generated method stub diff --git a/src/main/java/kr/wisestone/owl/repository/ApiTokenRepository.java b/src/main/java/kr/wisestone/owl/repository/ApiTokenRepository.java new file mode 100644 index 0000000..c959847 --- /dev/null +++ b/src/main/java/kr/wisestone/owl/repository/ApiTokenRepository.java @@ -0,0 +1,11 @@ +package kr.wisestone.owl.repository; + +import kr.wisestone.owl.domain.ApiToken; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface ApiTokenRepository extends JpaRepository<ApiToken, Long> { + List<ApiToken> findByUserId(@Param("userId") Long userId); +} diff --git a/src/main/java/kr/wisestone/owl/service/ApiTokenService.java b/src/main/java/kr/wisestone/owl/service/ApiTokenService.java new file mode 100644 index 0000000..d1d58e3 --- /dev/null +++ b/src/main/java/kr/wisestone/owl/service/ApiTokenService.java @@ -0,0 +1,34 @@ +package kr.wisestone.owl.service; + +import kr.wisestone.owl.domain.ApiToken; +import kr.wisestone.owl.domain.CompanyField; +import kr.wisestone.owl.domain.CustomField; +import kr.wisestone.owl.domain.Event; +import kr.wisestone.owl.vo.ApiTokenVo; +import kr.wisestone.owl.vo.CompanyFieldVo; +import kr.wisestone.owl.vo.EventVo; +import kr.wisestone.owl.web.condition.ApiTokenCondition; +import kr.wisestone.owl.web.condition.CompanyFieldCondition; +import kr.wisestone.owl.web.condition.EventCondition; +import kr.wisestone.owl.web.form.ApiTokenForm; +import kr.wisestone.owl.web.form.CompanyFieldForm; +import kr.wisestone.owl.web.form.DepartmentForm; +import kr.wisestone.owl.web.form.EventForm; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Service; +import org.springframework.ui.Model; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +public interface ApiTokenService extends AbstractService<ApiToken, Long, JpaRepository<ApiToken, Long>> { + ApiToken add(ApiTokenForm apiTokenForm); + + ApiTokenVo find(); + + void remove(ApiTokenForm apiTokenForm); +} diff --git a/src/main/java/kr/wisestone/owl/service/impl/ApiTokenServiceImpl.java b/src/main/java/kr/wisestone/owl/service/impl/ApiTokenServiceImpl.java new file mode 100644 index 0000000..d7d4039 --- /dev/null +++ b/src/main/java/kr/wisestone/owl/service/impl/ApiTokenServiceImpl.java @@ -0,0 +1,131 @@ +package kr.wisestone.owl.service.impl; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import kr.wisestone.owl.domain.ApiToken; +import kr.wisestone.owl.domain.User; +import kr.wisestone.owl.repository.ApiTokenRepository; +import kr.wisestone.owl.service.ApiTokenService; +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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Service; +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.util.List; +import java.lang.Long; +import com.fasterxml.jackson.databind.ObjectMapper; + +@Service +public class ApiTokenServiceImpl extends AbstractServiceImpl<ApiToken, Long, JpaRepository<ApiToken, Long>> implements ApiTokenService { + + private static final String ENCRYPT_STRING = "mpxowl"; + private static final String DATA_KEY = "user"; + + static final Logger log = LoggerFactory.getLogger(ApiTokenServiceImpl.class); + + @Autowired + private ApiTokenRepository apiTokenRepository; + + + @Autowired + protected WebAppUtil webAppUtil; + + // �넗�겙 �깮�꽦 + @Override + public ApiToken add(ApiTokenForm apiTokenForm) { + ApiToken apiToken = ConvertUtil.copyProperties(apiTokenForm, ApiToken.class); + String appName = apiToken.getAppName(); + apiToken.setUser(this.webAppUtil.getLoginUserObject()); + + // 湲곗〈 �넗�겙 �궘�젣 + this.remove(null); + + UserVo user = this.webAppUtil.getLoginUser(); + if (appName != null && !appName.isEmpty()) { + Long currentTime = System.currentTimeMillis(); + Date now = new Date(currentTime); + String token = Jwts.builder() + .setSubject(appName) + .setHeaderParam("typ", "JWT") + .setExpiration(DateUtil.addDays(now, 36500)) + .setIssuedAt(now) + .claim(DATA_KEY, user) + .signWith(SignatureAlgorithm.HS256, this.generateKey()) + .compact(); + + apiToken.setToken(token); + } + + return this.apiTokenRepository.save(apiToken); + } + + // �궎 �깮�꽦 + private byte[] generateKey(){ + byte[] key = null; + try { + key = ENCRYPT_STRING.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + log.error("Making secret Key Error :: ", e); + } + + System.out.println("鍮꾨� key : " + key); + + return key; + } + + //JWT 蹂듯샇�솕 + public UserVo getUser(String jwt) { + + //寃곌낵媛� = Claims + Jws<Claims> claims = null; + + try { + //鍮꾨��궎瑜� �씠�슜�빐�꽌 蹂듯샇�솕 �븯�뒗 �옉�뾽 + claims = Jwts.parser() + .setSigningKey(this.generateKey()) + .parseClaimsJws(jwt); + + } catch (Exception e) { + log.debug(e.getMessage(), e); + } + + ObjectMapper objectMapper = new ObjectMapper(); + //諛섑솚 ���엯�� LinkedHashMap �씠�떎. �씠瑜� User ���엯�쑝濡� 蹂��솚�븯湲� �쐞�빐 ObjectMapper �궗�슜 + return objectMapper.convertValue(claims.getBody().get(DATA_KEY), UserVo.class); + } + + // �넗�겙 議고쉶 + @Override + public ApiTokenVo find() { + User user = this.webAppUtil.getLoginUserObject(); + List<ApiToken> apiTokens = this.apiTokenRepository.findByUserId(user.getId()); + if (apiTokens != null && apiTokens.size() >0 ) { + return ConvertUtil.copyProperties(apiTokens.get(0), ApiTokenVo.class); + } + return null; + } + + // �넗�겙 �궘�젣 + @Override + public void remove(ApiTokenForm apiTokenForm) { + ApiTokenVo apiTokenVo = this.find(); + if (apiTokenVo != null) { + this.apiTokenRepository.deleteById(apiTokenVo.getId()); + } + } + + @Override + protected JpaRepository<ApiToken, Long> getRepository() { + return this.apiTokenRepository; + } +} diff --git a/src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java b/src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java index 7b14f1d..c32c1ee 100644 --- a/src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java +++ b/src/main/java/kr/wisestone/owl/service/impl/IssueTypeServiceImpl.java @@ -75,16 +75,16 @@ switch (projectType) { case BTS_PROJECT: - issueTypes.add(new IssueType(workspace, workflow, this.messageAccessor.message("common.bug"), "", "#ff5f99")); // 踰꾧렇 - issueTypes.add(new IssueType(workspace, workflow, this.messageAccessor.message("common.improvement"), "", "#3598fe")); // 媛쒖꽑 + issueTypes.add(new IssueType(workspace, workflow, "�븙�꽦 �룄硫붿씤", "", "#ff5f99")); // 踰꾧렇 + issueTypes.add(new IssueType(workspace, workflow, "寃쎌쑀吏� ���쓳", "", "#3598fe")); // 媛쒖꽑 break; case RMS_PROJECT: - issueTypes.add(new IssueType(workspace, workflow, this.messageAccessor.message("common.requirement"), "", "#3bcde2")); // �슂援� �궗�빆 + issueTypes.add(new IssueType(workspace, workflow, "�쑀�룷吏� ���쓳", "", "#3bcde2")); // �슂援� �궗�빆 break; case TCM_PROJECT: - issueTypes.add(new IssueType(workspace, workflow, this.messageAccessor.message("common.testcase"), "", "#008ca7")); // �뀒�뒪�듃 耳��씠�뒪, �떎�뻾 �닚�꽌, �쟾�젣 議곌굔, 湲곕� 寃곌낵 + issueTypes.add(new IssueType(workspace, workflow, "遺꾩꽍寃곌낵 ���쓳", "", "#008ca7")); // �뀒�뒪�듃 耳��씠�뒪, �떎�뻾 �닚�꽌, �쟾�젣 議곌굔, 湲곕� 寃곌낵 break; } diff --git a/src/main/java/kr/wisestone/owl/vo/ApiTokenVo.java b/src/main/java/kr/wisestone/owl/vo/ApiTokenVo.java new file mode 100644 index 0000000..26bee0f --- /dev/null +++ b/src/main/java/kr/wisestone/owl/vo/ApiTokenVo.java @@ -0,0 +1,47 @@ +package kr.wisestone.owl.vo; + +import com.google.common.collect.Lists; +import kr.wisestone.owl.domain.User; + +import java.util.List; + +public class ApiTokenVo extends BaseVo{ + private Long id; + private User user; + private String appName; + private String token; + + public ApiTokenVo(){} + + 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 String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } +} diff --git a/src/main/java/kr/wisestone/owl/web/condition/ApiTokenCondition.java b/src/main/java/kr/wisestone/owl/web/condition/ApiTokenCondition.java new file mode 100644 index 0000000..57b006d --- /dev/null +++ b/src/main/java/kr/wisestone/owl/web/condition/ApiTokenCondition.java @@ -0,0 +1,54 @@ +package kr.wisestone.owl.web.condition; + +import kr.wisestone.owl.domain.User; +import kr.wisestone.owl.util.CommonUtil; +import kr.wisestone.owl.util.ConvertUtil; +import kr.wisestone.owl.util.DateUtil; +import kr.wisestone.owl.util.MapUtil; +import org.springframework.util.StringUtils; + +import javax.persistence.*; +import java.util.Date; +import java.util.List; +import java.util.Map; + +public class ApiTokenCondition { + private Long id; + private User user; + private String appName; + private String token; + + public ApiTokenCondition(){} + + 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 String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } +} diff --git a/src/main/java/kr/wisestone/owl/web/controller/ApiController.java b/src/main/java/kr/wisestone/owl/web/controller/ApiController.java new file mode 100644 index 0000000..ed640c5 --- /dev/null +++ b/src/main/java/kr/wisestone/owl/web/controller/ApiController.java @@ -0,0 +1,50 @@ +package kr.wisestone.owl.web.controller; + +import kr.wisestone.owl.constant.Constants; +import kr.wisestone.owl.service.GuideService; +import kr.wisestone.owl.web.condition.GuideCondition; +import kr.wisestone.owl.web.form.GuideForm; +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; + +@Controller +public class ApiController extends BaseController { + + @Autowired + private GuideService guideService; + + // �씠�뒋 異붽� + @RequestMapping(value = "/api/add", produces = MediaType.APPLICATION_JSON_VALUE) + public + @ResponseBody + Map<String, Object> add(@RequestBody Map<String, Map<String, Object>> params) { + Map<String, Object> resJsonData = new HashMap<>(); + + // todo + + return this.setSuccessMessage(resJsonData); + } + + // �씠�뒋 議고쉶 + @RequestMapping(value = "/api/find", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) + public + @ResponseBody + Map<String, Object> find(@RequestBody Map<String, Map<String, Object>> params) { + Map<String, Object> resJsonData = new HashMap<>(); + Pageable pageable = this.pageUtil.convertPageable(this.getPageVo(params)); + + // todo + + return this.setSuccessMessage(resJsonData); + } +} + diff --git a/src/main/java/kr/wisestone/owl/web/controller/ApiTokenController.java b/src/main/java/kr/wisestone/owl/web/controller/ApiTokenController.java new file mode 100644 index 0000000..6e45b8a --- /dev/null +++ b/src/main/java/kr/wisestone/owl/web/controller/ApiTokenController.java @@ -0,0 +1,71 @@ +package kr.wisestone.owl.web.controller; + +import kr.wisestone.owl.constant.Constants; +import kr.wisestone.owl.domain.ApiToken; +import kr.wisestone.owl.service.ApiTokenService; +import kr.wisestone.owl.util.ConvertUtil; +import kr.wisestone.owl.vo.ApiTokenVo; +import kr.wisestone.owl.web.condition.ApiTokenCondition; +import kr.wisestone.owl.web.form.ApiTokenForm; +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.List; +import java.util.Map; + +@Controller +public class ApiTokenController extends BaseController { + + @Autowired + private ApiTokenService apiTokenService; + + // �넗�겙 �깮�꽦 + @RequestMapping(value = "/apiToken/add", produces = MediaType.APPLICATION_JSON_VALUE) + public + @ResponseBody + Map<String, Object> add(@RequestBody Map<String, Map<String, Object>> params) { + Map<String, Object> resJsonData = new HashMap<>(); + + ApiTokenForm form = ConvertUtil.convertMapToClass(params.get(Constants.REQ_KEY_CONTENT), ApiTokenForm.class); + + ApiToken apiToken = apiTokenService.add(form); + resJsonData.put(Constants.RES_KEY_CONTENTS, ConvertUtil.copyProperties(apiToken, ApiTokenVo.class)); + + return this.setSuccessMessage(resJsonData); + } + + // �넗�겙 議고쉶 + @RequestMapping(value = "/apiToken/find", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) + public + @ResponseBody + Map<String, Object> find(@RequestBody Map<String, Map<String, Object>> params) { + Map<String, Object> resJsonData = new HashMap<>(); + Pageable pageable = this.pageUtil.convertPageable(this.getPageVo(params)); + + ApiTokenVo token = this.apiTokenService.find(); + resJsonData.put(Constants.RES_KEY_CONTENTS, token); + + return this.setSuccessMessage(resJsonData); + } + + // �넗�겙 �궘�젣 + @RequestMapping(value = "/apiToken/remove", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) + public + @ResponseBody + Map<String, Object> remove(@RequestBody Map<String, Map<String, Object>> params) { + Map<String, Object> resJsonData = new HashMap<>(); + + ApiTokenForm apiTokenForm = ConvertUtil.convertMapToClass(params.get(Constants.REQ_KEY_CONTENT), ApiTokenForm.class); + this.apiTokenService.remove(apiTokenForm); + + return this.setSuccessMessage(resJsonData); + } +} + diff --git a/src/main/java/kr/wisestone/owl/web/form/ApiTokenForm.java b/src/main/java/kr/wisestone/owl/web/form/ApiTokenForm.java new file mode 100644 index 0000000..ab0b978 --- /dev/null +++ b/src/main/java/kr/wisestone/owl/web/form/ApiTokenForm.java @@ -0,0 +1,51 @@ +package kr.wisestone.owl.web.form; + +import com.google.common.collect.Lists; +import kr.wisestone.owl.domain.User; +import kr.wisestone.owl.util.ConvertUtil; +import kr.wisestone.owl.util.MapUtil; + +import java.util.List; +import java.util.Map; + +public class ApiTokenForm { + private Long id; + private User user; + private String appName; + private String token; + + public ApiTokenForm() { + } + + 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 String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } +} diff --git a/src/main/resources/migration/V1_11__Alter_Table.sql b/src/main/resources/migration/V1_11__Alter_Table.sql index bb9d896..e8b5010 100644 --- a/src/main/resources/migration/V1_11__Alter_Table.sql +++ b/src/main/resources/migration/V1_11__Alter_Table.sql @@ -52,4 +52,75 @@ `modify_id` BIGINT(20) NOT NULL, `modify_date` TIMESTAMP NULL, PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + + +-- api 愿��젴 +ALTER TABLE `user` ADD COLUMN `insert_type` VARCHAR(1) NOT NULL DEFAULT 'N'; + +CREATE TABLE `api_token`( + `id` BIGINT(11) AUTO_INCREMENT, + `user_id` BIGINT(50) NOT NULL, + `app_name` VARCHAR(50) NOT NULL, + `token` VARCHAR(1024) NOT NULL, + `register_id` BIGINT(20) NOT NULL, + `register_date` TIMESTAMP NULL, + `modify_id` BIGINT(20) NOT NULL, + `modify_date` TIMESTAMP NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `userIdIndex` (`user_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `issue_api_default`( + `id` BIGINT(11) AUTO_INCREMENT, + `user_id` BIGINT(11) NOT NULL, + `issue_type_id` bigint(11) NOT NULL, + `issue_status_id` bigint(20) DEFAULT NULL, + `project_id` bigint(20) DEFAULT NULL, + `priority_id` bigint(20) DEFAULT NULL, + `severity_id` bigint(20) DEFAULT NULL, + `title` varchar(300) DEFAULT NULL, + `description` mediumtext COMMENT 'description', + `reverse_index` bigint(20) DEFAULT NULL, + `issue_number` bigint(20) DEFAULT NULL, + `start_date` varchar(20) DEFAULT NULL, + `complete_date` varchar(20) DEFAULT NULL, + `register_id` BIGINT(20) NOT NULL, + `register_date` TIMESTAMP NULL, + `modify_id` BIGINT(20) NOT NULL, + `modify_date` TIMESTAMP NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `userIdIndex` (`user_id`) USING BTREE, + INDEX `issueTypeIdIndex` (`issue_type_id`) USING BTREE + +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `custom_field_api_default`( + `id` BIGINT(11) AUTO_INCREMENT, + `user_id` BIGINT(11) NOT NULL, + `issue_type_id` BIGINT(11) NOT NULL, + `custom_field_id` BIGINT(11) NOT NULL, + `custom_field_value` varchar(300) NOT NULL, + `register_id` BIGINT(20) NOT NULL, + `register_date` TIMESTAMP NULL, + `modify_id` BIGINT(20) NOT NULL, + `modify_date` TIMESTAMP NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `userIdIndex` (`user_id`) USING BTREE, + INDEX `issueTypeIdIndex` (`issue_type_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `custom_field_api_overlap`( + `id` BIGINT(11) AUTO_INCREMENT, + `user_id` BIGINT(11) NOT NULL, + `issue_type_id` BIGINT(11) NOT NULL, + `custom_field_id` BIGINT(11) NOT NULL, + `register_id` BIGINT(20) NOT NULL, + `register_date` TIMESTAMP NULL, + `modify_id` BIGINT(20) NOT NULL, + `modify_date` TIMESTAMP NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `userIdIndex` (`user_id`) USING BTREE, + INDEX `issueTypeIdIndex` (`issue_type_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + diff --git a/src/main/webapp/WEB-INF/i18n/code_ko_KR.properties b/src/main/webapp/WEB-INF/i18n/code_ko_KR.properties index 069a473..090f28b 100644 --- a/src/main/webapp/WEB-INF/i18n/code_ko_KR.properties +++ b/src/main/webapp/WEB-INF/i18n/code_ko_KR.properties @@ -75,6 +75,12 @@ common.stringField=\uBB38\uC790\uC5F4 \uD544\uB4DC common.singleSelectionField=\uB2E8\uC77C \uC120\uD0DD \uD544\uB4DC common.multipleSelectionField=\uB2E4\uC911 \uC120\uD0DD \uD544\uB4DC +common.numberField=\uC22B\uC790 \uD544\uB4DC +common.datetimeField=\uB0A0\uC9DC \uD544\uB4DC +common.ipAddressField=IP \uC8FC\uC18C \uD544\uB4DC +common.emailField=\uC774\uBA54\uC77C \uD544\uB4DC +common.siteField=\uD648\uD398\uC774\uC9C0 \uD544\uB4DC +common.telField=\uC804\uD654\uBC88\uD638 \uD544\uB4DC common.customField=\uC0AC\uC6A9\uC790 \uC815\uC758 \uD544\uB4DC common.customFieldList=\uC0AC\uC6A9\uC790 \uC815\uC758 \uD544\uB4DC \uBAA9\uB85D common.fieldType=\uD544\uB4DC \uC720\uD615 diff --git a/src/main/webapp/assets/styles/main.css b/src/main/webapp/assets/styles/main.css index c336ec9..7a8dce6 100644 --- a/src/main/webapp/assets/styles/main.css +++ b/src/main/webapp/assets/styles/main.css @@ -5162,7 +5162,7 @@ }*/ .modal-open { - overflow: hidden + overflow: auto } .modal { diff --git a/src/main/webapp/custom_components/js-workflow/js-workflow.html b/src/main/webapp/custom_components/js-workflow/js-workflow.html index 298aa36..38e42de 100644 --- a/src/main/webapp/custom_components/js-workflow/js-workflow.html +++ b/src/main/webapp/custom_components/js-workflow/js-workflow.html @@ -59,6 +59,24 @@ </div> </div> </div> + + <div class="form-group"> + <label><span translate="project.projectDepartment">�떞�떦 遺��꽌</span></label> + <div class="input-group"> + <select class="form-control input-sm issue-select-label" + name="targetStatusId" + ng-style="{ 'color' : fn.getOptionColor(vm.targetIssueStatusList, vm.targetStatusId) }" + ng-model="vm.targetStatusId"> + <option value="" translate="common.choose">�꽑�깮�븯�꽭�슂.</option> + <option value="{{issueStatus.id}}" + ng-style="{ 'color' : issueStatus.color, 'font-weight': 600 }" + ng-repeat="issueStatus in vm.targetIssueStatusList"> + �뿈 {{issueStatus.name}} + </option> + </select> + </div> + </div> + </div> <div class="col-md-9"> <div class="form-group workflowbox"> diff --git a/src/main/webapp/i18n/ko/global.json b/src/main/webapp/i18n/ko/global.json index 238522f..05bd9b9 100644 --- a/src/main/webapp/i18n/ko/global.json +++ b/src/main/webapp/i18n/ko/global.json @@ -786,7 +786,14 @@ "delete" : "�넗�겙 �궘�젣", "create" : "�넗�겙 �깮�꽦", "example" : "�궗�슜 �삁�떆", - "columnSetting" : "湲곕낯媛� �꽕�젙" + "columnSetting" : "湲곕낯媛� �꽕�젙", + "overlapSetting" : "以묐났 �븘�뱶 �꽕�젙", + "addOverlapField" : "以묐났 �븘�뱶 異붽�", + "failedToApiTokenFind" : "API �넗�겙 議고쉶 �떎�뙣", + "failedToApiTokenRemove" : "API �넗�겙 �궘�젣 �떎�뙣", + "failedToApiTokenAdd" : "API �넗�겙 �깮�꽦 �떎�뙣", + "successToApiTokenRemove" : "API �넗�겙 �궘�젣 �꽦怨�", + "successToApiTokenAdd" : "API �넗�겙 �깮�꽦 �꽦怨�" }, "companyField" : { "add" : "�뾽泥� �깮�꽦", diff --git a/src/main/webapp/scripts/app/api/api.js b/src/main/webapp/scripts/app/api/api.js index d25f981..3449369 100644 --- a/src/main/webapp/scripts/app/api/api.js +++ b/src/main/webapp/scripts/app/api/api.js @@ -33,7 +33,7 @@ loadController : ["$q", function ($q) { var deferred = $q.defer(); require(["apiAuthController", - , 'formSubmit', 'jsShortCut', 'inputRegex'], function () { + "apiService", 'formSubmit', 'jsShortCut', 'inputRegex'], function () { deferred.resolve(); }); @@ -52,7 +52,7 @@ loadController : ["$q", function ($q) { var deferred = $q.defer(); require(["apiSettingController", - , 'formSubmit', 'jsShortCut', 'inputRegex'], function () { + "apiService", 'formSubmit', 'jsShortCut', 'inputRegex'], function () { deferred.resolve(); }); @@ -71,7 +71,7 @@ loadController : ["$q", function ($q) { var deferred = $q.defer(); require(["apiMonitorController", - , 'formSubmit', 'jsShortCut', 'inputRegex'], function () { + "apiService", 'formSubmit', 'jsShortCut', 'inputRegex'], function () { deferred.resolve(); }); diff --git a/src/main/webapp/scripts/app/api/apiAuth.controller.js b/src/main/webapp/scripts/app/api/apiAuth.controller.js index 9640d25..fb542b1 100644 --- a/src/main/webapp/scripts/app/api/apiAuth.controller.js +++ b/src/main/webapp/scripts/app/api/apiAuth.controller.js @@ -7,20 +7,94 @@ 'app', 'angular' ], function (app, angular) { - app.controller('apiAuthController', ['$scope', '$rootScope', '$log', '$resourceProvider', 'SweetAlert', '$timeout', '$filter', - function ($scope, $rootScope, $log, $resourceProvider, SweetAlert, $timeout, $filter) { + app.controller('apiAuthController', ['$scope', '$rootScope', '$log', '$resourceProvider', '$state', 'Api', 'SweetAlert', '$timeout', '$filter', + function ($scope, $rootScope, $log, $resourceProvider, $state, Api, SweetAlert, $timeout, $filter) { $scope.fn = { - + formSubmit : formSubmit, + remove : remove, + find : find, + formCheck : formCheck }; $scope.vm = { + responseData : { + data : [] + }, form : { - name : "�솃�럹�씠吏� 蹂�議� �깘吏� �떆�뒪�뀥", - token : "77751b541212de21a44f87024174d3bd" + appName : "", + token : "" } }; + // �뤌 泥댄겕 + function formCheck(formInvalid) { + if (formInvalid) { + return true; + } + + return false; + } + + function formSubmit() { + var conditions = { + appName : $scope.vm.form.appName + } + + Api.add($resourceProvider.getContent(conditions, + $resourceProvider.getPageContent(0, 1))).then(function (result) { + + if (result.data.message.status === "success") { + if (angular.isDefined(result.data.data)) { + $scope.vm.form.token = result.data.data.token; + } + SweetAlert.swal($filter("translate")("api.successToApiTokenAdd"), result.data.message.message, "success"); // "api �넗�겙 �깮�꽦 �꽦怨�" + } + else { + SweetAlert.swal($filter("translate")("api.failedToApiTokenAdd"), result.data.message.message, "error"); // "api �넗�겙 �깮�꽦 �떎�뙣" + } + }); + } + + function remove() { + var content = { + id : "" + } + + Api.remove($resourceProvider.getContent(content, + $resourceProvider.getPageContent(0, 1))).then(function (result) { + + if (result.data.message.status === "success") { + $scope.vm.form.token = ""; + SweetAlert.swal($filter("translate")("api.successToApiTokenRemove"), result.data.message.message, "success"); // "api �넗�겙 �깮�꽦 �꽦怨�" + } + else { + SweetAlert.swal($filter("translate")("api.failedToApiTokenRemove"), result.data.message.message, "error"); // "api �넗�겙 �궘�젣 �떎�뙣" + } + }); + } + + function find() { + var conditions = { + appName : $scope.vm.form.appName + } + + Api.find($resourceProvider.getContent(conditions, + $resourceProvider.getPageContent(0, 1))).then(function (result) { + + if (result.data.message.status === "success") { + if (result.data.data != null) { + $scope.vm.form.appName = result.data.data.appName; + $scope.vm.form.token = result.data.data.token; + } + } + else { + SweetAlert.swal($filter("translate")("api.failedToApiTokenFind"), result.data.message.message, "error"); // "api �넗�겙 議고쉶 �떎�뙣" + } + }); + } + + $scope.fn.find(); }]); }); diff --git a/src/main/webapp/scripts/app/api/apiSetting.controller.js b/src/main/webapp/scripts/app/api/apiSetting.controller.js index 38e3b7c..db6427d 100644 --- a/src/main/webapp/scripts/app/api/apiSetting.controller.js +++ b/src/main/webapp/scripts/app/api/apiSetting.controller.js @@ -7,19 +7,40 @@ 'app', 'angular' ], function (app, angular) { - app.controller('apiSettingController', ['$scope', '$rootScope', '$log', '$resourceProvider', 'SweetAlert', '$timeout', '$filter', - function ($scope, $rootScope, $log, $resourceProvider, SweetAlert, $timeout, $filter) { + app.controller('apiSettingController', ['$scope', '$rootScope', '$log', '$resourceProvider','$uibModal', 'SweetAlert', '$timeout', '$filter', + function ($scope, $rootScope, $log, $resourceProvider, $uibModal, SweetAlert, $timeout, $filter) { $scope.fn = { - + changeTab : changeTab, + add : add, }; $scope.vm = { + tab : "API_COL_SETTING", form : { } }; + // �깮�꽦 �뙘�뾽 + function add() { + $uibModal.open({ + templateUrl : 'views/api/apiOverlapAdd.html', + size : "sm", + // controller : 'apiOverlapAddController', + backdrop : 'static' + }); + } + + function changeTab(tab) { + $scope.vm.tab = tab; + + if (tab === "API_COL_SETTING") { + $rootScope.$broadcast("changeColumnSettingTab"); + } else if (tab === "API_OVERLAP_SETTING") { + $rootScope.$broadcast("changeOverlapSettingTab"); + } + } }]); }); diff --git a/src/main/webapp/scripts/app/customField/customFieldAdd.controller.js b/src/main/webapp/scripts/app/customField/customFieldAdd.controller.js index 4edbe60..0107228 100644 --- a/src/main/webapp/scripts/app/customField/customFieldAdd.controller.js +++ b/src/main/webapp/scripts/app/customField/customFieldAdd.controller.js @@ -69,7 +69,8 @@ if (!duplication) { if (!$rootScope.isDefined($scope.vm.form.optionText)) { $scope.vm.form.optionText = ""; - SweetAlert.warning($filter("translate")("customField.emptyInputValue"), $filter("translate")("customField.emptyAddValue")); // �엯�젰 媛� �솗�씤 �븣由�, �엯�젰�븳 媛믪씠 �뾾�뒿�땲�떎. + SweetAlert.warning($filter("translate")("customField.emptyInputValue"), + $filter("translate")("customField.emptyAddValue")); // �엯�젰 媛� �솗�씤 �븣由�, �엯�젰�븳 媛믪씠 �뾾�뒿�땲�떎. return; } $scope.vm.form.options.push($scope.vm.form.optionText); @@ -81,7 +82,8 @@ }, 200); } else { - SweetAlert.warning($filter("translate")("customField.duplicateInputValue"), $filter("translate")("customField.alreadyAddedValue")); // "�엯�젰 媛� 以묐났 �븣由�", "�엯�젰�븳 媛믪씠 �씠誘� 異붽��릺�뼱 �엳�뒿�땲�떎." + SweetAlert.warning($filter("translate")("customField.duplicateInputValue"), + $filter("translate")("customField.alreadyAddedValue")); // "�엯�젰 媛� 以묐났 �븣由�", "�엯�젰�븳 媛믪씠 �씠誘� 異붽��릺�뼱 �엳�뒿�땲�떎." } } diff --git a/src/main/webapp/scripts/app/customField/customFieldList.controller.js b/src/main/webapp/scripts/app/customField/customFieldList.controller.js index 98204af..f731aae 100644 --- a/src/main/webapp/scripts/app/customField/customFieldList.controller.js +++ b/src/main/webapp/scripts/app/customField/customFieldList.controller.js @@ -46,6 +46,24 @@ }, { fieldKey : "SINGLE_SELECT", fieldValue : $filter("translate")("common.singleSelectionField") //"�떒�씪 �꽑�깮 �븘�뱶" + }, { + fieldKey : "NUMBER", + fieldValue : $filter("translate")("common.numberField") //"�닽�옄 �븘�뱶" + }, { + fieldKey : "DATETIME", + fieldValue : $filter("translate")("common.datetimeField") //"�궇吏� �븘�뱶" + }, { + fieldKey : "IP_ADDRESS", + fieldValue : $filter("translate")("common.ipAddressField") //"IP Address �븘�뱶" + }, { + fieldKey : "EMAIL", + fieldValue : $filter("translate")("common.emailField") //"�씠硫붿씪 �븘�뱶" + }, { + fieldKey : "SITE", + fieldValue : $filter("translate")("common.siteField") //"�솃�럹�씠吏� �븘�뱶" + }, { + fieldKey : "TEL", + fieldValue : $filter("translate")("common.telField") //"�쟾�솕踰덊샇 �븘�뱶" }] } }; diff --git a/src/main/webapp/scripts/app/ispField/ispField.js b/src/main/webapp/scripts/app/ispField/ispField.js index 563b10e..0c46982 100644 --- a/src/main/webapp/scripts/app/ispField/ispField.js +++ b/src/main/webapp/scripts/app/ispField/ispField.js @@ -32,7 +32,7 @@ resolve : { loadController : ["$q", function ($q) { var deferred = $q.defer(); - require(["ispFieldListController", 'jsTable', 'tableColumnGenerator', 'ispFieldService', 'modalFormAutoScroll' + require(["ispFieldListController", "ispFieldAddController", 'jsTable', 'tableColumnGenerator', 'ispFieldService', 'modalFormAutoScroll' , 'ispFieldAddController', 'ispFieldModifyController' , 'formSubmit', 'jsShortCut', 'inputRegex'], function () { deferred.resolve(); diff --git a/src/main/webapp/scripts/app/issueType/issueTypeAdd.controller.js b/src/main/webapp/scripts/app/issueType/issueTypeAdd.controller.js index de55159..589a9ae 100644 --- a/src/main/webapp/scripts/app/issueType/issueTypeAdd.controller.js +++ b/src/main/webapp/scripts/app/issueType/issueTypeAdd.controller.js @@ -33,6 +33,16 @@ } }, options : { + emailTemplates : [{ + fieldKey : "COMPANY", + fieldValue : "�뾽泥�" + }, { + fieldKey : "ISP", + fieldValue : "ISP", + }, { + fieldKey : "HOSTING", + fieldValue : "�샇�뒪�똿" + }], callbacks: { onImageUpload: function (data) { data.pop(); diff --git a/src/main/webapp/scripts/app/issueType/issueTypeList.controller.js b/src/main/webapp/scripts/app/issueType/issueTypeList.controller.js index 884febd..f298258 100644 --- a/src/main/webapp/scripts/app/issueType/issueTypeList.controller.js +++ b/src/main/webapp/scripts/app/issueType/issueTypeList.controller.js @@ -63,6 +63,13 @@ .setDAlign("text-center") .setDRenderer("COMMON_MODIFY")); $scope.vm.tableConfigs.push($tableProvider.config() + .setHName("issue.useProjects") + .setHWidth("bold") + .setDType("renderer") + .setDName("name") + .setDAlign("text-center") + .setDRenderer("USE_PROJECT_LIST")); + $scope.vm.tableConfigs.push($tableProvider.config() .setHName("common.color") .setHWidth("width-140-p bold") .setDType("renderer") diff --git a/src/main/webapp/scripts/app/project/projectList.controller.js b/src/main/webapp/scripts/app/project/projectList.controller.js index f6f68c5..3999767 100644 --- a/src/main/webapp/scripts/app/project/projectList.controller.js +++ b/src/main/webapp/scripts/app/project/projectList.controller.js @@ -107,17 +107,11 @@ .setDAlign("text-center") .setDRenderer("PROJECT_MANAGER")); $scope.vm.tableConfigs.push($tableProvider.config() - .setHName("dashboard.teamMember") + .setHName("project.projectDepartment") .setHWidth("width-140-p bold") .setDType("renderer") .setDAlign("text-center") .setDRenderer("PROJECT_USER")); - $scope.vm.tableConfigs.push($tableProvider.config() - .setHName("common.period") - .setHWidth("width-120-p bold") - .setDType("renderer") - .setDAlign("text-center") - .setDRenderer("PROJECT_DUE_DATE")); $scope.vm.tableConfigs.push($tableProvider.config() .setHName("project.projectKey") .setHWidth("width-100-p bold") diff --git a/src/main/webapp/scripts/components/api/api.service.js b/src/main/webapp/scripts/components/api/api.service.js new file mode 100644 index 0000000..b95c0c1 --- /dev/null +++ b/src/main/webapp/scripts/components/api/api.service.js @@ -0,0 +1,29 @@ +'use strict'; + +define([ + 'app' +], function (app) { + app.factory("Api", ['$http', '$log', function ($http, $log) { + return { + find : function (conditions) { + return $http.post("apiToken/find", conditions).then(function (response) { + $log.debug("�넗�겙 �뜲�씠�꽣 : ", response); + return response; + }); + }, + add : function (conditions) { + return $http.post("apiToken/add", conditions).then(function (response) { + $log.debug("�넗�겙 �깮�꽦 寃곌낵 : ", response); + return response; + }); + }, + remove : function (conditions) { + return $http.post("apiToken/remove", conditions).then(function (response) { + $log.debug("�넗�겙 �궘�젣 寃곌낵 : ", response); + return response; + }); + } + } + } + ]); +}); diff --git a/src/main/webapp/scripts/main.js b/src/main/webapp/scripts/main.js index e0d48fe..2c46176 100644 --- a/src/main/webapp/scripts/main.js +++ b/src/main/webapp/scripts/main.js @@ -325,6 +325,7 @@ /* api */ 'apiRoute' : 'app/api/api', // api route �젙蹂� + 'apiService' : 'components/api/api.service', // api 愿��젴�맂 �넻�떊 �떞�떦 'apiAuthController' :'app/api/apiAuth.controller', // api �씤利� 而⑦듃濡ㅻ윭 'apiSettingController' : 'app/api/apiSetting.controller', // api �꽕�젙 而⑦듃濡ㅻ윭 'apiMonitorController' : 'app/api/apiMonitor.controller', // api 紐⑤땲�꽣留� 而⑦듃濡ㅻ윭 diff --git a/src/main/webapp/views/api/apiAuth.html b/src/main/webapp/views/api/apiAuth.html index e74ce86..21c7a6e 100644 --- a/src/main/webapp/views/api/apiAuth.html +++ b/src/main/webapp/views/api/apiAuth.html @@ -8,7 +8,7 @@ </h6> <div class="element-box"> - <form role="form" name="issueStatusAddForm"> + <form role="form" name="apiTokenAddForm"> <div class="form-group"> <label for="apiApplicationForm1"><span translate="api.application">�뼱�뵆由ъ��씠�뀡 �씠由�</span> <code class="highlighter-rouge">*</code></label> <input id="apiApplicationForm1" @@ -19,7 +19,7 @@ kr-input autocomplete="off" maxlength="50" - ng-model="vm.form.name" + ng-model="vm.form.appName" ng-maxlength="20" required> </div> @@ -32,18 +32,18 @@ name="token" class="form-control" disabled - ng-model="vm.form.token" - required> + ng-model="vm.form.token"> </div> </div> </form> - <div class="modal-footer buttons-on-right"> - <button type="button" class="btn btn-md btn-grey" ng-click="fn.cancel()"><span translate="api.delete">痍⑥냼</span></button> - <button type="button" class="btn btn-md btn-primary bold" - js-short-cut - js-short-cut-action="(fn.formCheck(issueStatusAddForm.$invalid) || $root.spinner) ? null : fn.formSubmit()" - ng-click="fn.formSubmit()"><span translate="api.create">�깮�꽦</span> + <div class="buttons-on-right"> + <button type="button" class="btn btn-md btn-grey" ng-click="fn.remove()"><span translate="api.delete">痍⑥냼</span></button> + <button type="button" class="btn btn-md btn-primary bold" + js-short-cut + js-short-cut-action="(fn.formCheck(apiTokenAddForm.$invalid) || $root.spinner) ? null : fn.formSubmit()" + ng-disabled="fn.formCheck(apiTokenAddForm.$invalid)" + ng-click="fn.formSubmit()"><span translate="api.create">�깮�꽦</span> </button> </div> </div> diff --git a/src/main/webapp/views/api/apiOverlapAdd.html b/src/main/webapp/views/api/apiOverlapAdd.html new file mode 100644 index 0000000..ca69386 --- /dev/null +++ b/src/main/webapp/views/api/apiOverlapAdd.html @@ -0,0 +1,36 @@ +<div class="formModal"> + <div class="modal-header faded smaller"> + <div class="modal-title"> + <strong translate="api.addOverlapField">�궗�슜�옄 �젙�쓽 �븘�뱶 留뚮뱾湲�</strong> + </div> + <button aria-label="Close" class="close" type="button" ng-click="fn.cancel()"> + <span aria-hidden="true"> ×</span> + </button> + </div> + + <div class="modal-body"> + <form role="form" name="customFieldAddForm"> + <div class="form-group"> + <label for="customFieldAddForm2"><span>�븘�뱶 �꽑�깮</span> <code + class="highlighter-rouge">*</code></label> + <select id="customFieldAddForm2" class="form-control" ng-model="vm.form.customFieldType" + ng-change="fn.changeFieldType()"> + <option value="INPUT" >寃쎌쑀吏�</option> + <option value="SINGLE_SELECT" >IP</option> + <option value="NUMBER" >援�媛�</option> + </select> + </div> + </form> + </div> + + <div class="modal-footer buttons-on-right"> + <button type="button" class="btn btn-md btn-grey" ng-click="fn.cancel()"><span + translate="common.cancel">痍⑥냼</span></button> + <button type="button" class="btn btn-md btn-primary bold" + js-short-cut + js-short-cut-action="(fn.formCheck(customFieldAddForm.$invalid) || $root.spinner) ? null : fn.formSubmit()" + ng-disabled="fn.formCheck(customFieldAddForm.$invalid)" + ng-click="fn.formSubmit()"><span translate="common.save">���옣</span> + </button> + </div> +</div> diff --git a/src/main/webapp/views/api/apiSetting.html b/src/main/webapp/views/api/apiSetting.html index b470af1..1f2d2ad 100644 --- a/src/main/webapp/views/api/apiSetting.html +++ b/src/main/webapp/views/api/apiSetting.html @@ -1,272 +1,42 @@ <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.columnSetting"> + <h6 class="element-header" translate="api.setting"> �꽕�젙 </h6> - <!-- <div class="os-tabs-w"> <div class="os-tabs-controls"> <ul class="nav nav-tabs upper"> <li class="nav-item"> - <a class="nav-link cursor" translate="api.example">�궗�슜 �삁�떆</a> + <a class="nav-link cursor" ng-class="{ 'active' : vm.tab == 'API_COL_SETTING' }" ng-click="fn.changeTab('API_COL_SETTING')" translate="api.columnSetting">�궗�슜�옄 �벑湲� 愿�由�</a> + </li> + <li class="nav-item"> + <a class="nav-link cursor" ng-class="{ 'active' : vm.tab == 'API_OVERLAP_SETTING' }" ng-click="fn.changeTab('API_OVERLAP_SETTING')" translate="api.overlapSetting">遺��꽌 愿�由�</a> </li> </ul> </div> </div> - <div class="element-box"> - </div> ---> - <div class="row"> - <div class="col-md-4"> - <div class="form-group mb10"> - <label for="issueAddForm4" class="issue-label"> <span - translate="issue.issueType">�씠�뒋 ���엯</span> - </label> - <select id="issueAddForm4" - name="issueType" - class="form-control input-sm issue-select-label" - ng-model="vm.form.issueTypeId" - ng-change="fn.getIssueTypeCustomFields()" - ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.form.issueTypeId) }" - required> - <option ng-style="{ 'color' : '#353535' }" value="">�솃�럹�씠吏� 蹂�議� 媛먯� - </option> - <option ng-style="{ 'color' : '#353535' }" value="">寃쎌쑀吏� �깘吏� - </option> - <option ng-repeat="issueType in vm.issueTypes" - ng-style="{ 'color' : issueType.color, 'font-weight': 600 }" - value="{{issueType.id}}">�뿈 {{issueType.name}} - </option> - </select> - </div> + <div class="tab-content mt-30"> + <div ng-show="vm.tab == 'API_COL_SETTING'"> + <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/apiSettingOverlap.html'"></div> + </div> </div> - <div class="element-box"> - - <form role="form" name="issueAddForm"> - <div class="form-group mb10"> - <label for="issueAddForm1" class="issue-label"><span translate="issue.issueTitle">�씪媛� �젣紐�</span> </label> - <input id="issueAddForm1" - class="form-control input-sm" - ng-model="vm.form.title" - name="title" - required - kr-input - value="�솃�럹�씠吏� 蹂�議� 媛먯� 嫄�" - maxlength="300" - autocomplete="off" - autofocus - owl-auto-focus> - </div> - <div class="row"> - <div class="col-lg-4"> - <div class="form-group mb10"> - <label class="issue-label"> <span translate="common.project">�봽濡쒖젥�듃</span> </label> - <select id="issueAddForm6" - name="issueType" - class="form-control input-sm issue-select-label" - ng-model="vm.form.issueTypeId" - ng-change="fn.getIssueTypeCustomFields()" - ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.form.issueTypeId) }" - required> - <option ng-style="{ 'color' : '#353535' }" value="">�솃�럹�씠吏� 蹂�議� 媛먯� - </option> - <option ng-style="{ 'color' : '#353535' }" value="">MCF - </option> - <option ng-repeat="issueType in vm.issueTypes" - ng-style="{ 'color' : issueType.color, 'font-weight': 600 }" - value="{{issueType.id}}">�뿈 {{issueType.name}} - </option> - </select> - </div> - </div> - - <div class="col-lg-8 bdl1"> - <div class="row"> - - <div class="col-md-4"> - <div class="form-group mb10"> - <label for="issueAddForm2" class="issue-label"> - <span translate="common.priority">�슦�꽑 �닚�쐞</span> - </label> - <select id="issueAddForm2" - name="priority" - class="form-control input-sm issue-select-label" - ng-model="vm.form.priorityId" - ng-style="{ 'color' : fn.getOptionColor(vm.priorities, vm.form.priorityId) }" - required> - <option value="" ng-style="{ 'color' : '#353535' }"> - <span >蹂댄넻</span> - </option> - <option value="" ng-style="{ 'color' : '#353535' }"> - <span >�넂�쓬</span> - </option> - <option value="" ng-style="{ 'color' : '#353535' }"> - <span >�궙�쓬</span> - </option> - <option ng-repeat="priority in vm.priorities" - ng-style="{ 'color' : priority.color, 'font-weight': 600 }" - value="{{priority.id}}" - translate="{{priority.name}}"> - </option> - </select> - </div> - </div> - <div class="col-md-4"> - <div class="form-group mb10"> - <label for="issueAddForm3" class="issue-label"> <span - translate="common.importance">以묒슂�룄</span> </label> - <select id="issueAddForm3" - name="severity" - class="form-control input-sm issue-select-label" - ng-model="vm.form.severityId" - ng-style="{ 'color' : fn.getOptionColor(vm.severities, vm.form.severityId) }" - required> - <option value="" ng-style="{ color : '#353535' }"> - <span>蹂댄넻</span> - </option> - <option value="" ng-style="{ color : '#353535' }"> - <span>�넂�쓬</span> - </option> - <option value="" ng-style="{ color : '#353535' }"> - <span>�궙�쓬</span> - </option> - <option ng-repeat="severity in vm.severities" - ng-style="{ color : severity.color, 'font-weight': 600 }" - value="{{severity.id}}" - translate="{{severity.name}}"> - </option> - </select> - </div> - </div> - </div> - </div> - - </div> - - <div class="form-group mb10"> - <label class="issue-label"><span translate="common.content">�궡�슜</span></label> - <summernote - class="summernote" - lang="ko-KR" - summer-note-auto-focus - ng-model="vm.form.description" - data-editor="vm.summerNote.editor" - data-editable="vm.summerNote.editable" - on-image-upload="fn.imageUpload(files)" - target=".note-editable"></summernote> - </div> - - <div class="row"> - <div class="col-lg-12"> - <div class="form-group mb10"> - <label for="issueAddForm5" class="issue-label"> <span translate="common.period">湲곌컙</span> - </label> - <input id="issueAddForm5" - tabindex="-1" - type="text" - readonly - class="form-control cursor" - placeholder="{{'issue.clickToSelectDate' | translate}}" - ng-model="vm.form.startCompleteDateRange" - modal-form-auto-scroll - date-format="YYYY-MM-DD" - parent-el="'#createdWidget'" - date-range-picker> - <div class="row"> - <div class="col-xs-12"> - <div id="createdWidget" class="bootstrap-datepicker"></div> - </div> - </div> - </div> - </div> - </div> - <div class="row"> - <div class="col-lg-3"> - <div class="form-group mb10"> - <div class="form-group mb10"> - <label class="issue-label"> <span translate="common.assigneeTeam">�떞�떦遺��꽌</span> </label> - <select id="issueAddForm" - name="issueType" - class="form-control input-sm issue-select-label" - ng-model="vm.form.issueTypeId" - ng-change="fn.getIssueTypeCustomFields()" - ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.form.issueTypeId) }" - required> - <option value="" ng-style="{ 'color' : '#353535' }"><span>議곗튂�슜�뿭</span></option> - <option value="" ng-style="{ 'color' : '#353535' }"><span>遺꾩꽍�슜�뿭</span></option> - <option value="" ng-style="{ 'color' : '#353535' }"><span>�긽�솴�떎</span></option> - <option ng-repeat="issueType in vm.issueTypes" - ng-style="{ 'color' : issueType.color, 'font-weight': 600 }" - value="{{issueType.id}}">�뿈 {{issueType.name}} - </option> - </select> - </div> - </div> - - </div> - <div class="col-lg-3"> - <div class="form-group mb10"> - <div class="form-group mb10"> - <label class="issue-label"> <span>�뾽醫�</span> </label> - <select id="issueAddFormIP" - name="issueType" - class="form-control input-sm issue-select-label" - ng-model="vm.form.issueTypeId" - ng-change="fn.getIssueTypeCustomFields()" - ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.form.issueTypeId) }" - required> - <option value="" translate="common.selectTarget" ng-style="{ 'color' : '#353535' }"><span>���긽 �꽑�깮</span> - </option> - <option ng-repeat="issueType in vm.issueTypes" - ng-style="{ 'color' : issueType.color, 'font-weight': 600 }" - value="{{issueType.id}}">�뿈 {{issueType.name}} - </option> - </select> - </div> - - - </div> - </div> - <div class="col-lg-3"> - <div class="form-group mb10"> - <div class="form-group mb10"> - <label class="issue-label"> <span>�룄硫붿씤</span> </label> - <input id="issueAddForm8" - tabindex="-1" - type="text" - class="form-control cursor" - /> - - </div> - - - </div> - </div> - <div class="col-lg-3"> - <div class="form-group mb10"> - <div class="form-group mb10"> - <label class="issue-label"> <span>寃쎌쑀吏�IP</span> </label> - <input id="issueAddForm*" - tabindex="-1" - type="text" - class="form-control cursor" - /> - </div> - - - </div> - </div> - </div> - </form> - </div> </div> diff --git a/src/main/webapp/views/api/apiSettingColumn.html b/src/main/webapp/views/api/apiSettingColumn.html new file mode 100644 index 0000000..f134b54 --- /dev/null +++ b/src/main/webapp/views/api/apiSettingColumn.html @@ -0,0 +1,252 @@ +<div class="row"> + <div class="col-md-4"> + <div class="form-group mb10"> + <label for="issueAddForm4" class="issue-label"> <span + translate="issue.issueType">�씠�뒋 ���엯</span> + </label> + <select id="issueAddForm4" + name="issueType" + class="form-control input-sm issue-select-label" + ng-model="vm.form.issueTypeId" + ng-change="fn.getIssueTypeCustomFields()" + ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.form.issueTypeId) }" + required> + <option ng-style="{ 'color' : '#353535' }" value="">�솃�럹�씠吏� 蹂�議� 媛먯� + </option> + <option ng-style="{ 'color' : '#353535' }" value="">寃쎌쑀吏� �깘吏� + </option> + <option ng-repeat="issueType in vm.issueTypes" + ng-style="{ 'color' : issueType.color, 'font-weight': 600 }" + value="{{issueType.id}}">�뿈 {{issueType.name}} + </option> + </select> + </div> + </div> + +</div> + +<div class="element-box"> + <form role="form" name="issueAddForm"> + <div class="form-group mb10"> + <label for="issueAddForm1" class="issue-label"><span translate="issue.issueTitle">�씪媛� �젣紐�</span> </label> + <input id="issueAddForm1" + class="form-control input-sm" + ng-model="vm.form.title" + name="title" + required + kr-input + value="�솃�럹�씠吏� 蹂�議� 媛먯� 嫄�" + maxlength="300" + autocomplete="off" + autofocus + owl-auto-focus> + </div> + <div class="row"> + <div class="col-lg-4"> + <div class="form-group mb10"> + <label class="issue-label"> <span translate="common.project">�봽濡쒖젥�듃</span> </label> + <select id="issueAddForm6" + name="issueType" + class="form-control input-sm issue-select-label" + ng-model="vm.form.issueTypeId" + ng-change="fn.getIssueTypeCustomFields()" + ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.form.issueTypeId) }" + required> + <option ng-style="{ 'color' : '#353535' }" value="">�솃�럹�씠吏� 蹂�議� 媛먯� + </option> + <option ng-style="{ 'color' : '#353535' }" value="">MCF + </option> + <option ng-repeat="issueType in vm.issueTypes" + ng-style="{ 'color' : issueType.color, 'font-weight': 600 }" + value="{{issueType.id}}">�뿈 {{issueType.name}} + </option> + </select> + </div> + </div> + + <div class="col-lg-8 bdl1"> + <div class="row"> + + <div class="col-md-4"> + <div class="form-group mb10"> + <label for="issueAddForm2" class="issue-label"> + <span translate="common.priority">�슦�꽑 �닚�쐞</span> + </label> + <select id="issueAddForm2" + name="priority" + class="form-control input-sm issue-select-label" + ng-model="vm.form.priorityId" + ng-style="{ 'color' : fn.getOptionColor(vm.priorities, vm.form.priorityId) }" + required> + <option value="" ng-style="{ 'color' : '#353535' }"> + <span >蹂댄넻</span> + </option> + <option value="" ng-style="{ 'color' : '#353535' }"> + <span >�넂�쓬</span> + </option> + <option value="" ng-style="{ 'color' : '#353535' }"> + <span >�궙�쓬</span> + </option> + <option ng-repeat="priority in vm.priorities" + ng-style="{ 'color' : priority.color, 'font-weight': 600 }" + value="{{priority.id}}" + translate="{{priority.name}}"> + </option> + </select> + </div> + </div> + <div class="col-md-4"> + <div class="form-group mb10"> + <label for="issueAddForm3" class="issue-label"> <span + translate="common.importance">以묒슂�룄</span> </label> + <select id="issueAddForm3" + name="severity" + class="form-control input-sm issue-select-label" + ng-model="vm.form.severityId" + ng-style="{ 'color' : fn.getOptionColor(vm.severities, vm.form.severityId) }" + required> + <option value="" ng-style="{ color : '#353535' }"> + <span>蹂댄넻</span> + </option> + <option value="" ng-style="{ color : '#353535' }"> + <span>�넂�쓬</span> + </option> + <option value="" ng-style="{ color : '#353535' }"> + <span>�궙�쓬</span> + </option> + <option ng-repeat="severity in vm.severities" + ng-style="{ color : severity.color, 'font-weight': 600 }" + value="{{severity.id}}" + translate="{{severity.name}}"> + </option> + </select> + </div> + </div> + </div> + </div> + + </div> + + <div class="form-group mb10"> + <label class="issue-label"><span translate="common.content">�궡�슜</span></label> + <summernote + class="summernote" + lang="ko-KR" + summer-note-auto-focus + ng-model="vm.form.description" + data-editor="vm.summerNote.editor" + data-editable="vm.summerNote.editable" + on-image-upload="fn.imageUpload(files)" + target=".note-editable"></summernote> + </div> + + <div class="row"> + <div class="col-lg-12"> + <div class="form-group mb10"> + <label for="issueAddForm5" class="issue-label"> <span translate="common.period">湲곌컙</span> + </label> + <input id="issueAddForm5" + tabindex="-1" + type="text" + readonly + class="form-control cursor" + placeholder="{{'issue.clickToSelectDate' | translate}}" + ng-model="vm.form.startCompleteDateRange" + modal-form-auto-scroll + date-format="YYYY-MM-DD" + parent-el="'#createdWidget'" + date-range-picker> + <div class="row"> + <div class="col-xs-12"> + <div id="createdWidget" class="bootstrap-datepicker"></div> + </div> + </div> + </div> + </div> + </div> + <div class="row"> + <div class="col-lg-3"> + <div class="form-group mb10"> + <div class="form-group mb10"> + <label class="issue-label"> <span translate="common.assigneeTeam">�떞�떦遺��꽌</span> </label> + <select id="issueAddForm" + name="issueType" + class="form-control input-sm issue-select-label" + ng-model="vm.form.issueTypeId" + ng-change="fn.getIssueTypeCustomFields()" + ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.form.issueTypeId) }" + required> + <option value="" ng-style="{ 'color' : '#353535' }"><span>議곗튂�슜�뿭</span></option> + <option value="" ng-style="{ 'color' : '#353535' }"><span>遺꾩꽍�슜�뿭</span></option> + <option value="" ng-style="{ 'color' : '#353535' }"><span>�긽�솴�떎</span></option> + <option ng-repeat="issueType in vm.issueTypes" + ng-style="{ 'color' : issueType.color, 'font-weight': 600 }" + value="{{issueType.id}}">�뿈 {{issueType.name}} + </option> + </select> + </div> + </div> + + </div> + <div class="col-lg-3"> + <div class="form-group mb10"> + <div class="form-group mb10"> + <label class="issue-label"> <span>�뾽醫�</span> </label> + <select id="issueAddFormIP" + name="issueType" + class="form-control input-sm issue-select-label" + ng-model="vm.form.issueTypeId" + ng-change="fn.getIssueTypeCustomFields()" + ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.form.issueTypeId) }" + required> + <option value="" translate="common.selectTarget" ng-style="{ 'color' : '#353535' }"><span>���긽 �꽑�깮</span> + </option> + <option ng-repeat="issueType in vm.issueTypes" + ng-style="{ 'color' : issueType.color, 'font-weight': 600 }" + value="{{issueType.id}}">�뿈 {{issueType.name}} + </option> + </select> + </div> + + + </div> + </div> + <div class="col-lg-3"> + <div class="form-group mb10"> + <div class="form-group mb10"> + <label class="issue-label"> <span>�룄硫붿씤</span> </label> + <input id="issueAddForm8" + tabindex="-1" + type="text" + class="form-control cursor" + /> + + </div> + + + </div> + </div> + <div class="col-lg-3"> + <div class="form-group mb10"> + <div class="form-group mb10"> + <label class="issue-label"> <span>寃쎌쑀吏�IP</span> </label> + <input id="issueAddForm*" + tabindex="-1" + type="text" + class="form-control cursor" + /> + </div> + + + </div> + </div> + </div> + </form> + <div class="modal-footer buttons-on-right"> + <button type="button" class="btn btn-md btn-primary bold" + js-short-cut + js-short-cut-action="(fn.formCheck(issueStatusAddForm.$invalid) || $root.spinner) ? null : fn.formSubmit()" + ng-click="fn.formSubmit()"><span translate="common.saved">�깮�꽦</span> + </button> + </div> +</div> diff --git a/src/main/webapp/views/api/apiSettingOverlap.html b/src/main/webapp/views/api/apiSettingOverlap.html new file mode 100644 index 0000000..6929f53 --- /dev/null +++ b/src/main/webapp/views/api/apiSettingOverlap.html @@ -0,0 +1,36 @@ + + +<div class="row"> + <div class="col-sm-5"> + <div class="element-wrapper"> + <label for="issueAddForm4" class="issue-label"> <span + translate="issue.issueType">�씠�뒋 ���엯</span> + </label> + <select id="issueAddForm4" + name="issueType" + class="form-control input-sm issue-select-label" + ng-model="vm.form.issueTypeId" + ng-change="fn.getIssueTypeCustomFields()" + ng-style="{ 'color' : fn.getOptionColor(vm.issueTypes, vm.form.issueTypeId) }" + required> + <option ng-style="{ 'color' : '#353535' }" value="">�솃�럹�씠吏� 蹂�議� 媛먯� + </option> + <option ng-style="{ 'color' : '#353535' }" value="">寃쎌쑀吏� �깘吏� + </option> + <option ng-repeat="issueType in vm.issueTypes" + ng-style="{ 'color' : issueType.color, 'font-weight': 600 }" + value="{{issueType.id}}">�뿈 {{issueType.name}} + </option> + </select> + </div> + </div> + + +</div> + +<div class="element-box"> + <p class="btn btn-secondary"> + <span >寃쎌쑀吏�</span> + <span>횞</span> + </p> +</div> diff --git a/src/main/webapp/views/common/sidebar.html b/src/main/webapp/views/common/sidebar.html index 468c410..037179e 100644 --- a/src/main/webapp/views/common/sidebar.html +++ b/src/main/webapp/views/common/sidebar.html @@ -69,8 +69,6 @@ </ul> </div> </div> - - </div> <!-------------------- @@ -85,14 +83,6 @@ <span translate="common.dashboard">���떆蹂대뱶</span> </a> </li> - <li class="pointer"> - <a ng-click="fn.moveMenu('issues.list')" tabindex="-1"> - <div class="icon-w"> - <div class="os-icon os-icon-layers"></div> - </div> - <span translate="issue.managementIssue">�씠�뒋 愿�由�</span></a> - </li> - <!-- <li class=""> <a ui-sref="tasks.agileBoard" tabindex="-1"> <div class="icon-w"> @@ -258,16 +248,42 @@ </a> </li> <li class="sub-header"> - <span>Tasks</span> + <span>ISSUE LIST</span> </li> - <li class="pointer"> - <a ng-click="fn.moveMenu('issues.list')" tabindex="-1"> + <!-- UI臾몄꽌 �젣�옉�슜 �엫�떆 肄붾뱶 �떆�옉--> + <li class=""> + <a ui-sref="dashboards.dashboard" tabindex="-1"> <div class="icon-w"> - <div class="os-icon os-icon-layers"></div> + <div class="os-icon os-icon-layout"></div> </div> - <span translate="issue.managementIssue">�씠�뒋 愿�由�</span> + <span>�븙�꽦 �룄硫붿씤</span> </a> </li> + <li class=""> + <a ui-sref="dashboards.dashboard" tabindex="-1"> + <div class="icon-w"> + <div class="os-icon os-icon-layout"></div> + </div> + <span>寃쎌쑀吏� ���쓳</span> + </a> + </li> + <li class=""> + <a ui-sref="dashboards.dashboard" tabindex="-1"> + <div class="icon-w"> + <div class="os-icon os-icon-layout"></div> + </div> + <span>�쑀�룷吏� ���쓳</span> + </a> + </li> + <li class=""> + <a ui-sref="dashboards.dashboard" tabindex="-1"> + <div class="icon-w"> + <div class="os-icon os-icon-layout"></div> + </div> + <span>遺꾩꽍寃곌낵 ���쓳</span> + </a> + </li> + <!-- UI臾몄꽌 �젣�옉�슜 �엫�떆 肄붾뱶 �걹--> <!-- <li class=""> <a ui-sref="tasks.agileBoard" tabindex="-1"> @@ -389,11 +405,11 @@ <span translate="guide.manageGuide">媛��씠�뱶 愿�由�</span></a> </li> - <li class="sub-header"> + <li class="sub-header" ng-if="$root.checkMngPermission('USER_PERMISSION_MNG_API')"> <span>API</span> </li> - <li> + <li ng-if="$root.checkMngPermission('USER_PERMISSION_MNG_API')"> <a ui-sref="api.auth" tabindex="-1"> <div class="icon-w"> <div class="os-icon os-icon-package"></div> @@ -401,14 +417,14 @@ <span translate="api.auth">API �씤利�</span></a> </li> - <li> + <li ng-if="$root.checkMngPermission('USER_PERMISSION_MNG_API')"> <a ui-sref="api.setting" tabindex="-1"> <div class="icon-w"> <div class="os-icon os-icon-package"></div> </div> <span translate="api.setting">API �꽕�젙</span></a> </li> - <li> + <li ng-if="$root.checkMngPermission('USER_PERMISSION_MNG_API')"> <a ui-sref="api.monitor" tabindex="-1"> <div class="icon-w"> <div class="os-icon os-icon-package"></div> diff --git a/src/main/webapp/views/customField/customFieldAdd.html b/src/main/webapp/views/customField/customFieldAdd.html index 53a0e7a..c64c0ee 100644 --- a/src/main/webapp/views/customField/customFieldAdd.html +++ b/src/main/webapp/views/customField/customFieldAdd.html @@ -38,7 +38,12 @@ ng-change="fn.changeFieldType()"> <option value="INPUT" translate="common.stringField">臾몄옄�뿴 �븘�뱶</option> <option value="SINGLE_SELECT" translate="common.singleSelectionField">�떒�씪 �꽑�깮 �븘�뱶</option> - <option value="MULTI_SELECT" translate="common.multipleSelectionField">�떎以� �꽑�깮 �븘�뱶</option> + <option value="NUMBER" translate="common.numberField">�닽�옄 �븘�뱶</option> + <option value="DATETIME" translate="common.datetimeField">�궇吏� �븘�뱶</option> + <option value="IP_ADDRESS" translate="common.ipAddressField">IP 二쇱냼 �븘�뱶</option> + <option value="EMAIL" translate="common.emailField">�씠硫붿씪 �븘�뱶</option> + <option value="SITE" translate="common.siteField">�솃�럹�씠吏� 二쇱냼 �븘�뱶</option> + <option value="TEL" translate="common.telField">�쟾�솕踰덊샇 �븘�뱶</option> </select> </div> diff --git a/src/main/webapp/views/issueType/issueTypeAdd.html b/src/main/webapp/views/issueType/issueTypeAdd.html index b4896ce..d44c9b6 100644 --- a/src/main/webapp/views/issueType/issueTypeAdd.html +++ b/src/main/webapp/views/issueType/issueTypeAdd.html @@ -43,6 +43,28 @@ </div> <div class="form-group"> + <label><span translate="issue.useProjects">�궗�슜 �봽濡쒖젥�듃</span></label> + <js-autocomplete-single data-input-name="workflow" + selected-model="vm.form.workflows" + search="vm.workflowName" + source="fn.getWorkflowList(vm.workflowName, vm.form.workflows, vm.autoCompletePage.workflow.page, fn.getWorkflowListCallBack)" + page="vm.autoCompletePage.workflow.page" + total-page="vm.autoCompletePage.workflow.totalPage" + input-disabled="false" + extra-settings="{ displayProp : 'name' , idProp : 'id', imageable : false, imagePathProp : '', type : '', maxlength : 200, autoResize : false }"></js-autocomplete-single> + </div> + + <div class="form-group"> + <label><span + translate="issue.companyInfo">�뾽泥�/ISP/�샇�뒪�똿 �젙蹂�</span></label> + <ng-dropdown-multiselect class="multiSelect cursor" + data-input-name="issueStatusTypes" + selected-model="vm.search.issueStatusTypes" + extra-settings="{ stringTypeOption : true }" + options="vm.options.emailTemplates"></ng-dropdown-multiselect> + </div> + + <div class="form-group"> <label for="issueTypeAddForm2"><span translate="common.color">�깋�긽</span> <code class="highlighter-rouge">*</code></label> <div class="input-group"> <input id="issueTypeAddForm2" diff --git a/src/main/webapp/views/login/login.html b/src/main/webapp/views/login/login.html index a1f510e..a08cb35 100644 --- a/src/main/webapp/views/login/login.html +++ b/src/main/webapp/views/login/login.html @@ -122,12 +122,14 @@ <small>CopyRight WISESTONE All rights reserved.</small> </div> --> + <!-- �엫�떆 肄붾뱶 (�뒋�띁愿�由ъ옄 異붽�) <div> <button class="btn btn-light" ui-sref="superJoin" translate="users.workspaceJoin"> �쉶�썝媛��엯 </button> </div> + --> <div class="footer-s" > <small>CopyRight WISESTONE All rights reserved.</small> </div> diff --git a/src/main/webapp/views/project/projectModify.html b/src/main/webapp/views/project/projectModify.html index 0ba8561..ec7058a 100644 --- a/src/main/webapp/views/project/projectModify.html +++ b/src/main/webapp/views/project/projectModify.html @@ -33,7 +33,7 @@ <div class="row"> <div class="col-lg-6"> <div class="form-group"> - <label for="projectModifyForm2"><span translate="common.period">湲곌컙</span> <code class="highlighter-rouge">*</code></label> + <label for="projectModifyForm2"><span translate="common.period">湲곌컙</span></label> <input id="projectModifyForm2" type="text" class="form-control input-readonly" @@ -106,7 +106,7 @@ </div> <div class="form-group"> - <label><span translate="project.projectTeam">�봽濡쒖젥�듃 ���썝</span> </label> + <label><span translate="project.projectDepartment">�봽濡쒖젥�듃 遺��꽌</span> </label> <js-autocomplete-multi data-input-name="users" selected-model="vm.form.users" search="vm.userName" -- Gitblit v1.8.0