Commit a2132183 authored by Gyeongho Park's avatar Gyeongho Park

[ADD] 독스 프로젝트 이관

parent 99ea364d
version: '3'
services:
proxy:
image: nginx:latest
container_name: proxy
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
restart: "unless-stopped"
docs-back:
build:
context: ./docs-back
image: vridge-api-ai
container_name: vridge-api-ai
expose:
- "5000"
links:
- vridge-eureka
- mongodb
restart: "unless-stopped"
docs-front:
build:
context: ./docs-front
image: docs-front
container_name: docs-front
ports:
- "3000:3000"
volumes:
- ./docs-front/app:/var/www/app
restart: "unless-stopped"
mongodb:
image: mongo:4.4.6
container_name: mongodb
restart: always
ports:
- 27017:27017
volumes:
- /var/lib/mongodb:/data/db
-./mongodb/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
command: [ "mongod", "--bind_ip", "0.0.0.0" ]
environment:
- TZ=Asia/Seoul
- MONGO_INITDB_ROOT_USERNAME=vridge-admin
- MONGO_INITDB_ROOT_PASSWORD=vazil523320!
- MONGO_INITDB_DATABASE=vridge-docs
- MONGO_INITDB_USERNAME=vridge-admin
- MONGO_INITDB_PASSWORD=vazil523320!
\ No newline at end of file
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
FROM openjdk:11
WORKDIR /app
ADD build/libs/vridge-docs-1.0.0.jar vridge-docs.jar
EXPOSE 5005
ENTRYPOINT ["java","-Dspring.profiles.active=deploy","-Djava.net.preferIPv4Stack=true", "-jar","./vridge-docs.jar"]
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.8'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}
group = 'com.vazil.vridge'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'javax.servlet:javax.servlet-api'
implementation('org.springframework.boot:spring-boot-starter-data-mongodb')
implementation "io.springfox:springfox-boot-starter:3.0.0"
implementation 'org.apache.commons:commons-lang3:3.9'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$(ls -ld "$app_path")
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$(cd "${APP_HOME:-./}" && pwd -P) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn() {
echo "$*"
} >&2
die() {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$(uname)" in #(
CYGWIN*) cygwin=true ;; #(
Darwin*) darwin=true ;; #(
MSYS* | MINGW*) msys=true ;; #(
NONSTOP*) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ]; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop"; then
case $MAX_FD in #(
max*)
MAX_FD=$(ulimit -H -n) ||
warn "Could not query maximum file descriptor limit"
;;
esac
case $MAX_FD in #(
'' | soft) : ;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
;;
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys"; then
APP_HOME=$(cygpath --path --mixed "$APP_HOME")
CLASSPATH=$(cygpath --path --mixed "$CLASSPATH")
JAVACMD=$(cygpath --unix "$JAVACMD")
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg; do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*)
t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ]
;; #(
*) false ;;
esac
then
arg=$(cygpath --path --ignore --mixed "$arg")
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1; then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
rootProject.name = 'docs'
package com.vazil.vridge.docs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class VridgeDocsApplication {
public static void main(String[] args) {
SpringApplication.run(VridgeDocsApplication.class, args);
}
}
package com.vazil.vridge.docs.controller;
import com.vazil.vridge.docs.model.Guide;
import com.vazil.vridge.docs.model.GuideContent;
import com.vazil.vridge.docs.service.GuideService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@AllArgsConstructor
@Log4j2
@Api("가이드 API V1")
public class GuideController {
GuideService guideService;
@ApiOperation(value="모든 가이드 목차 조회")
@GetMapping("/index")
public ResponseEntity<?> findIndex()throws Exception{
return new ResponseEntity<>(guideService.findGuideIndex(), HttpStatus.OK);
}
@ApiOperation(value="모든 가이드 목차 검색")
@GetMapping("/search")
public ResponseEntity<?> search(@RequestParam(value = "keyword", required = false) String keyword) throws Exception{
return new ResponseEntity<>(guideService.search(keyword), HttpStatus.OK);
}
@ApiOperation(value="가이드 타이틀 추가")
@PostMapping("/index")
public ResponseEntity<?> createGuideIndex(@RequestBody Guide guide) throws Exception{
return new ResponseEntity<>(guideService.createGuide(guide), HttpStatus.CREATED);
}
@PutMapping("/index")
public ResponseEntity<?> updateGuideIndex(@RequestBody Guide guide) throws Exception{
return new ResponseEntity<>(guideService.updateGuide(guide), HttpStatus.OK);
}
@PutMapping("/keyword")
public ResponseEntity<?> updateGuideKeyword(@RequestBody Guide guide) throws Exception{
return new ResponseEntity<>(guideService.updateGuideKeyword(guide), HttpStatus.OK);
}
@GetMapping
public ResponseEntity<?> getGuide(@RequestParam(value = "guideId") String guideId) throws Exception{
return new ResponseEntity<>(guideService.findGuideById(guideId), HttpStatus.OK);
}
@DeleteMapping
public ResponseEntity<?> deleteGuideIndex(@RequestParam(value = "guideId") String guideId, @RequestParam(value = "cascade", required = false) boolean cascade) throws Exception{
return new ResponseEntity<>(guideService.deleteGuide(guideId, cascade), HttpStatus.OK);
}
@PutMapping
public ResponseEntity<?> updateGuideContent(@RequestBody GuideContent guideContent) throws Exception{
return new ResponseEntity<>(guideService.updateGuideContent(guideContent), HttpStatus.OK);
}
}
package com.vazil.vridge.docs.exceptions;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@Log4j2
@ControllerAdvice
public class ControllerExceptionHandler {
//모든 예외를 핸들링하여 ErrorResponse 형식으로 반환한다.
@ExceptionHandler(Exception.class)
protected ResponseEntity<?> handleException(Exception e, ServerHttpRequest request) {
log.error("handleException :: ", e);
return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
package com.vazil.vridge.docs.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import nonapi.io.github.classgraph.json.Id;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document(value= "guide")
@Data
public class Guide implements Serializable {
private static final long serialVersionUID = 1928367242L;
@Id
private String id;
private String parentId;
private String title;
private Integer order;
private Integer like;
private Integer view;
private String contentKey;
private Set<String> keywordSet;
@CreatedDate
private LocalDateTime createDate;
@LastModifiedDate
private LocalDateTime updateDate;
private LocalDateTime deleteDate;
@Transient
List<Guide> children;
@Transient
private Guide prevContent;
@Transient
private Guide nextContent;
}
package com.vazil.vridge.docs.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;
import java.time.LocalDateTime;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Document(value= "guideContent")
public class GuideContent {
@Id
private String id;
private String guideId;
private String title;
private String content;
private Integer like;
private Integer view;
@Transient
private Guide prevContent;
@Transient
private Guide nextContent;
@CreatedDate
private LocalDateTime createDate;
@LastModifiedDate
private LocalDateTime updateDate;
private LocalDateTime deleteDate;
}
package com.vazil.vridge.docs.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.LastModifiedDate;
import java.time.LocalDateTime;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GuideSub {
@Id
private String id;
private String title;
private String contents;
private String router;
@CreatedDate
private LocalDateTime createDate;
@LastModifiedDate
private LocalDateTime updateDate;
private LocalDateTime deleteDate;
}
package com.vazil.vridge.docs.repository;
import com.vazil.vridge.docs.model.GuideContent;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface GuideContentRepository extends CrudRepository<GuideContent, String> {
Optional<GuideContent> findByGuideId(String guideId);
void deleteByGuideId(String guideId);
}
package com.vazil.vridge.docs.repository;
import com.vazil.vridge.docs.model.Guide;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface GuideRepository extends CrudRepository<Guide, String> {
List<Guide> findAllByParentIdOrderByOrderAsc(String parentId);
List<Guide> findAllByKeywordSetContaining(String keyword);
int countAllBy();
int countAllByParentId(String parentId);
}
package com.vazil.vridge.docs.service;
import com.vazil.vridge.docs.model.Guide;
import com.vazil.vridge.docs.model.GuideContent;
import com.vazil.vridge.docs.repository.GuideContentRepository;
import com.vazil.vridge.docs.repository.GuideRepository;
import com.vazil.vridge.docs.utils.TimeManager;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
@Service
@AllArgsConstructor
@Log4j2
public class GuideService {
GuideRepository guideRepository;
GuideContentRepository guideContentRepository;
public List<Guide> findGuideIndex() throws Exception{
List<Guide> guides = new ArrayList<>();
List<Guide> sortedGuideList = guideRepository.findAllByParentIdOrderByOrderAsc("");
for(Guide guide : sortedGuideList) {
guide.setChildren(getGuideTreeByParentId(guide.getId()));
guides.add(guide);
}
return guides;
}
@Transactional
public Guide findGuideById(String guideId) throws Exception{
Guide targetGuide = guideRepository.findById(guideId).orElseThrow(NoSuchElementException::new);
List<Guide> sortedGuideList = new ArrayList<>();
for(Guide guide : guideRepository.findAllByParentIdOrderByOrderAsc("")) {
sortedGuideList.add(guide);
sortedGuideList.addAll(getGuideListByParentId(guide.getId()));
}
for(int i = 0; i < sortedGuideList.size(); i++) {
if(sortedGuideList.get(i).getId().equals(guideId)) {
if(i > 0) {
targetGuide.setPrevContent(sortedGuideList.get(i-1));
}
if(i < sortedGuideList.size() - 1) {
targetGuide.setNextContent(sortedGuideList.get(i+1));
}
break;
}
}
return targetGuide;
}
public List<Guide> search(String keyword) throws Exception{
return guideRepository.findAllByKeywordSetContaining(keyword);
}
@Transactional
public Guide createGuide(Guide guide) throws Exception{
guide.setCreateDate(TimeManager.now());
guide.setUpdateDate(TimeManager.now());
guide.setOrder(guide.getOrder() == null ? getLastOrder(guide.getParentId()) : 0);
guide.setParentId(StringUtils.isEmpty(guide.getParentId()) ? "" : guide.getParentId());
guide.setLike(0);
guide.setView(0);
return guideRepository.save(guide);
}
@Transactional
public Guide updateGuide(Guide guide) throws Exception{
Guide savedGuide = guideRepository.findById(guide.getId()).orElseThrow(NoSuchElementException::new);
savedGuide.setParentId(guide.getParentId());
savedGuide.setOrder(guide.getOrder());
savedGuide.setUpdateDate(TimeManager.now());
savedGuide.setContentKey(guide.getContentKey());
return guideRepository.save(savedGuide);
}
@Transactional
public Guide updateGuideKeyword(Guide guide) throws Exception{
Guide savedGuide = guideRepository.findById(guide.getId()).orElseThrow(NoSuchElementException::new);
savedGuide.setKeywordSet(guide.getKeywordSet());
return guideRepository.save(savedGuide);
}
@Transactional
public Guide deleteGuide(String guideId, boolean cascade) throws Exception{
Guide guide = guideRepository.findById(guideId).orElseThrow(NoSuchElementException::new);
String targetId = guide.getId();
String parentId = guide.getParentId();
List<Guide> children = getGuideListByParentId(targetId);
if(cascade) {
for(Guide g : children) {
guideRepository.delete(g);
//guideContentRepository.deleteByGuideId(g.getId());
}
} else {
for(Guide g : guideRepository.findAllByParentIdOrderByOrderAsc(targetId)) {
g.setParentId(parentId);
g.setOrder(getLastOrder(parentId));
guideRepository.save(g);
}
}
guideRepository.delete(guide);
//guideContentRepository.deleteByGuideId(guide.getId());
return guide;
}
///////////////////////////////////////////////////////
// Guide Content CRUD
@Transactional
public GuideContent findContentById(String guideId) throws Exception{
GuideContent targetContent = guideContentRepository.findByGuideId(guideId).orElseThrow(NoSuchElementException::new);
List<Guide> sortedGuideList = new ArrayList<>();
for(Guide guide : guideRepository.findAllByParentIdOrderByOrderAsc("")) {
sortedGuideList.add(guide);
sortedGuideList.addAll(getGuideListByParentId(guide.getId()));
}
for(int i = 0; i < sortedGuideList.size(); i++) {
if(sortedGuideList.get(i).getId().equals(guideId)) {
if(i > 0) {
targetContent.setPrevContent(sortedGuideList.get(i-1));
}
if(i < sortedGuideList.size() - 1) {
targetContent.setNextContent(sortedGuideList.get(i+1));
}
}
}
return targetContent;
}
@Transactional
public GuideContent updateGuideContent(GuideContent guideContent) throws Exception{
GuideContent savedGuideContent = guideContentRepository.findById(guideContent.getId()).orElseThrow(NoSuchElementException::new);
savedGuideContent.setContent(guideContent.getContent());
savedGuideContent.setUpdateDate(TimeManager.now());
return guideContentRepository.save(savedGuideContent);
}
/////////////////////////////////////////////////
// Common
// 트리 구조로 자식 guide를 가져옴
private List<Guide> getGuideTreeByParentId(String parentId) {
List<Guide> children = new ArrayList<>();
for(Guide childGuide : guideRepository.findAllByParentIdOrderByOrderAsc(parentId)) {
childGuide.setChildren(guideRepository.findAllByParentIdOrderByOrderAsc(childGuide.getId()));
children.add(childGuide);
}
return children;
}
//트리 구조의 guide를 1차원 리스트로 가져옴
private List<Guide> getGuideListByParentId(String parentId) {
List<Guide> children = new ArrayList<>();
for(Guide childGuide : guideRepository.findAllByParentIdOrderByOrderAsc(parentId)) {
children.add(childGuide);
children.addAll(guideRepository.findAllByParentIdOrderByOrderAsc(childGuide.getId()));
}
return children;
}
//현재 뎁스의 마지막 순번을 가져옴
private Integer getLastOrder(String parentId) {
return guideRepository.countAllByParentId(parentId);
}
}
package com.vazil.vridge.docs.swagger;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
@Configuration
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Vridge 문서(Docs)")
.description("Vridge Docs 서비스 관련 API 문서입니다.")
.contact(new springfox.documentation.service.Contact("Vazilcompany", "http://www.vazilcompany.com", "programming@vazilcompany.com"))
.license("Vridge License Version 1.0")
.licenseUrl("https://www.vridgeai.com/docs")
.version("1.0.0")
.build();
}
}
package com.vazil.vridge.docs.utils;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;
import java.nio.ByteBuffer;
import java.util.UUID;
/**
* @author 경호
* 시간 관리 클래스
*/
@Component
@Log4j2
public class IdUtils {
public static String generate() {
return UUID.randomUUID().toString().replace("-","");
}
public static String generateShort() {
return Long.toString(ByteBuffer.wrap(UUID.randomUUID().toString().getBytes()).getLong(), Character.MAX_RADIX).replace("-","");
}
public static String generateWithPrefix(String prefix) {
return prefix + "-" + generate();
}
public static String generateShortWithPrefix(String prefix) {
return prefix + "-" + generateShort();
}
}
package com.vazil.vridge.docs.utils;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.ZoneId;
/**
* @author 경호
* 시간 관리 클래스
*/
@Component
@Log4j2
public class TimeManager {
public static LocalDateTime now() {
return LocalDateTime.now(ZoneId.of("Asia/Seoul"));
}
public static boolean isExpired(LocalDateTime targetDateTime) {
LocalDateTime now = now();
return now.isAfter(targetDateTime);
}
public static LocalDateTime nowBeforeDay(int day) {
LocalDateTime now = now();
now = now.minusDays(day);
return now;
}
}
server:
port: 5000
spring:
application:
name: "vridge-docs"
data:
mongodb:
host: mongodb
port: 27017
database: vridge
username: vridge-admin
password: vazil523320!
mvc:
pathmatch:
matching-strategy: ant_path_matcher
\ No newline at end of file
,--. ,--. ,--. ,--. ,----. ,--. ,--.
\ `.' / ,--.--. `--' ,-| | ,---. ,---. ' .-./ ,--.,--. `--' ,-| | ,---.
\ / | .--' ,--. ' .-. | | .-. | | .-. : | | .---. | || | ,--. ' .-. | | .-. :
\ / | | | | \ `-' | ' '-' ' \ --. ' '--' | ' '' ' | | \ `-' | \ --.
`-' `--' `--' `---' .`- / `----' `------' `----' `--' `---' `----'
`---'
${application.title} ${application.version}
Powered by Spring Boot ${spring-boot.version}
package com.vazil.vridge.docs;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class VridgeDocsApplicationTests {
@Test
void contextLoads() {
}
}
.node_modules/
.dist/
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = false
[*.md]
trim_trailing_whitespace = false
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
/logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# Nuxt generate
dist
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# IDE / Editor
.idea
# Service worker
sw.*
# macOS
.DS_Store
# Vim swap files
*.swp
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
\ No newline at end of file
FROM node:16 as builder
WORKDIR /app
COPY . .
RUN yarn install \
--prefer-offline \
--frozen-lockfile \
--non-interactive \
--production=false
RUN yarn build
RUN rm -rf node_modules && \
NODE_ENV=production yarn install \
--prefer-offline \
--pure-lockfile \
--non-interactive \
--production=true
FROM node:16
WORKDIR /app
COPY --from=builder /app .
ENV HOST 0.0.0.0
EXPOSE 3000
CMD [ "yarn", "start" ]
# FistApp
클라우드 환경에서 인공지능 모델을 학습하고 배포 및 버전 관리 서비스
```bash
# install dependencies
$ npm install
# serve with hot reload at localhost:3000
$ npm run dev
# build for production and launch server
$ npm run build
$ npm run start
# generate static project
$ npm run generate
```
For detailed explanation on how things work, check out [Nuxt.js docs](https://nuxtjs.org).
import express from 'express'
// Create express router
const router = express.Router()
const app = express()
router.use((req, res, next) => {
Object.setPrototypeOf(req, app.request);
Object.setPrototypeOf(res, app.response);
req.res = res;
res.req = req;
next();
});
// Export the server middleware
export default {
path: '/apis',
handler: router
};
\ No newline at end of file
This diff is collapsed.
// Ref: https://github.com/nuxt-community/vuetify-module#customvariables
//
// The variables you want to modify
// $font-size-root: 20px;
$menu-content-elevation: 1;
$list-item-dense-title-font-size: 1rem;
$list-dense-min-height: 42px;
\ No newline at end of file
# COMPONENTS
**This directory is not required, you can delete it if you don't want to use it.**
The components directory contains your Vue.js Components.
_Nuxt.js doesn't supercharge these components._
<template>
<v-dialog
v-model="dialog"
:persistent="persistent"
scrollable
:max-width="maxWidth"
:max-height="maxHeight"
:width="width"
:fullscreen="fullDialog"
@keydown.enter="enterKeyEvent"
overlay-opacity="0.2"
transition="slide-y-reverse-transition"
content-class="vridge-dialog-container"
>
<template v-slot:activator="{on, attrs}">
<slot name="button" v-on="on" v-bind="{on, attrs}"></slot>
</template>
<v-card class="vridge-dialog" :tile="tile" elevation="0">
<v-card-title class="vridge-dialog-title">
<slot name="title" v-if="$slots.title">
</slot>
<v-row v-else no-gutters align="center">
<span class="font-weight-bold">
{{title}}
</span>
<v-spacer/>
<v-avatar size="28" class="vridge-dialog-close" v-if="closeButton">
<v-icon class="font-weight-bold" @click="clickNo" >mdi-close</v-icon>
</v-avatar>
</v-row>
</v-card-title>
<v-card-text class="vridge-content-container" color="white" flat :style="'height:' + height +'px !important; overflow-y:' + overflow + ';background:' + background" style="min-height:140px;">
<v-container fluid style="width:100%; height:100%;">
<slot name="content">
</slot>
</v-container>
</v-card-text>
<v-card-actions class="vridge_actions" v-if="!$slots.actionButton" >
<v-spacer></v-spacer>
<v-btn
:ripple="false"
elevation="0"
@click="clickNo"
:disabled="disabledNo"
:loading="loading"
>
<span>{{$t('close')}}</span>
</v-btn>
<v-btn
color="primary"
@click="clickYes"
elevation="0"
:ripple="false"
v-if="clickYesBtn"
:loading="loading"
:disabled="disabledYes"
>
<span>{{clickYesBtn}}</span>
</v-btn>
</v-card-actions>
<v-card-actions v-else class="vridge_actions">
<v-spacer/>
<slot name="actionButton"> </slot>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
name: 'vridgeDialog',
props: {
persistent:{
type:Boolean,
default:false
},
borderBottom:{
type:Number
},
borderRadius:{
type:Number
},
color:{
type:String
},
colorHeader:{
type:String
},
fullscreen:{
type:Boolean,
default:false
},
disabled:{
type: Boolean,
default: false
},
icon:{
type: String,
default: ''
},
title:{
type: String,
default: '새창'
},
width:{
type: Number,
default: 500
},
height:{
type: Number,
default: 120
},
maxWidth:{
type: Number,
default: 1080
},
maxHeight:{
type: Number,
default: 1080
},
padding:{
type:String
},
overflow:{
type:String,
default:'auto'
},
background:{
type:String
},
backgroundHeader:{
type:String
},
clickYesBtn:{
type:String,
default:""
},
mobileFull:{
type:Boolean,
default:false
},
enterKeyActive:{
type:Boolean,
default:false
},
tile:{
type:Boolean,
default:false
},
closeButton:{
type:Boolean,
default:false
},
loading: {
type:Boolean,
default:false
},
disabledYes: {
type:Boolean,
default:false
},
disabledNo: {
type:Boolean,
default:false
},
autoClose: {
type:Boolean,
default:true
}
},
data: () => ({
dialog: false,
format:'YYYY-MM-DD',
isFullDialog:false
}),
watch:{
dialog() {
this.$emit('change')
if(this.dialog) {
this.init()
if(this.mobileFull){
this.isFullDialog = window.innerWidth <= 768
}
} else {
this.$emit('click-no')
this.$emit('close')
}
},
},
computed: {
fullDialog(){
return this.isFullDialog || this.fullscreen
}
},
methods:{
init(){
},
clickYes(){
if(this.autoClose) this.dialog = false
this.$emit('click-yes')
},
enterKeyEvent(){
if(this.enterKeyActive){
this.$emit('click-yes')
}
},
select (index) {
this.selectedIndex = index
},
clickNo(){
this.dialog = false
this.$emit('click-no')
},
resizeEventHandler(e) {
if(this.dialog && this.mobileFull) {
if(e.currentTarget.outerWidth <= 768) {
this.isFullDialog = true
} else {
this.isFullDialog = false
}
} else {
this.isFullDialog = false
}
},
},
mounted(){
window.addEventListener("resize", this.resizeEventHandler);
},
destroyed() {
window.removeEventListener("resize", this.resizeEventHandler);
},
}
</script>
<style lang="scss">
.vridge-dialog-container{
.theme--light &{
box-shadow: rgba(0, 0, 0, 0.1) 0px 20px 30px !important;
}
}
.theme--dark{
.vridge-dialog{
border:1px solid #2a2a2a !important;
}
}
.theme--light{
.vridge-dialog{
border:1px solid #eee !important;
}
}
.vridge-dialog{
overflow-x:hidden;
padding:24px;
> .v-card__title{
font-size:20px !important;
padding:12px !important;
//margin-bottom:12px !important;
}
.vridge-content-container{
padding:0px !important;
font-size: 14px;
transition: height 0.5s ease-in-out;
}
.vridge_actions{
padding: 12px !important;
}
}
.create-slot-cover{
padding:0;
margin:0;
.search-menu-cover{
display:flex;
background-color:transparent;
border:1px solid #e0e0e0;
border-radius: 5px;
}
.search-menu-check-cover{
.v-input--selection-controls {
padding: 0;
margin: 0;
}
.v-messages {
display:none !important;
}
}
}
.v-dialog--persistent{
.vdp-datepicker, .vdpWithInput{
height:38px;
width:100%;
input{
height: 38px;
padding-left:12px;
width:100%;
font-size:15px;
}
.vdp-datepicker__calendar{
bottom: 40px;
}
}
}
.vdpClearInput{
display:none !important;
}
.dateInput >>> input{
padding:8px 0px;
font-size: 13px;
font-weight: 500;
opacity: .7;
}
.dateInput >>> button::before{
display:none !important;
}
.calendarCustom{
font-size:20px;
margin-left:-25px;
position:relative;
color:#4159b2;
cursor:pointer;
display:flex;
align-items:center;
}
/* .v-dialog{
overflow-y: initial;
}*/
.search-menu-cover{
.vdpHeader{
background:rgba(0,0,0,0.05) !important;
}
}
.vridge-dialog-close{
transition: all 0.2s ease-in-out;
opacity: 0.7;
&:hover{
transform:scale(1.1) !important;
opacity: 1.0;
.theme--dark{
background-color:#1b1c20 !important;
}
.theme--light{
background-color:#ccc !important;
}
font-weight: bold !important;
}
}
</style>
\ No newline at end of file
# LAYOUTS
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains your Application Layouts.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts).
This diff is collapsed.
<template>
<div>
<v-container class="error-container">
<v-row no-gutters justify="center" align="center" class="py-16">
<v-col justify="center" align="center">
<v-row no-gutters class="error_img_box" >
<img src="/error_img.png" />
<v-col cols="12" v-if="error.statusCode === 404" v-html="pageNotFound" justify="center" align="center" class="mb-16 error_text"></v-col>
<v-col cols="12" v-else justify="center" v-html="otherError" style="text-align:center;" align="center" class="mb-16 error_text">
</v-col>
<v-col cols="12" justify="center" align="start">
<span class="error_number">{{error.statusCode}}</span>
</v-col>
</v-row>
<v-row no-gutters justify="center" align="center">
<NuxtLink to="/" class="home-btn" style="margin-right: 16px; margin-top: 50px:">
홈으로
</NuxtLink>
</v-row>
</v-col>
</v-row>
</v-container>
</div>
</template>
<script>
export default {
props: {
error: {
type: Object,
default: null
}
},
data () {
return {
pageNotFound: "<h3>존재하지 않거나, 사용할 수 없는 페이지 입니다.</h3>"
}
},
head () {
const title = this.error.statusCode === 404 ? 'Not Found': 'ERROR'
return {
title
}
}
}
</script>
<style lang="scss">
.error-container{
margin-top: 64px;
}
@font-face {
font-family: 'EF_MACHO';
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2206-01@1.0/EF_MACHO.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}
.home-btn {
height: 42px;
line-height: 42px;
width: 120px;
text-align: center;
border-radius: 5px;
color:#fff !important;
// background-color: #4f4f4f;
background: linear-gradient(70deg, #d16ac2, 30%, #6347e2);
background: -webkit-linear-gradient(70deg, #d16ac2, 30%, #6347e2);
}
.cont_center_error {
position: relative;
}
.cont_box_error {
min-width: 100%;
}
.cont_error {
position: absolute;
top: 38%;
left: 50%;
transform: translate(-50%, -50%);
padding-bottom: 0 !important;
}
.error_img_box {
position: relative;
img {
margin:auto;
height: 400px;
}
}
.error_text {
text-align: center;
margin-bottom: 65px !important;
h3 {
margin-top: 20px;
font-size: 1.4em;
}
}
.error_number {
color: #fff;
letter-spacing: 10px;
font-size: 4.6em;
line-height: 1.1;
text-shadow: 0 2px 5px #fff;
position: absolute;
top: calc(60% - 25px);
left: calc(50% - 193px);
font-family: 'EF_MACHO' !important;
animation: error_number 2.2s linear infinite;
}
@keyframes error_number {
0% {
opacity: 1;
}
10% {
opacity: .5;
}
20% {
opacity: 1;
}
100% {
opacity: 1;
}
}
@media screen and (max-width: 1024px) {
.cont_center_error {
.cont_box_error {
min-height: 680px;
}
.cont_error {
margin-top: 0px;
}
img {
height: 250px;
object-fit: cover;
margin-top: 0;
}
.error_number {
font-size: 2.3em !important;
top: 50%;
left: calc(50% - 119px);
}
.error_text {
h3 {
font-size: 1.2em;
}
}
}//.cont_center_error end
}//@media screen and (max-width: 1024px) end
@media screen and (max-width: 820px) {
.cont_center_error {
.cont_box_error {
min-height: 680px;
}
.cont_error {
margin-top: 0px;
}
img {
height: 350px;
}
.error_number {
font-size: 3.6em !important;
top: calc(55% - 6px);
left: calc(50% - 170px);
}
.error_text {
h3 {
font-size: 1.2em;
}
}
}//.cont_center_error end
}
@media screen and (max-width: 466px) {
.cont_center_error {
.cont_error {
top: 45%;
}
img {
height: 220px;
}
.error_number {
font-size: 2em !important;
top: 161px;
left: calc(50% - 105px);
}
.error_text {
h3 {
font-size: 1em;
}
}
}//.cont_center_error end
}//@media screen and (max-width: 466px) end
@media screen and (max-width: 360px) {
.cont_center_error {
.cont_error {
top: 41%;
}
img {
height: 170px;
}
.error_number {
font-size: 1.4em !important;
top: 124px;
left: calc(50% - 82px);
}
.error_text {
text-align: center;
padding: 0 15px;
h3 {
font-size: 1em;
}
}
}//.cont_center_error end
}//@media screen and (max-width: 360px) end
</style>
import webpack from 'webpack'
export default {
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
script: [
{ src: 'https://static.nid.naver.com/js/naveridlogin_js_sdk_2.0.0.js' },
{ src: 'https://docs.opencv.org/3.4/opencv.js' },
],
titleTemplate: 'Vridge AI - %s',
title: 'Vridge AI',
htmlAttrs: {
lang: 'ko'
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'og:title', property: 'og:title', content: 'Vridge AI' },
{ hid: 'og:site_name', property: 'og:site_name', content: 'Vridge AI' },
{ hid: 'description', name: 'description', content: '클라우드 환경에서 인공지능 모델을 학습하고 배포 및 버전 관리 서비스' },
{ hid: 'og:image', property: 'og:image', content: 'https://d2q9yzkd471o7j.cloudfront.net/logo/head_logo.png?w=300&h=300' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{ rel: 'preconnect', href: 'https://fonts.gstatic.com' },
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100;300;400;500;700;900&display=swap' },
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/earlyaccess/nanumgothic.css'},
{ rel: 'stylesheet', href: 'https://cdn.jsdelivr.net/npm/@mdi/font@6.5.95/css/materialdesignicons.min.css'},
]
},
// loading: '~/components/LoadingBar.vue',
loading:false,
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
"~/assets/scss/common.scss",
"~/assets/scss/transition.scss",
],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
'~/plugins/global.js'
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
// https://go.nuxtjs.dev/vuetify
'@nuxtjs/vuetify',
'@nuxtjs/svg'
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
'@nuxtjs/auth',
'@nuxtjs/axios',
'@nuxtjs/pwa',
'nuxt-route-meta',
['cookie-universal-nuxt', { alias: 'cookiz' }],
"vue2-editor/nuxt",
'nuxt-healthcheck',
'nuxt-i18n',
],
// Vuetify module configuration: https://go.nuxtjs.dev/config-vuetify
vuetify: {
customVariables: ['~/assets/variables.scss'],
treeShake: true,
defaultAssets: {
font: {
family: 'Noto Sans KR'
}
}
},
animejs: true,
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
vendor: ['axios'],
hotMiddleware:{
client:{
quiet:true
}
},
html: {
minify: {
collapseWhitespace: true, // as @dario30186 mentioned
removeComments: true, // 👈 add this line
},
},
plugins: [
new webpack.ProvidePlugin({
// global modules
$: 'jquery',
jQuery: 'jquery',
IScroll: 'iscroll',
// _: 'lodash'
})
],
extend (config, ctx) {
config.module.rules.push({
enforce: 'pre',
test: /\.txt$/,
loader: 'raw-loader',
exclude: /(node_modules)/
});
}
},
axios:{
baseURL: 'http://localhost:5000'
},
healthCheck: {
contentType: 'application/json',
healthy: () => {
return JSON.stringify({result: 'ok'})
}
},
generate: {
minify: {
collapseWhitespace: false
}
}
}
\ No newline at end of file
{
"name": "vridge-docs",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate"
},
"dependencies": {
"@nuxtjs/axios": "^5.13.6",
"@nuxtjs/pwa": "^3.3.5",
"@nuxtjs/vuetify": "^1.11.3",
"atob": "^2.1.2",
"axios": "^0.21.1",
"body-parser": "^1.19.0",
"cookie-universal-nuxt": "^2.1.5",
"core-js": "^3.9.1",
"express": "^4.17.1",
"express-session": "^1.17.2",
"js-cookie": "^2.2.1",
"nuxt": "^2.15.3",
"nuxt-healthcheck": "^1.0.1",
"nuxt-i18n": "^6.28.1",
"nuxt-route-meta": "^2.2.1",
"nuxt-vuex-localstorage": "^1.3.0",
"sass-loader": "^10.2.0",
"vue-no-ssr": "^1.1.1",
"vue-swatches": "^2.1.1",
"vue-upload-component": "^2.8.22",
"vue2-editor": "^2.10.3",
"vuex-persistedstate": "^4.0.0"
},
"devDependencies": {
"@nuxtjs/svg": "^0.2.0",
"raw-loader": "^4.0.2"
}
}
# PAGES
This directory contains your Application Views and Routes.
The framework reads all the `*.vue` files inside this directory and creates the router of your application.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing).
This diff is collapsed.
<template>
<guide-board-editor
:board="board"
>
</guide-board-editor>
</template>
<script>
export default {
layout:'guide',
meta:{
title:'가이드 편집',
},
components: {
},
data:()=>({
board:null
}),
mounted(){
this.getBoard()
},
methods:{
getBoard(){
this.board.title = this.$route.params.guideSub
this.board.content = this.$store.state.guidSubList.contents
},
}
};
</script>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment