commit
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{layouts/signin-layout}" lang="ko" xml:lang="ko">
|
||||
<head>
|
||||
<title>로그인 페이지</title>
|
||||
<title>Sign In</title>
|
||||
</head>
|
||||
<body>
|
||||
<section layout:fragment="content">
|
||||
|
||||
@@ -77,7 +77,7 @@ public class QuartzConfig {
|
||||
factory.setDataSource(dataSource);
|
||||
factory.setTransactionManager(transactionManager);
|
||||
factory.setJobFactory(jobFactory);
|
||||
factory.setAutoStartup(false);
|
||||
factory.setAutoStartup(true);
|
||||
factory.setWaitForJobsToCompleteOnShutdown(true);
|
||||
return factory;
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 355 KiB After Width: | Height: | Size: 19 KiB |
@@ -13,18 +13,18 @@ const scheduleService = {
|
||||
},
|
||||
|
||||
pauseJob: async (groupName, jobName) => {
|
||||
const response = await apiClient.get(`/api/schedule/pause/${groupName}/${jobName}`);
|
||||
return response.data.data;
|
||||
await apiClient.get(`/api/schedule/pause/${groupName}/${jobName}`);
|
||||
return true;
|
||||
},
|
||||
|
||||
resumeJob: async (groupName, jobName) => {
|
||||
const response = await apiClient.get(`/api/schedule/resume/${groupName}/${jobName}`);
|
||||
return response.data.data;
|
||||
await apiClient.get(`/api/schedule/resume/${groupName}/${jobName}`);
|
||||
return true;
|
||||
},
|
||||
|
||||
triggerJob: async (groupName, jobName) => {
|
||||
const response = await apiClient.get(`/api/schedule/trigger/${groupName}/${jobName}`);
|
||||
return response.data.data;
|
||||
await apiClient.get(`/api/schedule/trigger/${groupName}/${jobName}`);
|
||||
return true;
|
||||
},
|
||||
|
||||
rescheduleJob: async (jobGroup, jobName, cronExpression) => {
|
||||
|
||||
@@ -6,6 +6,7 @@ let selectedMonth;
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initMonthPicker();
|
||||
fetchDataAndRender();
|
||||
setupEventListeners();
|
||||
});
|
||||
|
||||
const initMonthPicker = () => {
|
||||
@@ -38,6 +39,12 @@ const fetchDataAndRender = async () => {
|
||||
renderRecentJobsTable(recentJobs);
|
||||
};
|
||||
|
||||
const setupEventListeners = () => {
|
||||
document.getElementById('refreshBtn').addEventListener('click', async (e) => {
|
||||
fetchDataAndRender();
|
||||
});
|
||||
};
|
||||
|
||||
const chartOptions = {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import signService from '../../apis/sign-api.js';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const signOutButton = document.getElementById('signOut');
|
||||
const toggleSidebar = document.getElementById('toggleSidebar');
|
||||
setupEventListeners();
|
||||
});
|
||||
|
||||
signOutButton.addEventListener('click', (e) => {
|
||||
const setupEventListeners = () => {
|
||||
document.getElementById('signOut').addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
signService.signOut();
|
||||
});
|
||||
|
||||
toggleSidebar.addEventListener('click', (e) => {
|
||||
document.getElementById('toggleSidebar').addEventListener('click', () => {
|
||||
const body = document.body;
|
||||
body.classList.toggle("toggle-sidebar");
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -12,7 +12,12 @@ const setupEventListeners = () => {
|
||||
e.preventDefault();
|
||||
fetchDataAndRender();
|
||||
});
|
||||
document.getElementById('refreshJobBtn').addEventListener('click', refreshJobs);
|
||||
document.getElementById('refreshJobBtn').addEventListener('click', () => {
|
||||
const confirmUpdate = confirm('스케줄 재적용 하시겠습니까?');
|
||||
if (confirmUpdate) {
|
||||
refreshJobs();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const fetchDataAndRender = async () => {
|
||||
@@ -99,16 +104,21 @@ const getStatusBadgeClass = (status) => {
|
||||
const setupDetailModalEventListeners = (group, name) => {
|
||||
document.getElementById('pauseJobBtn').onclick = () => updateJobStatus(group, name, 'PAUSED', scheduleService.pauseJob);
|
||||
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 newCronExpression = document.getElementById('cronExpression').value;
|
||||
if (await scheduleService.rescheduleJob(group, name, newCronExpression)) {
|
||||
alert('스케쥴이 수정 되었습니다.');
|
||||
alert('스케줄이 수정 되었습니다.');
|
||||
fetchDataAndRender();
|
||||
} else {
|
||||
alert('스케쥴 수정이 실패했습니다.');
|
||||
alert('스케줄 수정이 실패했습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -128,7 +138,8 @@ const updateJobControlButtons = (status) => {
|
||||
};
|
||||
|
||||
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');
|
||||
statusElement.className = `badge ${getStatusBadgeClass(newStatus)}`;
|
||||
statusElement.textContent = newStatus;
|
||||
|
||||
@@ -6,6 +6,7 @@ let users = [];
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
fetchDataAndRender();
|
||||
setupEventListeners();
|
||||
manageTooltips.init();
|
||||
});
|
||||
|
||||
const setupEventListeners = () => {
|
||||
@@ -77,6 +78,7 @@ const updateUser = async () => {
|
||||
|
||||
await userService.changeRoleApprove(getModifiedRows(users, updatedUsers, "id"));
|
||||
alert('회원정보가 수정 되었습니다.');
|
||||
manageTooltips.hideAll();
|
||||
fetchDataAndRender();
|
||||
};
|
||||
|
||||
@@ -84,4 +86,15 @@ const deleteUser = async (id) => {
|
||||
await userService.deleteUser(id);
|
||||
alert('사용자가 삭제되었습니다.');
|
||||
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);
|
||||
}
|
||||
};
|
||||
@@ -25,11 +25,14 @@
|
||||
</div>
|
||||
<section class="section">
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-4">
|
||||
<div class="input-group">
|
||||
<div class="col-md-4 d-flex align-items-center">
|
||||
<div class="input-group me-2">
|
||||
<span class="input-group-text"><i class="bi bi-calendar-month"></i></span>
|
||||
<input type="month" id="monthPicker" class="form-control">
|
||||
</div>
|
||||
<button id="refreshBtn" class="btn btn-sm btn-outline-primary" title="재조회">
|
||||
<i class="bi bi-arrow-clockwise"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -86,10 +89,10 @@
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-1 text-nowrap sticky-top 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 sticky-top 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-people"></i> 그룹명</th>
|
||||
<th class="col-1 text-nowrap bg-light"><i class="bi bi-briefcase"></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 bg-light"><i class="bi bi-activity"></i> 상태</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="recentJobsTable">
|
||||
|
||||
@@ -64,11 +64,11 @@
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-1 text-nowrap sticky-top 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 sticky-top 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 sticky-top bg-light"><i class="bi bi-gear"></i> 액션</th>
|
||||
<th class="col-1 text-nowrap bg-light"><i class="bi bi-people"></i> 그룹</th>
|
||||
<th class="col-1 text-nowrap bg-light"><i class="bi bi-briefcase"></i> 잡 이름</th>
|
||||
<th class="col-1 text-nowrap bg-light"><i class="bi bi-calendar-event"></i> 스케줄</th>
|
||||
<th class="col-1 text-nowrap bg-light"><i class="bi bi-activity"></i> 상태</th>
|
||||
<th class="col-1 text-nowrap bg-light"><i class="bi bi-gear"></i> 액션</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -81,7 +81,7 @@
|
||||
</div>
|
||||
</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-content">
|
||||
<div class="modal-header bg-dark text-white">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{layouts/signin-layout}" lang="ko" xml:lang="ko">
|
||||
<head>
|
||||
<title>로그인 페이지</title>
|
||||
<title>Sign In</title>
|
||||
</head>
|
||||
<body>
|
||||
<section layout:fragment="content">
|
||||
@@ -13,8 +13,8 @@
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body p-5">
|
||||
<div class="text-center mb-4">
|
||||
<i class="bi bi-person-circle text-primary" style="font-size: 3rem;"></i>
|
||||
<h2 class="card-title mt-3">Sign in to NXCUS-Agent</h2>
|
||||
<i class="bi bi-person-bounding-box text-primary" style="font-size: 4rem;"></i>
|
||||
<h2 class="card-title mt-3" style="font-weight: bold;">Sign in to NXCUS-Agent</h2>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="input-group">
|
||||
@@ -52,7 +52,7 @@
|
||||
</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-content">
|
||||
<div class="modal-header bg-dark text-white">
|
||||
@@ -108,7 +108,7 @@
|
||||
</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-content">
|
||||
<div class="modal-header bg-info text-white">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
layout:decorate="~{layouts/layout}"
|
||||
layout:fragment="content" lang="ko" xml:lang="ko">
|
||||
<head>
|
||||
<title>사용자 관리</title>
|
||||
<title>User Management</title>
|
||||
</head>
|
||||
<body>
|
||||
<main id="main" class="main">
|
||||
|
||||
Reference in New Issue
Block a user