This commit is contained in:
mindol1004
2024-10-18 18:01:26 +09:00
parent 62e15760bf
commit ac844f4ca3
12 changed files with 71 additions and 36 deletions

View File

@@ -3,7 +3,7 @@
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layouts/signin-layout}" lang="ko" xml:lang="ko"> layout:decorate="~{layouts/signin-layout}" lang="ko" xml:lang="ko">
<head> <head>
<title>로그인 페이지</title> <title>Sign In</title>
</head> </head>
<body> <body>
<section layout:fragment="content"> <section layout:fragment="content">

View File

@@ -77,7 +77,7 @@ public class QuartzConfig {
factory.setDataSource(dataSource); factory.setDataSource(dataSource);
factory.setTransactionManager(transactionManager); factory.setTransactionManager(transactionManager);
factory.setJobFactory(jobFactory); factory.setJobFactory(jobFactory);
factory.setAutoStartup(false); factory.setAutoStartup(true);
factory.setWaitForJobsToCompleteOnShutdown(true); factory.setWaitForJobsToCompleteOnShutdown(true);
return factory; return factory;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -13,18 +13,18 @@ const scheduleService = {
}, },
pauseJob: async (groupName, jobName) => { pauseJob: async (groupName, jobName) => {
const response = await apiClient.get(`/api/schedule/pause/${groupName}/${jobName}`); await apiClient.get(`/api/schedule/pause/${groupName}/${jobName}`);
return response.data.data; return true;
}, },
resumeJob: async (groupName, jobName) => { resumeJob: async (groupName, jobName) => {
const response = await apiClient.get(`/api/schedule/resume/${groupName}/${jobName}`); await apiClient.get(`/api/schedule/resume/${groupName}/${jobName}`);
return response.data.data; return true;
}, },
triggerJob: async (groupName, jobName) => { triggerJob: async (groupName, jobName) => {
const response = await apiClient.get(`/api/schedule/trigger/${groupName}/${jobName}`); await apiClient.get(`/api/schedule/trigger/${groupName}/${jobName}`);
return response.data.data; return true;
}, },
rescheduleJob: async (jobGroup, jobName, cronExpression) => { rescheduleJob: async (jobGroup, jobName, cronExpression) => {

View File

@@ -6,6 +6,7 @@ let selectedMonth;
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
initMonthPicker(); initMonthPicker();
fetchDataAndRender(); fetchDataAndRender();
setupEventListeners();
}); });
const initMonthPicker = () => { const initMonthPicker = () => {
@@ -38,6 +39,12 @@ const fetchDataAndRender = async () => {
renderRecentJobsTable(recentJobs); renderRecentJobsTable(recentJobs);
}; };
const setupEventListeners = () => {
document.getElementById('refreshBtn').addEventListener('click', async (e) => {
fetchDataAndRender();
});
};
const chartOptions = { const chartOptions = {
responsive: true, responsive: true,
maintainAspectRatio: false, maintainAspectRatio: false,

View File

@@ -1,16 +1,17 @@
import signService from '../../apis/sign-api.js'; import signService from '../../apis/sign-api.js';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const signOutButton = document.getElementById('signOut'); setupEventListeners();
const toggleSidebar = document.getElementById('toggleSidebar'); });
signOutButton.addEventListener('click', (e) => { const setupEventListeners = () => {
document.getElementById('signOut').addEventListener('click', (e) => {
e.preventDefault(); e.preventDefault();
signService.signOut(); signService.signOut();
}); });
toggleSidebar.addEventListener('click', (e) => { document.getElementById('toggleSidebar').addEventListener('click', () => {
const body = document.body; const body = document.body;
body.classList.toggle("toggle-sidebar"); body.classList.toggle("toggle-sidebar");
}); });
}); };

View File

@@ -12,7 +12,12 @@ const setupEventListeners = () => {
e.preventDefault(); e.preventDefault();
fetchDataAndRender(); fetchDataAndRender();
}); });
document.getElementById('refreshJobBtn').addEventListener('click', refreshJobs); document.getElementById('refreshJobBtn').addEventListener('click', () => {
const confirmUpdate = confirm('스케줄 재적용 하시겠습니까?');
if (confirmUpdate) {
refreshJobs();
}
});
}; };
const fetchDataAndRender = async () => { const fetchDataAndRender = async () => {
@@ -99,16 +104,21 @@ const getStatusBadgeClass = (status) => {
const setupDetailModalEventListeners = (group, name) => { const setupDetailModalEventListeners = (group, name) => {
document.getElementById('pauseJobBtn').onclick = () => updateJobStatus(group, name, 'PAUSED', scheduleService.pauseJob); document.getElementById('pauseJobBtn').onclick = () => updateJobStatus(group, name, 'PAUSED', scheduleService.pauseJob);
document.getElementById('resumeJobBtn').onclick = () => updateJobStatus(group, name, 'NORMAL', scheduleService.resumeJob); document.getElementById('resumeJobBtn').onclick = () => updateJobStatus(group, name, 'NORMAL', scheduleService.resumeJob);
document.getElementById('updateCronBtn').onclick = () => updateCronExpression(group, name); document.getElementById('updateCronBtn').onclick = () => {
const confirmUpdate = confirm('스케줄을 수정하시겠습니까?');
if (confirmUpdate) {
updateCronExpression(group, name);
}
}
}; };
const updateCronExpression = async (group, name) => { const updateCronExpression = async (group, name) => {
const newCronExpression = document.getElementById('cronExpression').value; const newCronExpression = document.getElementById('cronExpression').value;
if (await scheduleService.rescheduleJob(group, name, newCronExpression)) { if (await scheduleService.rescheduleJob(group, name, newCronExpression)) {
alert('스케이 수정 되었습니다.'); alert('스케이 수정 되었습니다.');
fetchDataAndRender(); fetchDataAndRender();
} else { } else {
alert('스케 수정이 실패했습니다.'); alert('스케 수정이 실패했습니다.');
} }
}; };
@@ -128,7 +138,8 @@ const updateJobControlButtons = (status) => {
}; };
const updateJobStatus = async (group, name, newStatus, action) => { const updateJobStatus = async (group, name, newStatus, action) => {
if (await action(group, name)) { const result = await action(group, name);
if (result) {
const statusElement = document.querySelector('#scheduleDetailContent .badge'); const statusElement = document.querySelector('#scheduleDetailContent .badge');
statusElement.className = `badge ${getStatusBadgeClass(newStatus)}`; statusElement.className = `badge ${getStatusBadgeClass(newStatus)}`;
statusElement.textContent = newStatus; statusElement.textContent = newStatus;

View File

@@ -6,6 +6,7 @@ let users = [];
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
fetchDataAndRender(); fetchDataAndRender();
setupEventListeners(); setupEventListeners();
manageTooltips.init();
}); });
const setupEventListeners = () => { const setupEventListeners = () => {
@@ -77,6 +78,7 @@ const updateUser = async () => {
await userService.changeRoleApprove(getModifiedRows(users, updatedUsers, "id")); await userService.changeRoleApprove(getModifiedRows(users, updatedUsers, "id"));
alert('회원정보가 수정 되었습니다.'); alert('회원정보가 수정 되었습니다.');
manageTooltips.hideAll();
fetchDataAndRender(); fetchDataAndRender();
}; };
@@ -84,4 +86,15 @@ const deleteUser = async (id) => {
await userService.deleteUser(id); await userService.deleteUser(id);
alert('사용자가 삭제되었습니다.'); alert('사용자가 삭제되었습니다.');
fetchDataAndRender(); fetchDataAndRender();
};
const manageTooltips = {
init: () => {
document.querySelectorAll('[data-bs-toggle="tooltip"]')
.forEach(el => new bootstrap.Tooltip(el));
},
hideAll: () => {
const tooltip = bootstrap.Tooltip.getInstance('#updateUserBtn');
setTimeout(() => tooltip.hide(), 100);
}
}; };

View File

@@ -25,11 +25,14 @@
</div> </div>
<section class="section"> <section class="section">
<div class="row mb-4"> <div class="row mb-4">
<div class="col-md-4"> <div class="col-md-4 d-flex align-items-center">
<div class="input-group"> <div class="input-group me-2">
<span class="input-group-text"><i class="bi bi-calendar-month"></i></span> <span class="input-group-text"><i class="bi bi-calendar-month"></i></span>
<input type="month" id="monthPicker" class="form-control"> <input type="month" id="monthPicker" class="form-control">
</div> </div>
<button id="refreshBtn" class="btn btn-sm btn-outline-primary" title="재조회">
<i class="bi bi-arrow-clockwise"></i>
</button>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
@@ -86,10 +89,10 @@
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-people"></i> 그룹명</th> <th class="col-1 text-nowrap bg-light"><i class="bi bi-people"></i> 그룹명</th>
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-briefcase"></i> 잡 이름</th> <th class="col-1 text-nowrap bg-light"><i class="bi bi-briefcase"></i> 잡 이름</th>
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-calendar-event me-2"></i> 실행 시간</th> <th class="col-1 text-nowrap bg-light"><i class="bi bi-calendar-event me-2"></i> 실행 시간</th>
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-activity"></i> 상태</th> <th class="col-1 text-nowrap bg-light"><i class="bi bi-activity"></i> 상태</th>
</tr> </tr>
</thead> </thead>
<tbody id="recentJobsTable"> <tbody id="recentJobsTable">

View File

@@ -64,11 +64,11 @@
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-people"></i> 그룹</th> <th class="col-1 text-nowrap bg-light"><i class="bi bi-people"></i> 그룹</th>
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-briefcase"></i> 잡 이름</th> <th class="col-1 text-nowrap bg-light"><i class="bi bi-briefcase"></i> 잡 이름</th>
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-calendar-event"></i> 스케줄</th> <th class="col-1 text-nowrap bg-light"><i class="bi bi-calendar-event"></i> 스케줄</th>
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-activity"></i> 상태</th> <th class="col-1 text-nowrap bg-light"><i class="bi bi-activity"></i> 상태</th>
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-gear"></i> 액션</th> <th class="col-1 text-nowrap bg-light"><i class="bi bi-gear"></i> 액션</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -81,7 +81,7 @@
</div> </div>
</section> </section>
<div class="modal fade" id="scheduleDetailModal" tabindex="-1" aria-labelledby="scheduleDetailModalLabel" aria-hidden="true"> <div class="modal fade" id="scheduleDetailModal" tabindex="-1" aria-labelledby="scheduleDetailModalLabel" aria-hidden="true" data-bs-backdrop="static">
<div class="modal-dialog modal-dialog-scrollable modal-dialog-centered"> <div class="modal-dialog modal-dialog-scrollable modal-dialog-centered">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header bg-dark text-white"> <div class="modal-header bg-dark text-white">

View File

@@ -3,7 +3,7 @@
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layouts/signin-layout}" lang="ko" xml:lang="ko"> layout:decorate="~{layouts/signin-layout}" lang="ko" xml:lang="ko">
<head> <head>
<title>로그인 페이지</title> <title>Sign In</title>
</head> </head>
<body> <body>
<section layout:fragment="content"> <section layout:fragment="content">
@@ -13,8 +13,8 @@
<div class="card shadow-sm"> <div class="card shadow-sm">
<div class="card-body p-5"> <div class="card-body p-5">
<div class="text-center mb-4"> <div class="text-center mb-4">
<i class="bi bi-person-circle text-primary" style="font-size: 3rem;"></i> <i class="bi bi-person-bounding-box text-primary" style="font-size: 4rem;"></i>
<h2 class="card-title mt-3">Sign in to NXCUS-Agent</h2> <h2 class="card-title mt-3" style="font-weight: bold;">Sign in to NXCUS-Agent</h2>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<div class="input-group"> <div class="input-group">
@@ -52,7 +52,7 @@
</div> </div>
<!-- 회원가입 모달 --> <!-- 회원가입 모달 -->
<div class="modal fade" id="signupModal" tabindex="-1" aria-labelledby="signupModalLabel" aria-hidden="true"> <div class="modal fade" id="signupModal" tabindex="-1" aria-labelledby="signupModalLabel" aria-hidden="true" data-bs-backdrop="static">
<div class="modal-dialog modal-dialog-scrollable modal-dialog-centered"> <div class="modal-dialog modal-dialog-scrollable modal-dialog-centered">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header bg-dark text-white"> <div class="modal-header bg-dark text-white">
@@ -108,7 +108,7 @@
</div> </div>
<!-- 비밀번호 변경 모달 --> <!-- 비밀번호 변경 모달 -->
<div class="modal fade" id="changePasswordModal" tabindex="-1" aria-labelledby="changePasswordModalLabel" aria-hidden="true"> <div class="modal fade" id="changePasswordModal" tabindex="-1" aria-labelledby="changePasswordModalLabel" aria-hidden="true" data-bs-backdrop="static">
<div class="modal-dialog modal-dialog-centered"> <div class="modal-dialog modal-dialog-centered">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header bg-info text-white"> <div class="modal-header bg-info text-white">

View File

@@ -4,7 +4,7 @@
layout:decorate="~{layouts/layout}" layout:decorate="~{layouts/layout}"
layout:fragment="content" lang="ko" xml:lang="ko"> layout:fragment="content" lang="ko" xml:lang="ko">
<head> <head>
<title>사용자 관리</title> <title>User Management</title>
</head> </head>
<body> <body>
<main id="main" class="main"> <main id="main" class="main">