From 54e66d483f59776f4dcae7ef255c9952ab2abb5f Mon Sep 17 00:00:00 2001 From: st-yclee Date: Wed, 28 Aug 2024 09:50:44 +0900 Subject: [PATCH 1/5] =?UTF-8?q?=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/co/mcmp/dto/oss/NexusFormatType.java | 20 -- .../co/mcmp/dto/oss/NexusRepositoryDto.java | 193 ------------------ .../mcmp/service/oss/NexusAdapterFactory.java | 25 --- .../mcmp/service/oss/NexusAdapterService.java | 12 -- .../oss/NexusDockerAdapterService.java | 36 ---- .../service/oss/NexusHelmAdapterService.java | 37 ---- .../service/oss/NexusRawAdapterService.java | 34 --- .../oss/NexusRepositoryAdapterClient.java | 190 ----------------- .../service/oss/NexusRepositoryService.java | 38 ---- 9 files changed, 585 deletions(-) delete mode 100644 src/main/java/kr/co/mcmp/dto/oss/NexusFormatType.java delete mode 100644 src/main/java/kr/co/mcmp/dto/oss/NexusRepositoryDto.java delete mode 100644 src/main/java/kr/co/mcmp/service/oss/NexusAdapterFactory.java delete mode 100644 src/main/java/kr/co/mcmp/service/oss/NexusAdapterService.java delete mode 100644 src/main/java/kr/co/mcmp/service/oss/NexusDockerAdapterService.java delete mode 100644 src/main/java/kr/co/mcmp/service/oss/NexusHelmAdapterService.java delete mode 100644 src/main/java/kr/co/mcmp/service/oss/NexusRawAdapterService.java delete mode 100644 src/main/java/kr/co/mcmp/service/oss/NexusRepositoryAdapterClient.java delete mode 100644 src/main/java/kr/co/mcmp/service/oss/NexusRepositoryService.java diff --git a/src/main/java/kr/co/mcmp/dto/oss/NexusFormatType.java b/src/main/java/kr/co/mcmp/dto/oss/NexusFormatType.java deleted file mode 100644 index 0039776..0000000 --- a/src/main/java/kr/co/mcmp/dto/oss/NexusFormatType.java +++ /dev/null @@ -1,20 +0,0 @@ -package kr.co.mcmp.dto.oss; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class NexusFormatType { - - @Schema(title = "레포지토리 포맷 유형") - private String format; - - @Schema(title = "레포지토리 타입 유형") - private String type; -} diff --git a/src/main/java/kr/co/mcmp/dto/oss/NexusRepositoryDto.java b/src/main/java/kr/co/mcmp/dto/oss/NexusRepositoryDto.java deleted file mode 100644 index aa28b7a..0000000 --- a/src/main/java/kr/co/mcmp/dto/oss/NexusRepositoryDto.java +++ /dev/null @@ -1,193 +0,0 @@ -package kr.co.mcmp.dto.oss; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.Valid; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; - -@Getter -public class NexusRepositoryDto { - - @Getter - @Builder - @NoArgsConstructor - @AllArgsConstructor - public static class ResGetRepositoryDto { - @Schema(title = "레포지토리 이름", required = true) - @NotBlank - private String name; - - @Schema(title = "레포지토리 포맷 유형", required = true) - @NotBlank - private String format; - - @Schema(title = "레포지토리 타입 유형", required = true) - @NotBlank - private String type; - - @Schema(title = "레포지토리 접근 url", required = true) - @NotBlank - private String url; - - @Schema(title = "레포지토리 사용자 접근 가능 여부", required = true) - @NotNull - private Boolean online; - - @Valid - private ResGetStorageDto storage; - - @Valid - private ResGetDockerDto docker; - - @Getter - @Builder - @NoArgsConstructor - @AllArgsConstructor - public static class ResGetStorageDto { - @Schema(title = "아티팩트를 저장하는 물리적 저장소 이름", required = true, example = "default") - @NotBlank - private String blobStoreName; - - @Schema(title = "저장되는 아티팩트 유형 일치 여부 검증", required = true) - @NotNull - private Boolean strictContentTypeValidation; - - @Schema(title = "레포지토리 읽기/쓰기 설정", required = true, example = "allow, allow_once, read_only") - @NotBlank - private String writePolicy; - } - - @Getter - @Builder - @NoArgsConstructor - @AllArgsConstructor - public static class ResGetDockerDto { - @Schema(title = "도커 registry 버전 지원(false: v2 지원)", required = true) - @NotNull - private Boolean v1Enabled; - - @Schema(title = "도커 클라이언트가 레포지토리에 접근할 때 기본 인증 사용 여부", required = true) - @NotNull - private Boolean forceBasicAuth; - - @Schema(title = "도커 레포지토리에 접근할 때 사용할 http 포트") - private Integer httpPort; - - @Schema(title = "도커 레포지토리에 접근할 때 사용할 https 포트") - private Integer httpsPort; - - @Schema(title = "도커 레포지토리에 접근할 때 사용할 서브도메인") - private String subdomain; - } - } - - @Getter - public static class ReqCreateRepositoryDto { - @Schema(title = "레포지토리 이름", required = true) - @NotBlank - private String name; - - @Schema(title = "레포지토리 사용자 접근 가능 여부", required = true) - @NotNull - private Boolean online; - - @Valid - private ReqCreateStorageDto storage; - - @Valid - private ReqCreateDockerDto docker; - - @Getter - public static class ReqCreateStorageDto { - @Schema(title = "아티팩트를 저장하는 물리적 저장소 이름", required = true, example = "default") - @NotBlank - private String blobStoreName; - - @Schema(title = "저장되는 아티팩트 유형 일치 여부 검증", required = true) - @NotNull - private Boolean strictContentTypeValidation; - - @Schema(title = "레포지토리 읽기/쓰기 설정", required = true, example = "allow, allow_once, read_only") - @NotBlank - private String writePolicy; - } - - @Getter - public static class ReqCreateDockerDto { - @Schema(title = "도커 registry 버전 지원(false: v2 지원)", required = true) - @NotNull - private Boolean v1Enabled; - - @Schema(title = "도커 클라이언트가 레포지토리에 접근할 때 기본 인증 사용 여부", required = true) - @NotNull - private Boolean forceBasicAuth; - - @Schema(title = "도커 레포지토리에 접근할 때 사용할 http 포트") - private Integer httpPort; - - @Schema(title = "도커 레포지토리에 접근할 때 사용할 https 포트") - private Integer httpsPort; - - @Schema(title = "도커 레포지토리에 접근할 때 사용할 서브도메인") - private String subdomain; - } - } - - @Getter - public static class ReqUpdateRepositoryDto { - @Schema(title = "레포지토리 이름", required = true) - @JsonIgnore - private String name; - - @Schema(title = "레포지토리 사용자 접근 가능 여부", required = true) - @NotNull - private Boolean online; - - @Valid - private ReqUpdateStorageDto storage; - - @Valid - private ReqUpdateDockerDto docker; - - @Getter - public static class ReqUpdateStorageDto { - @Schema(title = "아티팩트를 저장하는 물리적 저장소 이름", required = true, example = "default") - @JsonIgnore - private String blobStoreName; - - @Schema(title = "저장되는 아티팩트 유형 일치 여부 검증", required = true) - @NotNull - private Boolean strictContentTypeValidation; - - @Schema(title = "레포지토리 읽기/쓰기 설정", required = true, example = "allow, allow_once, read_only") - @NotBlank - private String writePolicy; - } - - @Getter - public static class ReqUpdateDockerDto { - @Schema(title = "도커 registry 버전 지원(false: v2 지원)", required = true) - @NotNull - private Boolean v1Enabled; - - @Schema(title = "도커 클라이언트가 레포지토리에 접근할 때 기본 인증 사용 여부", required = true) - @NotNull - private Boolean forceBasicAuth; - - @Schema(title = "도커 레포지토리에 접근할 때 사용할 http 포트") - private Integer httpPort; - - @Schema(title = "도커 레포지토리에 접근할 때 사용할 https 포트") - private Integer httpsPort; - - @Schema(title = "도커 레포지토리에 접근할 때 사용할 서브도메인") - private String subdomain; - } - } -} diff --git a/src/main/java/kr/co/mcmp/service/oss/NexusAdapterFactory.java b/src/main/java/kr/co/mcmp/service/oss/NexusAdapterFactory.java deleted file mode 100644 index df8250f..0000000 --- a/src/main/java/kr/co/mcmp/service/oss/NexusAdapterFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -package kr.co.mcmp.service.oss; - -import kr.co.mcmp.dto.oss.NexusFormatType; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class NexusAdapterFactory { - - private final NexusRawAdapterService rawAdapterService; - private final NexusDockerAdapterService dockerAdapterService; - private final NexusHelmAdapterService helmAdapterService; - - public NexusAdapterService getAdapterService(NexusFormatType formatType) { - if ("raw".equals(formatType.getFormat())) { - return rawAdapterService; - } else if ("docker".equals(formatType.getFormat())) { - return dockerAdapterService; - } else if ("helm".equals(formatType.getFormat())) { - return helmAdapterService; - } - throw new IllegalArgumentException("unknown format: " + formatType.getFormat()); - } -} diff --git a/src/main/java/kr/co/mcmp/service/oss/NexusAdapterService.java b/src/main/java/kr/co/mcmp/service/oss/NexusAdapterService.java deleted file mode 100644 index 4ee4dee..0000000 --- a/src/main/java/kr/co/mcmp/service/oss/NexusAdapterService.java +++ /dev/null @@ -1,12 +0,0 @@ -package kr.co.mcmp.service.oss; - -import kr.co.mcmp.dto.oss.NexusFormatType; -import kr.co.mcmp.dto.oss.NexusRepositoryDto; - -public interface NexusAdapterService { - - NexusRepositoryDto.ResGetRepositoryDto getRepositoryByName(NexusFormatType formatType, String name); - - void createRepository(NexusFormatType formatType, NexusRepositoryDto.ReqCreateRepositoryDto repositoryDto); - -} diff --git a/src/main/java/kr/co/mcmp/service/oss/NexusDockerAdapterService.java b/src/main/java/kr/co/mcmp/service/oss/NexusDockerAdapterService.java deleted file mode 100644 index ccbcb10..0000000 --- a/src/main/java/kr/co/mcmp/service/oss/NexusDockerAdapterService.java +++ /dev/null @@ -1,36 +0,0 @@ -package kr.co.mcmp.service.oss; - -import kr.co.mcmp.dto.oss.NexusFormatType; -import kr.co.mcmp.dto.oss.NexusRepositoryDto; -import lombok.RequiredArgsConstructor; -import lombok.extern.log4j.Log4j2; -import org.springframework.stereotype.Service; - -import java.util.Collections; -import java.util.Optional; - -@Log4j2 -@Service -@RequiredArgsConstructor -public class NexusDockerAdapterService implements NexusAdapterService { - - private final NexusRepositoryAdapterClient repositoryAdapterClient; - - @Override - public NexusRepositoryDto.ResGetRepositoryDto getRepositoryByName(NexusFormatType formatType, String name) { - return Optional.ofNullable(repositoryAdapterClient.getRepositoryByName(formatType, name)) - .orElseThrow(() -> new IllegalArgumentException("레포지토리 " + name + "을(를) 찾을 수 없습니다.")); - } - - @Override - public void createRepository(NexusFormatType formatType, NexusRepositoryDto.ReqCreateRepositoryDto repositoryDto) { - boolean duplicateNameCheck = Optional.ofNullable(repositoryAdapterClient.getRepositoryList()) - .orElse(Collections.emptyList()).stream() - .noneMatch(r -> r.getName().equals(repositoryDto.getName())); - - if (duplicateNameCheck) { - repositoryAdapterClient.createRepository(formatType, repositoryDto); - } - throw new IllegalArgumentException("중복된 이름의 레포지토리가 존재합니다."); - } -} diff --git a/src/main/java/kr/co/mcmp/service/oss/NexusHelmAdapterService.java b/src/main/java/kr/co/mcmp/service/oss/NexusHelmAdapterService.java deleted file mode 100644 index 396dc12..0000000 --- a/src/main/java/kr/co/mcmp/service/oss/NexusHelmAdapterService.java +++ /dev/null @@ -1,37 +0,0 @@ -package kr.co.mcmp.service.oss; - -import kr.co.mcmp.dto.oss.NexusFormatType; -import kr.co.mcmp.dto.oss.NexusRepositoryDto; -import kr.co.mcmp.exception.AlreadyExistsException; -import lombok.RequiredArgsConstructor; -import lombok.extern.log4j.Log4j2; -import org.springframework.stereotype.Service; - -import java.util.Collections; -import java.util.Optional; - -@Log4j2 -@Service -@RequiredArgsConstructor -public class NexusHelmAdapterService implements NexusAdapterService { - - private final NexusRepositoryAdapterClient repositoryAdapterClient; - - @Override - public NexusRepositoryDto.ResGetRepositoryDto getRepositoryByName(NexusFormatType formatType, String name) { - return Optional.ofNullable(repositoryAdapterClient.getRepositoryByName(formatType, name)) - .orElseThrow(() -> new IllegalArgumentException("레포지토리 " + name + "을(를) 찾을 수 없습니다.")); - } - - @Override - public void createRepository(NexusFormatType formatType, NexusRepositoryDto.ReqCreateRepositoryDto repositoryDto) { - boolean duplicateNameCheck = Optional.ofNullable(repositoryAdapterClient.getRepositoryList()) - .orElse(Collections.emptyList()).stream() - .noneMatch(r -> r.getName().equals(repositoryDto.getName())); - - if (duplicateNameCheck) { - repositoryAdapterClient.createRepository(formatType, repositoryDto); - } - throw new IllegalArgumentException("중복된 이름의 레포지토리가 존재합니다."); - } -} diff --git a/src/main/java/kr/co/mcmp/service/oss/NexusRawAdapterService.java b/src/main/java/kr/co/mcmp/service/oss/NexusRawAdapterService.java deleted file mode 100644 index 5b283bd..0000000 --- a/src/main/java/kr/co/mcmp/service/oss/NexusRawAdapterService.java +++ /dev/null @@ -1,34 +0,0 @@ -package kr.co.mcmp.service.oss; - -import kr.co.mcmp.dto.oss.NexusFormatType; -import kr.co.mcmp.dto.oss.NexusRepositoryDto; -import kr.co.mcmp.exception.AlreadyExistsException; -import lombok.RequiredArgsConstructor; -import lombok.extern.log4j.Log4j2; -import org.springframework.stereotype.Service; - -import java.util.Collections; -import java.util.Optional; - -@Log4j2 -@Service -@RequiredArgsConstructor -public class NexusRawAdapterService implements NexusAdapterService { - - private final NexusRepositoryAdapterClient repositoryAdapterClient; - - @Override - public NexusRepositoryDto.ResGetRepositoryDto getRepositoryByName(NexusFormatType formatType, String name) { - return repositoryAdapterClient.getRepositoryByName(formatType, name); - } - - @Override - public void createRepository(NexusFormatType formatType, NexusRepositoryDto.ReqCreateRepositoryDto repositoryDto) { - NexusRepositoryDto.ResGetRepositoryDto repositoryOne = repositoryAdapterClient.getRepositoryOne(repositoryDto.getName()); - - if (repositoryOne != null) { - repositoryAdapterClient.createRepository(formatType, repositoryDto); - } - } - -} diff --git a/src/main/java/kr/co/mcmp/service/oss/NexusRepositoryAdapterClient.java b/src/main/java/kr/co/mcmp/service/oss/NexusRepositoryAdapterClient.java deleted file mode 100644 index ec295c0..0000000 --- a/src/main/java/kr/co/mcmp/service/oss/NexusRepositoryAdapterClient.java +++ /dev/null @@ -1,190 +0,0 @@ -package kr.co.mcmp.service.oss; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import kr.co.mcmp.config.oss.RestTemplateProvider; -import kr.co.mcmp.dto.oss.NexusFormatType; -import kr.co.mcmp.dto.oss.NexusRepositoryDto; -import kr.co.mcmp.exception.NexusClientException; -import kr.co.mcmp.util.Base64Util; -import lombok.extern.log4j.Log4j2; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.*; -import org.springframework.stereotype.Service; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.util.UriComponentsBuilder; - -import java.util.Collections; -import java.util.List; - -@Log4j2 -@Service -public class NexusRepositoryAdapterClient { - - private static final String NEXUS_ID = "admin"; - private static final String NEXUS_PWD = "tjxjfkxh!23"; - - private static final String BASE_URL = "http://210.217.178.130:8081/service/rest"; - private static final String AUTHORIZATION = "Authorization"; - - private static final String GET_REPO_LIST = "/v1/repositories"; - private static final String GET_REPO_ONE = "/v1/repositories/{name}"; - private static final String GET_REPO_BY_NAME = "/v1/repositories/{format}/{type}/{name}"; - private static final String POST_CREATE_REPO = "/v1/repositories/{format}/{type}"; - - public List getRepositoryList() { - String url = UriComponentsBuilder.fromHttpUrl(BASE_URL) - .path(GET_REPO_LIST) - .toUriString(); - - HttpEntity request = getRequest(null); - RestTemplate template = RestTemplateProvider.get(); - - try { - ResponseEntity> response = template.exchange( - url, - HttpMethod.GET, - request, - new ParameterizedTypeReference>() {}); - - if (response.getStatusCode() == HttpStatus.OK) { - return response.getBody(); - } else { - throw new IllegalArgumentException("Unexpected Response Status: " + response.getStatusCode() + " from URL: " + url); - } - - } catch (HttpClientErrorException e) { - String errorMessage = e.getResponseBodyAsString(); - String parseMessage = parseErrorMessage(errorMessage); - throw new IllegalArgumentException(parseMessage, e); - } - } - - public NexusRepositoryDto.ResGetRepositoryDto getRepositoryOne(String name) { - String url = UriComponentsBuilder.fromHttpUrl(BASE_URL) - .path(GET_REPO_ONE) - .buildAndExpand(name) - .toUriString(); - - HttpEntity request = getRequest(null); - RestTemplate template = RestTemplateProvider.get(); - - try { - ResponseEntity response = template.exchange( - url, - HttpMethod.GET, - request, - new ParameterizedTypeReference() {}); - - if (response.getStatusCode() == HttpStatus.OK) { - return response.getBody(); - } else { - throw new NexusClientException("Unexpected Response Status: " + response.getStatusCode() + " from URL: " + url); - } - - } catch (HttpClientErrorException e) { - String errorMessage = e.getResponseBodyAsString(); - String parseMessage = parseErrorMessage(errorMessage); - throw new NexusClientException(parseMessage); - } - } - - public NexusRepositoryDto.ResGetRepositoryDto getRepositoryByName(NexusFormatType formatType, String name) { - String url = UriComponentsBuilder.fromHttpUrl(BASE_URL) - .path(GET_REPO_BY_NAME) - .buildAndExpand(formatType.getFormat(), formatType.getType(), name) - .toUriString(); - - HttpEntity request = getRequest(null); - RestTemplate template = RestTemplateProvider.get(); - - try { - ResponseEntity response = template.exchange( - url, - HttpMethod.GET, - request, - new ParameterizedTypeReference() {}); - - if (response.getStatusCode() == HttpStatus.OK) { - return response.getBody(); - } else { - throw new NexusClientException("Unexpected Response Status: " + response.getStatusCode() + " from URL: " + url); - } - - } catch (HttpClientErrorException e) { - String errorMessage = e.getResponseBodyAsString(); - String parseMessage = parseErrorMessage(errorMessage); - throw new NexusClientException(parseMessage); - } - } - - public Object createRepository(NexusFormatType formatType, NexusRepositoryDto.ReqCreateRepositoryDto repositoryDto) { - String url = UriComponentsBuilder.fromHttpUrl(BASE_URL) - .path(POST_CREATE_REPO) - .buildAndExpand(formatType.getFormat(), formatType.getType()) - .toUriString(); - - HttpEntity request = getRequest(repositoryDto); - RestTemplate template = RestTemplateProvider.get(); - - try { - ResponseEntity response = template.exchange( - url, - HttpMethod.POST, - request, - new ParameterizedTypeReference() {}); - - if (response.getStatusCode() == HttpStatus.OK) { - return response.getBody(); - } else { - throw new IllegalArgumentException("Unexpected Response Status: " + response.getStatusCode() + " from URL: " + url); - } - - } catch (HttpClientErrorException e) { - String errorMessage = e.getResponseBodyAsString(); - String parseMessage = parseErrorMessage(errorMessage); - throw new IllegalArgumentException(parseMessage, e); - } - } - - private static HttpEntity getRequest(T body) { - String basicToken = createToken(); - HttpHeaders headers = getHeaders(basicToken); - if (body == null) { - return new HttpEntity(headers); - } - return new HttpEntity(body, headers); - } - - private static HttpHeaders getHeaders(String basicToken) { - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); - headers.set(AUTHORIZATION, basicToken); - return headers; - } - - private static String createToken() { - String auth = NEXUS_ID + ":" + NEXUS_PWD; - String encodedAuth = Base64Util.base64Encoding(auth); - return "Basic " + encodedAuth; - } - - private String parseErrorMessage(String errorMessage) { - ObjectMapper mapper = new ObjectMapper(); - try { - String jsonPart = errorMessage.substring(errorMessage.indexOf("{")); - - JsonNode rootNode = mapper.readTree(jsonPart); - JsonNode messageNode = rootNode.path("message"); - - String message = messageNode.asText(); - return message.replace("\\\"", "\"").replace("\"", ""); - - } catch (Exception e) { - return "Message Parsing Error"; - } - } -} diff --git a/src/main/java/kr/co/mcmp/service/oss/NexusRepositoryService.java b/src/main/java/kr/co/mcmp/service/oss/NexusRepositoryService.java deleted file mode 100644 index 6b1413f..0000000 --- a/src/main/java/kr/co/mcmp/service/oss/NexusRepositoryService.java +++ /dev/null @@ -1,38 +0,0 @@ -package kr.co.mcmp.service.oss; - -import kr.co.mcmp.dto.oss.NexusFormatType; -import kr.co.mcmp.dto.oss.NexusRepositoryDto; -import lombok.RequiredArgsConstructor; -import lombok.extern.log4j.Log4j2; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Log4j2 -@Service -@RequiredArgsConstructor -public class NexusRepositoryService { - - private final NexusRepositoryAdapterClient repositoryAdapterClient; - private final NexusAdapterFactory adapterFactory; - - public List getRepositoryList() { - return repositoryAdapterClient.getRepositoryList(); - } - - public NexusRepositoryDto.ResGetRepositoryDto getRepositoryOne(String name) { - return repositoryAdapterClient.getRepositoryOne(name); - } - - public NexusRepositoryDto.ResGetRepositoryDto getRepositoryByName(NexusFormatType formatType, String name) { - NexusAdapterService adapterService = adapterFactory.getAdapterService(formatType); - return adapterService.getRepositoryByName(formatType, name); - } - - public void createRepository(NexusFormatType formatType, NexusRepositoryDto.ReqCreateRepositoryDto repositoryDto) { - NexusAdapterService adapterService = adapterFactory.getAdapterService(formatType); - adapterService.createRepository(formatType, repositoryDto); - } - - //public updateRepository(String name, NexusRepositoryDto.ReqUpdateRepositoryDto repositoryDto) -} From c4dfbab05ef0d8ca40a3068ba679be0ffd0c6004 Mon Sep 17 00:00:00 2001 From: st-yclee Date: Wed, 28 Aug 2024 10:26:17 +0900 Subject: [PATCH 2/5] =?UTF-8?q?=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=A0=9C=EA=B1=B02?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/co/mcmp/api/response/ResponseCode.java | 72 ------------------- .../co/mcmp/api/response/ResponseWrapper.java | 42 ----------- 2 files changed, 114 deletions(-) delete mode 100644 src/main/java/kr/co/mcmp/api/response/ResponseCode.java delete mode 100644 src/main/java/kr/co/mcmp/api/response/ResponseWrapper.java diff --git a/src/main/java/kr/co/mcmp/api/response/ResponseCode.java b/src/main/java/kr/co/mcmp/api/response/ResponseCode.java deleted file mode 100644 index 2c7037a..0000000 --- a/src/main/java/kr/co/mcmp/api/response/ResponseCode.java +++ /dev/null @@ -1,72 +0,0 @@ -package kr.co.mcmp.api.response; - -import kr.co.mcmp.exception.McmpException; -import lombok.Getter; - -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -@Getter -public enum ResponseCode { - - OK(200, "정상처리 되었습니다."), - - /* common */ - BAD_REQUEST(400, "BAD REQUEST"), - UNAUTHORIZED(401, "UNAUTHORIZED"), - FORBIDDEN(403, "FORBIDDEN"), - NOT_FOUND(404, "NOT FOUND"), - METHOD_NOT_ALLOWED(405,"METHOD NOT ALLOWED"), - CLIENT_ERROR(408,"CLIENT_ERROR"), - CONFLICT(409,"CONFLICT"), - INTERNAL_SERVER_ERROR(500,"INTERNAL SERVER ERROR"), - - /* 공통 코드 */ - COMMON_CODE_EXISTS(9001, "EXISTS COMMON CODE"), - COMMON_CODE_DELETE_NOT_ALLOWED(9002,"DELETE NOT ALLOWED COMMON CODE"), - - /* Exception */ - UNKNOWN_ERROR(9999, "Unknown error"), - - /* GitLab-Project */ - ALREADY_EXISTS(1001, "ALREADY EXISTS"), - CREATE_FAILED_PROJECT_SOURCE(1003, "CREATE FAILED PROJECT SOURCE"), - - /* Jenkins */ - CREATE_FAILED_JENKINS_JOB(1103, "CREATE FAILED JENKINS JOB"), - EXISTS_JENKINS_JOB(1104, "EXISTS JENKINS JOB"), - NOT_EXISTS_JENKINS_JOB(1105, "NOT EXISTS JENKINS JOB"), - ERROR_JENKINS_API(1106, "ERROR JENKINS API"), - - /* Workload Deploy */ - RUN_FAILED_DEPLOY(1201, "RUN FAILED DEPLOY"), - - /* Catalog Deploy */ - CREATE_FAILED_APPLICATION(1301, "CREATE FAILED APPLICATION"), - NOT_EXISTS_APPLICATION(1302, "NOT EXISTS APPLICATION"), - EXISTS_APPLICATION(1303, "EXISTS APPLICATION"), - - /* K8S Client */ - CONNECTION_FAILED_CLUSTER(1401, "CONNECTION FAILED CLUSTER"), - - /* OSS */ - IN_USE_OSS(1501, "OSS IN USE CANNOT BE DELETED"), - IS_NOT_MAPPED_OSS(1502, "IS NOT MAPPED OSS TO SERVICE GROUP."); - - private final int code; - private final String message; - - ResponseCode(int code, String message) { - this.code = code; - this.message = message; - } - - private static final Map map = - Stream.of(values()).collect(Collectors.toMap(ResponseCode::getCode, e -> e)); - - public static ResponseCode findByCode(int code) { - return Optional.ofNullable(map.get(code)).orElseThrow(() -> new McmpException(String.valueOf(ResponseCode.UNKNOWN_ERROR))); - } -} diff --git a/src/main/java/kr/co/mcmp/api/response/ResponseWrapper.java b/src/main/java/kr/co/mcmp/api/response/ResponseWrapper.java deleted file mode 100644 index b81a2dc..0000000 --- a/src/main/java/kr/co/mcmp/api/response/ResponseWrapper.java +++ /dev/null @@ -1,42 +0,0 @@ -package kr.co.mcmp.api.response; - -import lombok.Getter; - -import java.io.Serializable; - -@Getter -public class ResponseWrapper implements Serializable { - - private static final long serialVersionUID = -1745006582949878939L; - - private int code; - private String message; - private String detail; - private T data; - - public ResponseWrapper() { - this(ResponseCode.OK); - } - - public ResponseWrapper(ResponseCode status){ - this.code = status.getCode(); - this.message = status.getMessage(); - } - - public ResponseWrapper(T data) { - this(); - this.data = data; - } - - public ResponseWrapper(ResponseCode status, String detail){ - this(status); - this.detail = detail; - } - - public ResponseWrapper(int code, String message, String detail){ - this.code = code; - this.message = message; - this.detail = detail; - } - -} From 5ad92586c1670b3b14612cf29aac8d0fc09c4262 Mon Sep 17 00:00:00 2001 From: ysh Date: Wed, 28 Aug 2024 16:40:47 +0900 Subject: [PATCH 3/5] =?UTF-8?q?UI=20Template=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- applicationFE/.env | 1 + applicationFE/.eslintrc.cjs | 19 + applicationFE/.gitignore | 31 ++ applicationFE/.prettierrc.json | 8 + applicationFE/README.md | 39 ++ applicationFE/env.d.ts | 10 + applicationFE/index.html | 13 + applicationFE/nginx/nginx.config | 15 + applicationFE/package.json | 47 +++ applicationFE/src/App.vue | 11 + applicationFE/src/api/eventListener.ts | 45 +++ applicationFE/src/api/oss.ts | 57 +++ applicationFE/src/api/workflow.ts | 63 ++++ applicationFE/src/api/workflowStage.ts | 56 +++ applicationFE/src/common/request.ts | 49 +++ .../src/components/Table/TableHeader.vue | 56 +++ .../src/components/Table/Tabulator.vue | 85 +++++ applicationFE/src/img/icon/Plus.svg | 5 + applicationFE/src/main.ts | 30 ++ applicationFE/src/permission.ts | 8 + applicationFE/src/router/index.ts | 19 + applicationFE/src/stores/counter.ts | 12 + applicationFE/src/utils/common.js | 240 +++++++++++++ applicationFE/src/utils/input-validate.js | 250 +++++++++++++ applicationFE/src/utils/scroll-to.js | 58 +++ applicationFE/src/utils/validate.js | 92 +++++ applicationFE/src/views/oss/OssList.vue | 158 +++++++++ .../src/views/oss/components/deleteOss.vue | 59 +++ .../src/views/oss/components/ossForm.vue | 335 ++++++++++++++++++ applicationFE/src/views/type/type.ts | 14 + applicationFE/tsconfig.app.json | 14 + applicationFE/tsconfig.json | 11 + applicationFE/tsconfig.node.json | 19 + applicationFE/vite-env.d.ts | 10 + applicationFE/vite.config.ts | 26 ++ 35 files changed, 1965 insertions(+) create mode 100644 applicationFE/.env create mode 100644 applicationFE/.eslintrc.cjs create mode 100644 applicationFE/.gitignore create mode 100644 applicationFE/.prettierrc.json create mode 100644 applicationFE/README.md create mode 100644 applicationFE/env.d.ts create mode 100644 applicationFE/index.html create mode 100644 applicationFE/nginx/nginx.config create mode 100644 applicationFE/package.json create mode 100644 applicationFE/src/App.vue create mode 100644 applicationFE/src/api/eventListener.ts create mode 100644 applicationFE/src/api/oss.ts create mode 100644 applicationFE/src/api/workflow.ts create mode 100644 applicationFE/src/api/workflowStage.ts create mode 100644 applicationFE/src/common/request.ts create mode 100644 applicationFE/src/components/Table/TableHeader.vue create mode 100644 applicationFE/src/components/Table/Tabulator.vue create mode 100644 applicationFE/src/img/icon/Plus.svg create mode 100644 applicationFE/src/main.ts create mode 100644 applicationFE/src/permission.ts create mode 100644 applicationFE/src/router/index.ts create mode 100644 applicationFE/src/stores/counter.ts create mode 100644 applicationFE/src/utils/common.js create mode 100644 applicationFE/src/utils/input-validate.js create mode 100644 applicationFE/src/utils/scroll-to.js create mode 100644 applicationFE/src/utils/validate.js create mode 100644 applicationFE/src/views/oss/OssList.vue create mode 100644 applicationFE/src/views/oss/components/deleteOss.vue create mode 100644 applicationFE/src/views/oss/components/ossForm.vue create mode 100644 applicationFE/src/views/type/type.ts create mode 100644 applicationFE/tsconfig.app.json create mode 100644 applicationFE/tsconfig.json create mode 100644 applicationFE/tsconfig.node.json create mode 100644 applicationFE/vite-env.d.ts create mode 100644 applicationFE/vite.config.ts diff --git a/applicationFE/.env b/applicationFE/.env new file mode 100644 index 0000000..3fd20df --- /dev/null +++ b/applicationFE/.env @@ -0,0 +1 @@ +# VITE_API_URL="http://localhost:18083" \ No newline at end of file diff --git a/applicationFE/.eslintrc.cjs b/applicationFE/.eslintrc.cjs new file mode 100644 index 0000000..7e4f590 --- /dev/null +++ b/applicationFE/.eslintrc.cjs @@ -0,0 +1,19 @@ +/* eslint-env node */ +require('@rushstack/eslint-patch/modern-module-resolution') + +module.exports = { + root: true, + 'extends': [ + 'plugin:vue/vue3-essential', + 'eslint:recommended', + '@vue/eslint-config-typescript', + '@vue/eslint-config-prettier/skip-formatting' + ], + parserOptions: { + ecmaVersion: 'latest' + }, + rules: { + // should always be multi-word 적용 X + 'vue/multi-word-component-names' : 0 + }, +} diff --git a/applicationFE/.gitignore b/applicationFE/.gitignore new file mode 100644 index 0000000..cef63ec --- /dev/null +++ b/applicationFE/.gitignore @@ -0,0 +1,31 @@ +yarn.lock +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/applicationFE/.prettierrc.json b/applicationFE/.prettierrc.json new file mode 100644 index 0000000..66e2335 --- /dev/null +++ b/applicationFE/.prettierrc.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": false, + "tabWidth": 2, + "singleQuote": true, + "printWidth": 100, + "trailingComma": "none" +} \ No newline at end of file diff --git a/applicationFE/README.md b/applicationFE/README.md new file mode 100644 index 0000000..342b5c1 --- /dev/null +++ b/applicationFE/README.md @@ -0,0 +1,39 @@ +# workflow-manager-ui + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +yarn install +``` + +### Compile and Hot-Reload for Development + +```sh +yarn dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +yarn build +``` + +### Lint with [ESLint](https://eslint.org/) + +```sh +yarn lint +``` diff --git a/applicationFE/env.d.ts b/applicationFE/env.d.ts new file mode 100644 index 0000000..409cda1 --- /dev/null +++ b/applicationFE/env.d.ts @@ -0,0 +1,10 @@ +/// + +interface ImportMetaEnv { + readonly VITE_API_URL: string + // 다른 환경 변수들에 대한 타입 정의... + } + + interface ImportMeta { + readonly env: ImportMetaEnv + } \ No newline at end of file diff --git a/applicationFE/index.html b/applicationFE/index.html new file mode 100644 index 0000000..c6f3b8c --- /dev/null +++ b/applicationFE/index.html @@ -0,0 +1,13 @@ + + + + + + + Workflow + + +
+ + + diff --git a/applicationFE/nginx/nginx.config b/applicationFE/nginx/nginx.config new file mode 100644 index 0000000..e43ec02 --- /dev/null +++ b/applicationFE/nginx/nginx.config @@ -0,0 +1,15 @@ +server { + listen 80; + listen [::]:80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + try_files $uri $uri/ /index.html; + } + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +} \ No newline at end of file diff --git a/applicationFE/package.json b/applicationFE/package.json new file mode 100644 index 0000000..620217d --- /dev/null +++ b/applicationFE/package.json @@ -0,0 +1,47 @@ +{ + "name": "application-manager-ui", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build --force", + "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", + "format": "prettier --write src/" + }, + "dependencies": { + "@tabler/core": "^1.0.0-beta20", + "ace-builds": "^1.35.2", + "axios": "^1.7.2", + "bootstrap": "^5.3.0", + "lodash": "^4.17.21", + "pinia": "^2.1.7", + "tabulator-tables": "^6.2.1", + "vue": "^3.4.29", + "vue-draggable-next": "^2.2.1", + "vue-router": "^4.3.3", + "vue-toastification": "^2.0.0-rc.5", + "vue3-ace-editor": "^2.2.4" + }, + "devDependencies": { + "@rushstack/eslint-patch": "^1.8.0", + "@tsconfig/node20": "^20.1.4", + "@types/node": "^20.14.5", + "@types/tabulator-tables": "^6.2.2", + "@vitejs/plugin-vue": "^5.0.5", + "@vue/eslint-config-prettier": "^9.0.0", + "@vue/eslint-config-typescript": "^13.0.0", + "@vue/tsconfig": "^0.5.1", + "eslint": "^8.57.0", + "eslint-plugin-vue": "^9.23.0", + "npm-run-all2": "^6.2.0", + "prettier": "^3.2.5", + "typescript": "~5.4.0", + "vite": "^5.3.1", + "vite-plugin-vue-devtools": "^7.3.1", + "vue-tsc": "^2.0.21" + } +} diff --git a/applicationFE/src/App.vue b/applicationFE/src/App.vue new file mode 100644 index 0000000..df4dfcf --- /dev/null +++ b/applicationFE/src/App.vue @@ -0,0 +1,11 @@ + + + + + + diff --git a/applicationFE/src/api/eventListener.ts b/applicationFE/src/api/eventListener.ts new file mode 100644 index 0000000..791e6b4 --- /dev/null +++ b/applicationFE/src/api/eventListener.ts @@ -0,0 +1,45 @@ +import request from "../common/request"; +import type { EventListener } from "../views/type/type"; + + +// Event Listener 목록 +export const getEventListenerList = () => { + return request.get('/eventlistener/list') +} + +// Event Listener 상세 +export function getEventListenerDetailInfo(eventlistenerIdx:number) { + return request.get("/eventlistener/" + eventlistenerIdx); +} + +// 중복확인 +export function duplicateCheck(param: {eventListenerName:string, eventListenerUrl: string}) { + return request.get(`/eventlistener/duplicate?eventlistenerName=${param.eventListenerName}&eventListenerUrl=${param.eventListenerUrl}`) +} + +// Event Listener 등록 +export function registEventListener(param: EventListener) { + return request.post(`/eventlistener`, param) +} + +// Event Listener 수정 +export function updateEventListener(param: EventListener) { + return request.patch(`/eventlistener/${param.eventListenerIdx}`, param) +} + +// Event Listener 삭제 +export function deleteEventListener(eventlistenerIdx: number) { + return request.delete(`/eventlistener/${eventlistenerIdx}`) +} + + + + + + + + + + + + diff --git a/applicationFE/src/api/oss.ts b/applicationFE/src/api/oss.ts new file mode 100644 index 0000000..172121d --- /dev/null +++ b/applicationFE/src/api/oss.ts @@ -0,0 +1,57 @@ +import request from "../common/request"; +import type { Oss } from "../views/type/type"; + + +// OSS Type 목록 +export const getOssTypeList = () => { + return request.get('/ossType/list') +} + +// OSS Type 필터링 목록 +// 이미 생성된 OSS는 또 다시 생성할 수 없다 +export const getOssTypeFilteredList = () => { + return request.get('/ossType/filter/list') +} + +// OSS 목록 +export const getOssAllList = () => { + return request.get('/oss/list') +} + +// OSS 목록 +export const getOssList = (ossTypeName:string) => { + return request.get(`/oss/list/${ossTypeName}`) +} + +// 중복확인 +export function duplicateCheck(param: { ossName:string, ossUrl:string, ossUsername:string}) { + return request.get(`/oss/duplicate?ossName=${param.ossName}&ossUrl=${param.ossUrl}&ossUsername=${param.ossUsername}`) +} + + +// 연결 확인 +export function ossConnectionChecked(param: { ossUrl: string, ossUsername: string, ossPassword: string, ossTypeIdx: number }) { + return request.post(`/oss/connection-check`, param) +} + + +// OSS 상세 +export function getOssDetailInfo(ossIdx:number | string | string[]) { + return request.get("/oss/" + ossIdx); +} + + +// OSS 등록 +export function registOss(param:Oss) { + return request.post(`/oss`, param) +} + +// OSS 수정 +export function updateOss(param: Oss) { + return request.patch(`/oss/${param.ossIdx}`, param) +} + +// OSS 삭제 +export function deleteOss(ossIdx: number) { + return request.delete(`/oss/${ossIdx}`) +} \ No newline at end of file diff --git a/applicationFE/src/api/workflow.ts b/applicationFE/src/api/workflow.ts new file mode 100644 index 0000000..3a05221 --- /dev/null +++ b/applicationFE/src/api/workflow.ts @@ -0,0 +1,63 @@ +import request from "../common/request"; +import type { Workflow } from "../views/type/type" + +// 워크플로우 목록 +// export const getWorkflowList = () => { +// return request.get('/workflow/list') +// } +export const getWorkflowList = (eventlistenerYn:String) => { + return request.get(`/eventlistener/workflowList/${eventlistenerYn}`) +} + +// 중복확인 +export function duplicateCheck(workflowName:string) { + return request.get(`/workflow/name/duplicate?workflowName=${workflowName}`) +} + +// default 스크립트 +export function getTemplateStage(workflowName:string) { + return request.get(`/workflow/template/${workflowName}`) +} + +// 파이프라인 목록 +export function getWorkflowPipelineList() { + return request.get(`/workflow/workflowStageList`) +} + +// 파이프라인 구분 목록 +export function getPipelineCdList() { + return request.get(`/workflowStageType/list`); +} + +// 워크플로우 상세 +// export function getWorkflowDetailInfo(workflowIdx:number | string | string[]) { +// return request.get("/workflow/" + workflowIdx + "/N"); +// } +export function getWorkflowDetailInfo(workflowIdx:number | string | string[], eventlistenerYn:String) { + return request.get(`/eventlistener/workflowDetail/${workflowIdx}/${eventlistenerYn}`); +} + +// 저장 +export function registWorkflow(workflow: Workflow | any) { + return request.post(`/workflow`, workflow); +} + +// 수정 +export function updateWorkflow(workflow: Workflow | any) { + return request.patch(`/workflow/${workflow.workflowInfo.workflowIdx}`, workflow); +} + + +// 삭제 +export function deleteWorkflow(workflowIdx: number) { + return request.delete(`/workflow/${workflowIdx}`); +} + +// 배포 실행 +export function runWorkflow(params: Workflow) { + return request.post(`/workflow/run`, params); +} + +export function existEventListener(workflowIdx: number) { + return request.get(`/workflow/existEventListener/${workflowIdx}`); +} \ No newline at end of file diff --git a/applicationFE/src/api/workflowStage.ts b/applicationFE/src/api/workflowStage.ts new file mode 100644 index 0000000..c0e8cd5 --- /dev/null +++ b/applicationFE/src/api/workflowStage.ts @@ -0,0 +1,56 @@ +import request from "../common/request"; +import type { WorkflowStage } from "../views/type/type"; + + +// Workflow Stage Type 목록 +export const getWorkflowStageTypeList = () => { + return request.get('/workflowStageType/list') +} + +// Workflow Stage 목록 +export const getWorkflowStageList = () => { + return request.get('/workflowStage/list') +} + +// Workflow Stage 상세 +export function getWorkflowStageDetailInfo(workflowStageIdx:number) { + return request.get("/workflowStage/" + workflowStageIdx); +} + +// 중복확인 +export function duplicateCheck(param: { workflowStageName:string, workflowStageTypeName:string}) { + return request.get(`/workflowStage/duplicate?workflowStageName=${param.workflowStageName}&workflowStageTypeName=${param.workflowStageTypeName}`) +} + +// Workflow Stage 등록 +export function registWorkflowStage(param: WorkflowStage) { + return request.post(`/workflowStage`, param) +} + +// Workflow Stage 수정 +export function updateWorkflowStage(param: WorkflowStage) { + return request.patch(`/workflowStage/${param.workflowStageIdx}`, param) +} + +// Workflow Stage 삭제 +export function deleteWorkflowStage(workflowStageIdx: number) { + return request.delete(`/workflowStage/${workflowStageIdx}`) +} + +// Workflow Stage DefaultScript 조회 +export function getWorkflowStageDefaultScript(workflowStageTypeName: string) { + return request.get(`/workflowStage/default/script/${workflowStageTypeName}`) +} + + + + + + + + + + + + + diff --git a/applicationFE/src/common/request.ts b/applicationFE/src/common/request.ts new file mode 100644 index 0000000..68a30a8 --- /dev/null +++ b/applicationFE/src/common/request.ts @@ -0,0 +1,49 @@ +import axios from "axios"; +import { useToast } from "vue-toastification"; + +const splitUrl = window.location.host.split(':'); +const baseUrl = window.location.protocol + '//' + splitUrl[0] + ':18083' +const toast = useToast(); +const service = axios.create({ + // baseURL: process.env.VUE_APP_API_URL, + baseURL: baseUrl, + timeout: 300000 +}); + + +// request interceptor +service.interceptors.request.use( + config => { + // console.log("##[", "api", "]##", "request", config.url, config); + return config; + }, + error => { + console.log("error ---------- ", error); + return Promise.reject(error); + } +); + +// response interceptor +service.interceptors.response.use( + response => { + const res = response.data; + + if (res.code === 200) { + return res; + } else { + toast.error(res.detail) + return Promise.reject(new Error(res.message || "Error")); + } + }, + error => { + console.log("ApiService.Response -> fail", error); + + if (axios.isCancel(error)) { + return Promise.reject(error); + } + // toast.error(error.message) + return Promise.reject(error); + } +); + +export default service; diff --git a/applicationFE/src/components/Table/TableHeader.vue b/applicationFE/src/components/Table/TableHeader.vue new file mode 100644 index 0000000..7358f09 --- /dev/null +++ b/applicationFE/src/components/Table/TableHeader.vue @@ -0,0 +1,56 @@ + + + \ No newline at end of file diff --git a/applicationFE/src/components/Table/Tabulator.vue b/applicationFE/src/components/Table/Tabulator.vue new file mode 100644 index 0000000..a4840b0 --- /dev/null +++ b/applicationFE/src/components/Table/Tabulator.vue @@ -0,0 +1,85 @@ + + + + \ No newline at end of file diff --git a/applicationFE/src/img/icon/Plus.svg b/applicationFE/src/img/icon/Plus.svg new file mode 100644 index 0000000..270fa62 --- /dev/null +++ b/applicationFE/src/img/icon/Plus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/applicationFE/src/main.ts b/applicationFE/src/main.ts new file mode 100644 index 0000000..e5efa72 --- /dev/null +++ b/applicationFE/src/main.ts @@ -0,0 +1,30 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import '@tabler/core/dist/css/tabler.min.css' +import 'tabulator-tables/dist/css/tabulator_bootstrap4.min.css' +import axios from 'axios' +import './permission' + +const app = createApp(App) + +// Axios +axios.defaults.baseURL = import.meta.env.VITE_API_URL +app.config.globalProperties.axios = axios + +app.use(createPinia()) + +import router from './router' +app.use(router) + +import Toast from "vue-toastification"; +import "vue-toastification/dist/index.css"; +app.use(Toast, {}); + + +import 'bootstrap/dist/css/bootstrap.min.css' +import 'bootstrap/dist/js/bootstrap.bundle.min.js' + +app.mount('#app') + diff --git a/applicationFE/src/permission.ts b/applicationFE/src/permission.ts new file mode 100644 index 0000000..e1ea05b --- /dev/null +++ b/applicationFE/src/permission.ts @@ -0,0 +1,8 @@ +import router from "./router/index"; + +router.beforeEach(async (to, from, next) => { + console.log('## to ### : ', to) + console.log('## from ### : ', from) + + next(); +}); \ No newline at end of file diff --git a/applicationFE/src/router/index.ts b/applicationFE/src/router/index.ts new file mode 100644 index 0000000..8812cc9 --- /dev/null +++ b/applicationFE/src/router/index.ts @@ -0,0 +1,19 @@ +import { createRouter, createWebHistory } from 'vue-router' + +const router = createRouter({ + history: createWebHistory(), + routes: [ + { + path: '/web', + name: 'rootOssList', + component: () => import('@/views/oss/OssList.vue' as any) + }, + { + path: '/web/oss/list', + name: 'ossList', + component: () => import('@/views/oss/OssList.vue' as any) + }, + ] +}) + +export default router diff --git a/applicationFE/src/stores/counter.ts b/applicationFE/src/stores/counter.ts new file mode 100644 index 0000000..b6757ba --- /dev/null +++ b/applicationFE/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/applicationFE/src/utils/common.js b/applicationFE/src/utils/common.js new file mode 100644 index 0000000..e465424 --- /dev/null +++ b/applicationFE/src/utils/common.js @@ -0,0 +1,240 @@ + +/* 사용자 정보 이름과 아이디 함께 노출시 정의한 포맷으로 반환*/ +export function getUserNameAndIdStr(name, id) { + name = name || '' + id = id || '' + return `${name}(@${id})` +} + +export function validateGroupName(name) { + const reg = /^[A-z0-9_-]{1,50}$/ + return reg.test(name) +} + +export function validateProjectName(name) { + const reg = /^[A-z0-9_-]{1,50}$/ + return reg.test(name) +} + +export function validateOpenShiftAppName(name) { + //alphanumeric (a-z, 0-9) 최대 16 character. 첫 글자는 a-z 만 허용. ‘-’ 는 허용되는데 처음과 끝은 안됨 + const reg = /^[A-Za-z]{1}[A-z0-9_-]{1,16}[A-Za-z0-9]$/ + return reg.test(name) +} + + + +/** + * 바이트 문자 입력가능 문자수 체크 + * + * @param id : tag id + * @param title : tag title + * @param maxLength : 최대 입력가능 수 (byte) + * @returns {Boolean} + */ +export function maxLengthCheck(title, maxLength){ + maxLength = maxLength || 255; + if(Number(byteCheck(title)) > Number(maxLength)) { + return false; + } else { + return true; + } +} + +/** +* 바이트수 반환 +* +* @param el : tag jquery object +* @returns {Number} +*/ +export function byteCheck(txt){ + let codeByte = 0; + for (let idx = 0; idx < txt.length; idx++) { + let oneChar = escape(txt.charAt(idx)); + if ( oneChar.length == 1 ) { + codeByte ++; + } else if (oneChar.indexOf("%u") != -1) { + codeByte += 2; + } else if (oneChar.indexOf("%") != -1) { + codeByte ++; + } + } + return codeByte; +} + + +export function getSize(fileSize, fixed) { + var value = {} + // GB 단위 이상일때 GB 단위로 환산 + if (fileSize >= 1024 * 1024 * 1024) { + fileSize = fileSize / (1024 * 1024 * 1024) + fileSize = (fixed === undefined) ? fileSize : fileSize.toFixed(fixed) + value.size = fileSize + value.unit = 'gb' + } + + // MB 단위 이상일때 MB 단위로 환산 + if (fileSize >= 1024 * 1024) { + fileSize = fileSize / (1024 * 1024) + fileSize = (fixed === undefined) ? fileSize : fileSize.toFixed(fixed) + value.size = fileSize + value.unit = 'mb' + } else if (fileSize >= 1024) { // KB 단위 이상일때 KB 단위로 환산 + fileSize = fileSize / 1024 + fileSize = (fixed === undefined) ? fileSize : fileSize.toFixed(fixed) + value.size = fileSize + value.unit = 'kb' + } else { // KB 단위보다 작을때 byte 단위로 환산 + fileSize = (fixed === undefined) ? fileSize : fileSize.toFixed(fixed) + value.size = fileSize + value.unit = 'byte' + } + return value +} + +export function isOverOneDay(curDate) { + var today, resultDate + today = new Date() + resultDate = new Date(curDate) + + // Time (minutes * seconds * millisecond) + if ((today - resultDate) / (60 * 60 * 1000) <= 24) { + return true + } + return false +} + +export function toPascalCase(str) { + var arr = str.split(/\s|_/) + for (var i = 0, l = arr.length; i < l; i++) { + arr[i] = arr[i].substr(0, 1).toUpperCase() + + (arr[i].length > 1 ? arr[i].substr(1).toLowerCase() : '') + } + return arr.join(' ') +} + +export function copyClipboard(str) { + var tempElem = document.createElement('textarea') + tempElem.value = str + document.body.appendChild(tempElem) + + tempElem.select() + document.execCommand('copy') + document.body.removeChild(tempElem) +} + + +/* + - ary 요소의 key, value 값을 오브젝트로 만들기. + - call: deploy params에서 호출 +*/ +export function arrayToObject(ary) { + let object = {}; + if (ary == null) + return {}; + + ary.forEach((item) => { + object[item.key] = item.value; + }) + + return object; +} + +/* + - ary 요소의 object.value값을 배열의 요소로 만들기. + - call: deploy params에서 호출 +*/ +export function valueObjectToArray(ary) { + let array = []; + if (ary == null) + return []; + + + ary.forEach((item) => { + array.push(item.value); + }) + + return array; +} + + +/* +object 정보를 key, value 오브젝트 배열 요소로 추가 + { + key1:value1, + key2:value2 + } + + => + [{key1:value1},{key2:value2}] +*/ +export function objectToArray(obj) { + let toArray = []; + if (obj == null) + return []; + + Object.keys(obj).forEach((key) => { + toArray.push({ + key: key, + value:obj[key] + }) + }) + + return toArray; +} + +/* +["value1", "value2"] => [{value:"value1"}, {value:"value2"}] +*/ +export function arrayToValueObjectArray(targetArray) { + let toArray = []; + + if (targetArray == null) + return [{value:""}]; + + targetArray.forEach((value) => { + toArray.push({ + value:value + }) + }) + + return toArray; +} + + + +export function isEmptyObject(obj) { + if (obj == null) + return true; + + + if (Object.keys(obj).length == 0) { + return true; + } + + return false; +} + + +/* +.을 기준으로 앞에는 name +뒤에는 domin 값으로 분리하는 기능 +*/ +export function splitACRServerInfo(str) { + let index = str.indexOf("."); + let info = { + name:"", + domain:"" + } + if (index == -1) { + info.name = str; + } else { + info.name = str.substr(0, index); + info.domain = str.substr(index+1, str.length); + } + + return info; +} +export function joinACRServerInfo(name, domain) { + return name +"."+domain; +} \ No newline at end of file diff --git a/applicationFE/src/utils/input-validate.js b/applicationFE/src/utils/input-validate.js new file mode 100644 index 0000000..ee20828 --- /dev/null +++ b/applicationFE/src/utils/input-validate.js @@ -0,0 +1,250 @@ +// import { checkIP } from './validate' + + + + +// const _validateAlphanumericUnderbarHyphen = (rule, value, callback) => { +// const { t } = i18n.global; +// const reg = /^[A-z0-9_-]{1,50}$/ + +// if (!reg.test(value)) { +// callback(new Error(t("validation.alphanumericUnderbarHyphen"))); +// } else { +// callback() +// } +// } + +// const _validateAlphanumericUnderbarHyphenSpace = (rule, value, callback) => { +// const { t } = i18n.global; +// const reg = /^[A-z0-9_-\s]{1,50}$/ + +// if (!reg.test(value)) { +// callback(new Error(t("validation.alphanumericUnderbarHyphen"))); +// } else { +// callback() +// } +// } + +// const _validateAlphaNumeric = (rule, value, callback) => { +// const { t } = i18n.global; +// const reg = /^[0-9a-zA-Z]+$/ +// if (!reg.test(value)) { +// callback(new Error(t("validation.alphanumeric"))); +// } else { +// callback() +// } +// } +export const _validateAlphaNumericHyphen= (rule, value, callback) => { + const reg = /^[0-9a-zA-Z-]+$/ + if (!reg.test(value)) { + callback(new Error("규칙에 맞게 입력해주세요.(영문자, 숫자, (-)만 가능)")); + } else { + callback() + } +} + +// const _validateDomain = (rule, value, callback) => { +// const { t } = i18n.global; +// const reg = /^[^((http(s?))\:\/\/)]([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/ +// if (!reg.test(value)) { +// callback(new Error(t("validation.domain"))); +// } else { +// callback() +// } + +// } + +// const _validateOpenShiftAppName = (rule, value, callback) => { +// const { t } = i18n.global; +// //alphanumeric (a-z, 0-9) 최대 16 character. 첫 글자는 a-z 만 허용. ‘-’ 는 허용되는데 처음과 끝은 안됨 +// const reg = /^[A-Za-z]{1}[A-z0-9_-]{1,16}[A-Za-z0-9]$/ +// if (!reg.test(value) || value.length > 16) { +// callback(new Error(t("validation.openShiftAppNameMsg"))); +// } else { +// callback() +// } +// } + +// const _validateAppName = (rule, value, callback) => { +// const { t } = i18n.global; +// //alphanumeric (a-z, 0-9) 최대 16 character. 첫 글자는 a-z 만 허용. ‘-’ 는 허용되는데 처음과 끝은 안됨 +// const reg = /^[a-z]{1}[a-z0-9_-]{1,16}$/ +// if (!reg.test(value) || value.length > 16) { +// callback(new Error(t("validation.appNameMsg"))); +// } else { +// callback() +// } +// } + + +// const _validateName = (rule, value, callback) => { +// const { t } = i18n.global; +// if (value==null || !value.toString().length) { +// callback(new Error(t("validation.msgEmtpyInput"))); +// } else { +// callback() + +// } + +// } + +// const _valdateLimitLength=(rule, value, callback)=>{ +// const { t } = i18n.global; +// if (value.length > rule.length) { +// callback(new Error(t("validation.limitLength"))); +// } else { +// callback() +// } +// } + +export const _validateLength = (rule, value, callback) => { + if (value.length < rule.length) { + if (rule.length == 2) { + callback(new Error("2자 이상 입력해주세요.")); + return + } + if (rule.length == 3) { + callback(new Error("3자 이상 입력해주세요.")); + return + } + if (rule.length == 4) { + callback(new Error("4자 이상 입력해주세요.")); + return + } + callback(new Error("내용을 입력해주세요.")); + } else { + callback() + } +} + +// const _validateIp = (rule, value, callback) => { +// const { t } = i18n.global; +// if (checkIP(value) == false) { +// callback(new Error(t("validation.msgIP"))); +// } else { +// callback() +// } +// } + +// const _validateEmail = (rule, value, callback) => { +// const { t } = i18n.global; +// const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + +// if (reg.test(value) == false) { +// callback(new Error(t("validation.msgEmail"))); +// } else { +// callback() +// } +// } + +// const _validateUserPassword = (rule, value, callback) => { +// const { t } = i18n.global; +// const passwordPatten = /^(?=.*?[A-Z])(?=.*?[0-9]).{8,16}$/ +// if (passwordPatten.test(value) == false) { +// let msgType = rule.msgType || "full"; +// if(msgType=="full") +// callback(new Error(t("validation.msgPw"))); +// else +// callback(new Error(t("validation.msgSimplePw"))); + +// } else { +// callback() +// } +// } + +// const _validatePackageName = (rule, value, callback) => { +// const { t } = i18n.global; +// const packageNamePatten = /^([A-Za-z]{1}[A-Za-z\d_]*\.)*[A-Za-z][A-Za-z\d_]*$/ +// if (packageNamePatten.test(value) == false) { +// callback(new Error(t("validation.msgPackageName"))); + +// } else { +// callback() +// } +// } + + +// const _validateUserLengthPassword = (rule, value, callback) => { +// const { t } = i18n.global; +// let temp = value.toString(); +// if (temp.length>=8 && temp.length<=16) { +// callback() +// } else { +// callback(new Error(t("validation.msgPw2"))); +// } +// } + +// const _validateSelect = (rule, value, callback) => { +// const { t } = i18n.global; +// if (value=="" || value==undefined) { +// callback(new Error(t("validation.msgSelect"))); +// } else { +// callback() +// } +// } + +// const _validateSelect2 = (rule, value, callback) => { +// const { t } = i18n.global; +// if (parseInt(value)==-1) { +// callback(new Error(t("validation.msgSelect"))); +// } else { +// callback() +// } +// } + + + +// const _validateURL = (rule, value, callback) => { +// const { t } = i18n.global; +// const urlPatten = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/ +// if (urlPatten.test(value) == false) { +// callback(new Error(t("validation.msgURL"))); +// } else { +// callback() +// } +// } + +// const _validateURL_http = (rule, value, callback) => { +// console.log('http == ', value) +// const { t } = i18n.global; +// const urlPatten = /^(http):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/ +// if (urlPatten.test(value) == false) { +// callback(new Error(t("validation.msgURL"))); +// } else { +// callback() +// } +// } + +// const _validateURL_https = (rule, value, callback) => { +// console.log('https == ', value) +// const { t } = i18n.global; +// const urlPatten = /^(https):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/ +// if (urlPatten.test(value) == false) { +// callback(new Error(t("validation.msgURL"))); +// } else { +// callback() +// } +// } + +// export { +// _validateName, +// _validateLength, +// _validateIp, +// _validateEmail, +// _validateUserPassword, +// _validateUserLengthPassword, +// _validatePackageName, +// _validateSelect, +// _validateSelect2, +// _validateURL, +// _validateURL_http, +// _validateURL_https, +// _valdateLimitLength, +// _validateAlphanumericUnderbarHyphen, +// _validateAlphanumericUnderbarHyphenSpace, +// _validateAlphaNumeric, +// _validateAlphaNumericHyphen, +// _validateDomain, +// _validateOpenShiftAppName, +// _validateAppName +// } diff --git a/applicationFE/src/utils/scroll-to.js b/applicationFE/src/utils/scroll-to.js new file mode 100644 index 0000000..c5d8e04 --- /dev/null +++ b/applicationFE/src/utils/scroll-to.js @@ -0,0 +1,58 @@ +Math.easeInOutQuad = function(t, b, c, d) { + t /= d / 2 + if (t < 1) { + return c / 2 * t * t + b + } + t-- + return -c / 2 * (t * (t - 2) - 1) + b +} + +// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts +var requestAnimFrame = (function() { + return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) } +})() + +/** + * Because it's so fucking difficult to detect the scrolling element, just move them all + * @param {number} amount + */ +function move(amount) { + document.documentElement.scrollTop = amount + document.body.parentNode.scrollTop = amount + document.body.scrollTop = amount +} + +function position() { + return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop +} + +/** + * @param {number} to + * @param {number} duration + * @param {Function} callback + */ +export function scrollTo(to, duration, callback) { + const start = position() + const change = to - start + const increment = 20 + let currentTime = 0 + duration = (typeof (duration) === 'undefined') ? 500 : duration + var animateScroll = function() { + // increment the time + currentTime += increment + // find the value with the quadratic in-out easing function + var val = Math.easeInOutQuad(currentTime, start, change, duration) + // move the document.body + move(val) + // do the animation unless its over + if (currentTime < duration) { + requestAnimFrame(animateScroll) + } else { + if (callback && typeof (callback) === 'function') { + // the animation is done so lets callback + callback() + } + } + } + animateScroll() +} diff --git a/applicationFE/src/utils/validate.js b/applicationFE/src/utils/validate.js new file mode 100644 index 0000000..0f3d0b0 --- /dev/null +++ b/applicationFE/src/utils/validate.js @@ -0,0 +1,92 @@ +/** + * Created by PanJiaChen on 16/11/18. + */ + +/** + * @param {string} path + * @returns {Boolean} + */ +export function isExternal(path) { + return /^(https?:|mailto:|tel:)/.test(path) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validUsername(str) { + const valid_map = ['admin', 'editor'] + return valid_map.indexOf(str.trim()) >= 0 +} + +/** + * @param {string} url + * @returns {Boolean} + */ +export function validURL(url) { + const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/ + return reg.test(url) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validLowerCase(str) { + const reg = /^[a-z]+$/ + return reg.test(str) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validUpperCase(str) { + const reg = /^[A-Z]+$/ + return reg.test(str) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validAlphabets(str) { + const reg = /^[A-Za-z]+$/ + return reg.test(str) +} + +/** + * @param {string} email + * @returns {Boolean} + */ +export function validEmail(email) { + const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + return reg.test(email) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function isString(str) { + if (typeof str === 'string' || str instanceof String) { + return true + } + return false +} + +/** + * @param {Array} arg + * @returns {Boolean} + */ +export function isArray(arg) { + if (typeof Array.isArray === 'undefined') { + return Object.prototype.toString.call(arg) === '[object Array]' + } + return Array.isArray(arg) +} + +export function checkIP(strIP) { + var expUrl = /^(1|2)?\d?\d([.](1|2)?\d?\d){3}$/ + return expUrl.test(strIP) +} diff --git a/applicationFE/src/views/oss/OssList.vue b/applicationFE/src/views/oss/OssList.vue new file mode 100644 index 0000000..98d01ff --- /dev/null +++ b/applicationFE/src/views/oss/OssList.vue @@ -0,0 +1,158 @@ + + \ No newline at end of file diff --git a/applicationFE/src/views/oss/components/deleteOss.vue b/applicationFE/src/views/oss/components/deleteOss.vue new file mode 100644 index 0000000..0796e71 --- /dev/null +++ b/applicationFE/src/views/oss/components/deleteOss.vue @@ -0,0 +1,59 @@ + + + \ No newline at end of file diff --git a/applicationFE/src/views/oss/components/ossForm.vue b/applicationFE/src/views/oss/components/ossForm.vue new file mode 100644 index 0000000..ca709c6 --- /dev/null +++ b/applicationFE/src/views/oss/components/ossForm.vue @@ -0,0 +1,335 @@ + + + + + \ No newline at end of file diff --git a/applicationFE/src/views/type/type.ts b/applicationFE/src/views/type/type.ts new file mode 100644 index 0000000..350316e --- /dev/null +++ b/applicationFE/src/views/type/type.ts @@ -0,0 +1,14 @@ +export interface Oss { + ossIdx: number + ossTypeIdx: number + ossName: string + ossDesc: string + ossUsername: string + ossPassword: string + ossUrl: string +} +export interface OssType { + ossTypeIdx: number + ossTypeName: string + ossTypeDesc: string +} \ No newline at end of file diff --git a/applicationFE/tsconfig.app.json b/applicationFE/tsconfig.app.json new file mode 100644 index 0000000..e14c754 --- /dev/null +++ b/applicationFE/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/applicationFE/tsconfig.json b/applicationFE/tsconfig.json new file mode 100644 index 0000000..66b5e57 --- /dev/null +++ b/applicationFE/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/applicationFE/tsconfig.node.json b/applicationFE/tsconfig.node.json new file mode 100644 index 0000000..f094063 --- /dev/null +++ b/applicationFE/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/applicationFE/vite-env.d.ts b/applicationFE/vite-env.d.ts new file mode 100644 index 0000000..409cda1 --- /dev/null +++ b/applicationFE/vite-env.d.ts @@ -0,0 +1,10 @@ +/// + +interface ImportMetaEnv { + readonly VITE_API_URL: string + // 다른 환경 변수들에 대한 타입 정의... + } + + interface ImportMeta { + readonly env: ImportMetaEnv + } \ No newline at end of file diff --git a/applicationFE/vite.config.ts b/applicationFE/vite.config.ts new file mode 100644 index 0000000..dd2da0f --- /dev/null +++ b/applicationFE/vite.config.ts @@ -0,0 +1,26 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueDevTools from 'vite-plugin-vue-devtools' + +export default defineConfig({ + + plugins: [ + vue(), + vueDevTools(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + }, + // server: { + // proxy: { + // '/*': { + // target: import.meta.env.VITE_API_URL, + // changeOrigin: true, + // }, + // }, + // } +}) From f81483f9b5bc60d8f4c5d1b3d422756e65a7a6fd Mon Sep 17 00:00:00 2001 From: ysh Date: Wed, 28 Aug 2024 16:53:16 +0900 Subject: [PATCH 4/5] =?UTF-8?q?UI=20=EC=A0=95=EC=A0=81=20=EB=A6=AC?= =?UTF-8?q?=EC=86=8C=EC=8A=A4=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EC=9E=91?= =?UTF-8?q?=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/kr/co/mcmp/config/WebConfig.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/kr/co/mcmp/config/WebConfig.java diff --git a/src/main/java/kr/co/mcmp/config/WebConfig.java b/src/main/java/kr/co/mcmp/config/WebConfig.java new file mode 100644 index 0000000..ec50511 --- /dev/null +++ b/src/main/java/kr/co/mcmp/config/WebConfig.java @@ -0,0 +1,19 @@ +package kr.co.mcmp.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/web/{spring:[a-zA-Z\\-]+}") + .setViewName("forward:/index.html"); + registry.addViewController("/web/**/{spring:[a-zA-Z\\-]+}") + .setViewName("forward:/index.html"); + registry.addViewController("/web/{spring:[a-zA-Z\\-]+}/**{spring:?!(\\.js|\\.css)$}") + .setViewName("forward:/index.html"); + } +} From fe1f25e86b12ba976d87bf2f3180968d7a8bbd79 Mon Sep 17 00:00:00 2001 From: dmsej108 Date: Thu, 29 Aug 2024 10:29:36 +0900 Subject: [PATCH 5/5] Update software-catalog.html --- src/main/resources/static/tabler/software-catalog.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/static/tabler/software-catalog.html b/src/main/resources/static/tabler/software-catalog.html index d16b3e6..744e943 100644 --- a/src/main/resources/static/tabler/software-catalog.html +++ b/src/main/resources/static/tabler/software-catalog.html @@ -21,7 +21,7 @@ } - \ No newline at end of file +