Compare commits
3 Commits
7b47a02d9a
...
feature/gi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5d98f06e1 | ||
|
|
c962cb6886 | ||
|
|
a2e27ca5b4 |
@@ -9,20 +9,34 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Java 8
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: "8"
|
||||||
|
|
||||||
- name: Maven Build WAR
|
- name: Maven Build WAR
|
||||||
run: mvn -B clean package -DskipTests
|
run: mvn -B clean package -DskipTests
|
||||||
|
|
||||||
- name: Login Harbor
|
- name: Docker login to Harbor
|
||||||
run: |
|
run: |
|
||||||
echo "${{ secrets.HARBOR_PASSWORD }}" | docker login harbor.sayinfo.co.kr -u ${{ secrets.HARBOR_USERNAME }} --password-stdin
|
echo "${{ secrets.HARBOR_PASSWORD }}" | docker login harbor.sayinfo.co.kr \
|
||||||
|
-u ${{ secrets.HARBOR_USERNAME }} --password-stdin
|
||||||
|
|
||||||
- name: Build Docker image
|
- name: Build Docker image
|
||||||
run: |
|
run: |
|
||||||
docker build -t sayit-helpdesk:latest .
|
docker build -t sayit-helpdesk:latest .
|
||||||
|
|
||||||
- name: Push to Harbor
|
- name: Tag image for Harbor
|
||||||
run: |
|
run: |
|
||||||
docker tag sayit-helpdesk:latest harbor.sayinfo.co.kr/helpdesk/helpdesk-service:latest
|
docker tag sayit-helpdesk:latest harbor.sayinfo.co.kr/gitea_action_runner_test/helpdesk-service:latest
|
||||||
docker push harbor.sayinfo.co.kr/helpdesk/helpdesk-service:latest
|
|
||||||
|
- name: Push image to Harbor
|
||||||
|
run: |
|
||||||
|
docker push harbor.sayinfo.co.kr/gitea_action_runner_test/helpdesk-service:latest
|
||||||
|
|
||||||
|
- name: Done
|
||||||
|
run: echo "Main branch build + Harbor push completed."
|
||||||
|
|||||||
@@ -10,7 +10,22 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Maven Build (skip tests)
|
- name: Set up Java 8
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: "8"
|
||||||
|
|
||||||
|
- name: Cache Maven repo
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.m2
|
||||||
|
key: m2-${{ runner.os }}-${{ hashFiles('**/pom.xml') }}
|
||||||
|
restore-keys: |
|
||||||
|
m2-${{ runner.os }}-
|
||||||
|
|
||||||
|
- name: Maven Build
|
||||||
run: mvn -B clean package -DskipTests
|
run: mvn -B clean package -DskipTests
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
<settings>
|
|
||||||
<mirrors>
|
|
||||||
<mirror>
|
|
||||||
<id>sayinfo-nexus</id>
|
|
||||||
<name>Sayinfo Nexus</name>
|
|
||||||
<url>https://nexus.sayinfo.co.kr/repository/maven-public/</url>
|
|
||||||
<mirrorOf>*</mirrorOf>
|
|
||||||
</mirror>
|
|
||||||
</mirrors>
|
|
||||||
</settings>
|
|
||||||
45
Dockerfile
45
Dockerfile
@@ -1,45 +0,0 @@
|
|||||||
# 1단계: OTEL Java 에이전트 다운로드
|
|
||||||
FROM alpine:3.20 AS otel
|
|
||||||
ARG OTEL_VERSION=2.21.0
|
|
||||||
|
|
||||||
RUN apk add --no-cache curl && \
|
|
||||||
curl -fL \
|
|
||||||
https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v${OTEL_VERSION}/opentelemetry-javaagent.jar \
|
|
||||||
-o /opentelemetry-javaagent.jar
|
|
||||||
|
|
||||||
# 2단계: Tomcat 이미지 (Java 8 기준)
|
|
||||||
FROM tomcat:9.0-jdk8-temurin
|
|
||||||
|
|
||||||
ENV TZ=Asia/Seoul \
|
|
||||||
OTEL_SERVICE_NAME=helpdesk_service \
|
|
||||||
OTEL_EXPORTER_OTLP_ENDPOINT=http://192.168.100.203:4317 \
|
|
||||||
OTEL_EXPORTER_OTLP_PROTOCOL=grpc \
|
|
||||||
OTEL_RESOURCE_ATTRIBUTES="deployment.environment=prod" \
|
|
||||||
JAVA_TOOL_OPTIONS="\
|
|
||||||
-Xms1g \
|
|
||||||
-Xmx1g \
|
|
||||||
-XX:+UseG1GC \
|
|
||||||
-XX:MaxGCPauseMillis=200 \
|
|
||||||
-XX:+UnlockExperimentalVMOptions \
|
|
||||||
-XX:+UseStringDeduplication \
|
|
||||||
-XX:+HeapDumpOnOutOfMemoryError \
|
|
||||||
-XX:HeapDumpPath=/tmp \
|
|
||||||
-XX:+DisableExplicitGC \
|
|
||||||
-javaagent:/opt/opentelemetry-javaagent.jar"
|
|
||||||
|
|
||||||
# 타임존 설정
|
|
||||||
RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
|
|
||||||
|
|
||||||
# OTEL 에이전트 복사
|
|
||||||
COPY --from=otel /opentelemetry-javaagent.jar /opt/opentelemetry-javaagent.jar
|
|
||||||
RUN chown 1000:1000 /opt/opentelemetry-javaagent.jar
|
|
||||||
|
|
||||||
# 기본 웹앱 정리
|
|
||||||
RUN rm -rf /usr/local/tomcat/webapps/*
|
|
||||||
|
|
||||||
# Maven 빌드된 WAR 복사
|
|
||||||
COPY target/sayit-helpdesk.war /usr/local/tomcat/webapps/ROOT.war
|
|
||||||
RUN chown -R 1000:1000 /usr/local/tomcat/
|
|
||||||
|
|
||||||
EXPOSE 8080
|
|
||||||
CMD ["catalina.sh","run"]
|
|
||||||
132
Jenkinsfile
vendored
132
Jenkinsfile
vendored
@@ -1,132 +0,0 @@
|
|||||||
// Jenkinsfile — Kaniko build + K8s deploy (빌드번호 태그 사용)
|
|
||||||
def L = 'kaniko-and-deploy'
|
|
||||||
def REG = 'harbor.sayinfo.co.kr'
|
|
||||||
def IMAGE = 'sayit-helpdesk/helpdesk-service' // Harbor 프로젝트/레포 이름
|
|
||||||
def APP_NS = 'sayit-helpdesk' // 실제 K8s 네임스페이스
|
|
||||||
def DEPLOY = 'sayit-helpdesk-service' // 실제 Deployment 이름
|
|
||||||
def IMAGE_TAG = "${env.BUILD_NUMBER}"
|
|
||||||
|
|
||||||
podTemplate(
|
|
||||||
label: L,
|
|
||||||
yaml: """
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
spec:
|
|
||||||
serviceAccountName: default
|
|
||||||
securityContext:
|
|
||||||
fsGroup: 1001
|
|
||||||
fsGroupChangePolicy: OnRootMismatch
|
|
||||||
hostAliases:
|
|
||||||
- ip: "192.168.0.210"
|
|
||||||
hostnames:
|
|
||||||
- "harbor.sayinfo.co.kr"
|
|
||||||
- "nexus.sayinfo.co.kr"
|
|
||||||
containers:
|
|
||||||
- name: maven
|
|
||||||
image: maven:3.9.9-eclipse-temurin-8
|
|
||||||
command: ["/bin/sh","-lc"]
|
|
||||||
args: ["sleep 99d"]
|
|
||||||
tty: true
|
|
||||||
volumeMounts:
|
|
||||||
- name: workspace-volume
|
|
||||||
mountPath: /home/jenkins/agent
|
|
||||||
- name: maven-cache
|
|
||||||
mountPath: /root/.m2
|
|
||||||
- name: kaniko
|
|
||||||
image: gcr.io/kaniko-project/executor:debug
|
|
||||||
command: ["/busybox/sh","-c"]
|
|
||||||
args: ["sleep 99d"]
|
|
||||||
tty: true
|
|
||||||
volumeMounts:
|
|
||||||
- name: kaniko-auth
|
|
||||||
mountPath: /kaniko/.docker
|
|
||||||
- name: workspace-volume
|
|
||||||
mountPath: /home/jenkins/agent
|
|
||||||
- name: kubectl
|
|
||||||
image: bitnamilegacy/kubectl:latest
|
|
||||||
command: ["/bin/sh","-lc"]
|
|
||||||
args: ["sleep 99d"]
|
|
||||||
securityContext:
|
|
||||||
runAsUser: 0
|
|
||||||
runAsGroup: 0
|
|
||||||
tty: true
|
|
||||||
volumeMounts:
|
|
||||||
- name: workspace-volume
|
|
||||||
mountPath: /home/jenkins/agent
|
|
||||||
volumes:
|
|
||||||
- name: kaniko-auth
|
|
||||||
projected:
|
|
||||||
sources:
|
|
||||||
- secret:
|
|
||||||
name: regcred-sayit-helpdesk
|
|
||||||
items:
|
|
||||||
- key: .dockerconfigjson
|
|
||||||
path: config.json
|
|
||||||
- name: workspace-volume
|
|
||||||
emptyDir: {}
|
|
||||||
- name: maven-cache
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: maven-repo-pvc
|
|
||||||
"""
|
|
||||||
) {
|
|
||||||
node(L) {
|
|
||||||
timestamps {
|
|
||||||
stage('Checkout') {
|
|
||||||
checkout scm
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Maven Build') {
|
|
||||||
container('maven') {
|
|
||||||
sh '''
|
|
||||||
set -eux
|
|
||||||
cd "${WORKSPACE}"
|
|
||||||
mvn -B -q -e -T 1C -s .mvn/settings.xml clean package -DskipTests
|
|
||||||
'''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Preflight (Kaniko)') {
|
|
||||||
container('kaniko') {
|
|
||||||
sh '''
|
|
||||||
set -eux
|
|
||||||
cd "${WORKSPACE}"
|
|
||||||
test -f /kaniko/.docker/config.json
|
|
||||||
nslookup harbor.sayinfo.co.kr || true
|
|
||||||
grep harbor /etc/hosts || true
|
|
||||||
'''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Build & Push (Kaniko)') {
|
|
||||||
container('kaniko') {
|
|
||||||
sh """
|
|
||||||
set -eux
|
|
||||||
cd "\${WORKSPACE}"
|
|
||||||
/kaniko/executor \\
|
|
||||||
--context=. \\
|
|
||||||
--dockerfile=Dockerfile \\
|
|
||||||
--destination=${REG}/${IMAGE}:${IMAGE_TAG} \\
|
|
||||||
--snapshot-mode=redo \\
|
|
||||||
--skip-tls-verify \\
|
|
||||||
--cache=true \\
|
|
||||||
--cache-repo=${REG}/sayit-helpdesk/build-cache
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Deploy to Kubernetes') {
|
|
||||||
container('kubectl') {
|
|
||||||
sh """
|
|
||||||
set -eux
|
|
||||||
kubectl -n ${APP_NS} set image deploy/${DEPLOY} ${DEPLOY}=${REG}/${IMAGE}:${IMAGE_TAG}
|
|
||||||
kubectl -n ${APP_NS} rollout status deploy/${DEPLOY} --timeout=300s
|
|
||||||
|
|
||||||
kubectl -n ${APP_NS} get deploy ${DEPLOY} -o wide
|
|
||||||
kubectl -n ${APP_NS} get pods -l app=${DEPLOY} -o wide
|
|
||||||
kubectl -n ${APP_NS} get pod -l app=${DEPLOY} -o jsonpath='{.items[*].spec.containers[*].image}'; echo
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -45,9 +45,7 @@ public class AuthenticInterceptor extends HandlerInterceptorAdapter {
|
|||||||
uri.equals("/") ||
|
uri.equals("/") ||
|
||||||
uri.equals("/actionLoginSys.do") ||
|
uri.equals("/actionLoginSys.do") ||
|
||||||
uri.equals("/js/") ||
|
uri.equals("/js/") ||
|
||||||
uri.equals("/images/") ||
|
uri.equals("/images/")
|
||||||
uri.equals("/health.do")
|
|
||||||
|
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,6 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import java.io.IOException;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
public class MainController {
|
public class MainController {
|
||||||
@@ -90,12 +88,5 @@ public class MainController {
|
|||||||
}
|
}
|
||||||
return startPage;
|
return startPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequestMapping(value = "/health.do", method = RequestMethod.GET)
|
|
||||||
public void health(HttpServletResponse response) throws IOException {
|
|
||||||
response.setStatus(HttpServletResponse.SC_OK);
|
|
||||||
response.setContentType("text/plain;charset=UTF-8");
|
|
||||||
response.getWriter().write("OK");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
<security:http pattern="/js/**" security="none"/>
|
<security:http pattern="/js/**" security="none"/>
|
||||||
<security:http pattern="/resource/**" security="none"/>
|
<security:http pattern="/resource/**" security="none"/>
|
||||||
<security:http pattern="\A/WEB-INF/jsp/.*\Z" request-matcher="regex" security="none"/>
|
<security:http pattern="\A/WEB-INF/jsp/.*\Z" request-matcher="regex" security="none"/>
|
||||||
<security:http pattern="/health.do" security="none"/>
|
|
||||||
|
|
||||||
<egov-security:config id="securityConfig"
|
<egov-security:config id="securityConfig"
|
||||||
loginUrl="/login.do"
|
loginUrl="/login.do"
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -17,7 +17,6 @@
|
|||||||
<script src="js/common/login.js"></script>
|
<script src="js/common/login.js"></script>
|
||||||
<base target="_self" />
|
<base target="_self" />
|
||||||
<title><%=MainGlobals.SITE_TITLE%></title>
|
<title><%=MainGlobals.SITE_TITLE%></title>
|
||||||
<link rel="icon" type="image/x-icon" href="${pageContext.request.contextPath}/Favicon.ico?v=20251209" />
|
|
||||||
<style>
|
<style>
|
||||||
.login_wrap_body{ background:url(${pageContext.request.contextPath}/images/admin/login_bg.gif) repeat left top; font-family:"맑은 고딕",Malgun Gothic,AppleGothic,sans-serif,"돋움", Dotum; }
|
.login_wrap_body{ background:url(${pageContext.request.contextPath}/images/admin/login_bg.gif) repeat left top; font-family:"맑은 고딕",Malgun Gothic,AppleGothic,sans-serif,"돋움", Dotum; }
|
||||||
.login_wrap{display:block; height:100%; left:0; position:fixed; top:0; width:100%; z-index:10000;}
|
.login_wrap{display:block; height:100%; left:0; position:fixed; top:0; width:100%; z-index:10000;}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
<meta name="keywords" content="" />
|
<meta name="keywords" content="" />
|
||||||
<base target="_self" />
|
<base target="_self" />
|
||||||
<title><%=MainGlobals.SITE_TITLE%></title>
|
<title><%=MainGlobals.SITE_TITLE%></title>
|
||||||
<link rel="icon" type="image/x-icon" href="${pageContext.request.contextPath}/Favicon.ico?v=20251209" />
|
|
||||||
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
|
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
|
||||||
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
|
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
|
||||||
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>
|
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ if(UserHelper.isAuthenticated()) {
|
|||||||
<meta name="keywords" content="" />
|
<meta name="keywords" content="" />
|
||||||
<base target="_self" />
|
<base target="_self" />
|
||||||
<title><%=MainGlobals.SITE_TITLE%></title>
|
<title><%=MainGlobals.SITE_TITLE%></title>
|
||||||
<link rel="icon" type="image/x-icon" href="${pageContext.request.contextPath}/Favicon.ico?v=20251209" />
|
|
||||||
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
|
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
|
||||||
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
|
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
|
||||||
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>
|
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ if(UserHelper.isAuthenticated()) {
|
|||||||
<meta name="keywords" content="" />
|
<meta name="keywords" content="" />
|
||||||
<base target="_self" />
|
<base target="_self" />
|
||||||
<title><%=MainGlobals.SITE_TITLE%></title>
|
<title><%=MainGlobals.SITE_TITLE%></title>
|
||||||
<link rel="icon" type="image/x-icon" href="${pageContext.request.contextPath}/Favicon.ico?v=20251209" />
|
|
||||||
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
|
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
|
||||||
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
|
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
|
||||||
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>
|
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ if(UserHelper.isAuthenticated()) {
|
|||||||
<meta name="keywords" content="" />
|
<meta name="keywords" content="" />
|
||||||
<base target="_self" />
|
<base target="_self" />
|
||||||
<title><%=MainGlobals.SITE_TITLE%></title>
|
<title><%=MainGlobals.SITE_TITLE%></title>
|
||||||
<link rel="icon" type="image/x-icon" href="${pageContext.request.contextPath}/Favicon.ico?v=20251209" />
|
|
||||||
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
|
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
|
||||||
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
|
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
|
||||||
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>
|
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
<meta name="keywords" content="noframe" />
|
<meta name="keywords" content="noframe" />
|
||||||
<base target="_self" />
|
<base target="_self" />
|
||||||
<title><%=MainGlobals.SITE_TITLE%></title>
|
<title><%=MainGlobals.SITE_TITLE%></title>
|
||||||
<link rel="icon" type="image/x-icon" href="${pageContext.request.contextPath}/Favicon.ico?v=20251209" />
|
|
||||||
<script type="text/javascript">var G_CONTEXT_PATH = "${pageContext.request.contextPath}";</script>
|
<script type="text/javascript">var G_CONTEXT_PATH = "${pageContext.request.contextPath}";</script>
|
||||||
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
|
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
|
||||||
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>
|
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ if(UserHelper.isAuthenticated()) {
|
|||||||
<meta name="keywords" content="" />
|
<meta name="keywords" content="" />
|
||||||
<base target="_self" />
|
<base target="_self" />
|
||||||
<title><%=MainGlobals.SITE_TITLE%></title>
|
<title><%=MainGlobals.SITE_TITLE%></title>
|
||||||
<link rel="icon" type="image/x-icon" href="${pageContext.request.contextPath}/Favicon.ico?v=20251209" />
|
|
||||||
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
|
<script type="text/javascript">var G_CONTEXT_PATH = '${pageContext.request.contextPath}';</script>
|
||||||
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
|
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/engine.js"></script>
|
||||||
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>
|
<script type="text/javascript" src="${pageContext.request.contextPath}/dwr/util.js"></script>
|
||||||
|
|||||||
14
src/main/webapp/js/common/chart.js
Normal file
14
src/main/webapp/js/common/chart.js
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user